diff --git a/beam/cli.cpp b/beam/cli.cpp index 8dbbbfdf36..4189b06781 100644 --- a/beam/cli.cpp +++ b/beam/cli.cpp @@ -549,8 +549,6 @@ int main(int argc, char* argv[]) node.m_Cfg.m_Horizon.SetInfinite(); } - ByteBuffer bufRichParser; - if (vm.count(cli::CONTRACT_RICH_INFO)) { uint8_t nFlag = vm[cli::CONTRACT_RICH_INFO].as() ? @@ -560,26 +558,6 @@ int main(int argc, char* argv[]) node.m_Cfg.m_ProcessorParams.m_RichInfoFlags |= nFlag; } - if (vm.count(cli::CONTRACT_RICH_PARSER)) - { - auto sPath = vm[cli::CONTRACT_RICH_PARSER].as(); - if (!sPath.empty()) - { - std::FStream fs; - fs.Open(sPath.c_str(), true, true); - - bufRichParser.resize(static_cast(fs.get_Remaining())); - if (!bufRichParser.empty()) - fs.read(&bufRichParser.front(), bufRichParser.size()); - - bvm2::Processor::Compile(bufRichParser, bufRichParser, bvm2::Processor::Kind::Manager); - - node.m_Cfg.m_ProcessorParams.m_RichParser = bufRichParser; - } - - node.m_Cfg.m_ProcessorParams.m_RichInfoFlags |= NodeProcessor::StartParams::RichInfo::UpdShader; - } - node.m_Cfg.m_pExternalPOW = stratumServer.get(); node.Initialize(); diff --git a/bvm/Shaders/Explorer/Parser.cpp b/bvm/Shaders/Explorer/Parser.cpp deleted file mode 100644 index 69b0bb34b7..0000000000 --- a/bvm/Shaders/Explorer/Parser.cpp +++ /dev/null @@ -1,3507 +0,0 @@ -#include "../common.h" -#include "../app_common_impl.h" -#include "../upgradable/contract.h" -#include "../upgradable2/contract.h" -#include "../upgradable3/contract.h" -#include "../vault/contract.h" -#include "../vault_anon/contract.h" -#include "../faucet/contract.h" -#include "../faucet2/contract.h" -#include "../dao-core/contract.h" -#include "../gallery/contract.h" -#include "../nephrite/contract.h" -#include "../oracle2/contract.h" -#include "../dao-vault/contract.h" -#include "../bans/contract.h" -#include "../amm/contract.h" -#include "../dao-core/contract.h" -#include "../dao-core2/contract.h" -#include "../dao-accumulator/contract.h" -#include "../dao-vote/contract.h" -namespace Masternet { -#include "../dao-core-masternet/contract.h" -} -namespace Testnet { -#include "../dao-core-testnet/contract.h" -} -#include "../minter/contract.h" -#include "../blackhole/contract.h" -#include "../sidechain_pos/contract_l1.h" -#include "../sidechain_pos/contract_l2.h" -#include "../pbft/pbft_dpos.h" -#include "../pbft/pbft_stat.h" - -template -void DocAddTextLen(const char* szID, const void* szValue, uint32_t nLen) -{ - char szBuf[nMaxLen + 1]; - nLen = std::min(nLen, nMaxLen); - - Env::Memcpy(szBuf, szValue, nLen); - szBuf[nLen] = 0; - - Env::DocAddText(szID, szBuf); -} - -void DocSetType(const char* sz) -{ - Env::DocAddText("type", sz); -} - -void DocAddTableHeader(const char* sz) -{ - Env::DocGroup gr(""); - DocSetType("th"); - Env::DocAddText("value", sz); -} - -void DocAddAmount(const char* sz, Amount x) -{ - Env::DocGroup gr(sz); - DocSetType("amount"); - Env::DocAddNum("value", x); -} - -void DocAddAmountSigned(const char* sz, Amount val, bool bPos) -{ - Env::DocGroup gr(sz); - DocSetType("amount"); - - char szBuf[Utils::String::Decimal::DigitsMax::N + 2]; - szBuf[0] = bPos ? '+' : '-'; - Utils::String::Decimal::Print(szBuf + 1, val); - - Env::DocAddText("value", szBuf); -} - -void DocAddAmountSigned(const char* sz, int64_t x) -{ - if (x > 0) - DocAddAmountSigned(sz, x, true); - else - if (x < 0) - DocAddAmountSigned(sz, -x, false); - else - DocAddAmount(sz, 0); -} - -void DocAddHeight(const char* sz, Height h) -{ - Env::DocGroup gr(sz); - DocSetType("height"); - Env::DocAddNum("value", h); -} - -void DocAddHeight1(const char* sz, Height h) -{ - DocAddHeight(sz, h + 1); -} - -template -void DocAddMonoblob(const char* sz, const T& x) -{ - Env::DocGroup gr(sz); - DocSetType("blob"); - Env::DocAddBlob_T("value", x); -} - -void DocAddPk(const char* sz, const PubKey& pk) -{ - DocAddMonoblob(sz, pk); -} - - -void DocAddAmountBig(const char* sz, Amount valLo, Amount valHi) -{ - if (valHi) - { - MultiPrecision::UInt<4> val; - val.Set<2>(valHi); - val += MultiPrecision::UInt<2>(valLo); - - MultiPrecision::UInt<1> div1(1000000000ul); - - char szBuf[64]; // little extra - char* szPos = szBuf + _countof(szBuf) - 1; - szPos[0] = 0; - - while (true) - { - MultiPrecision::UInt<4> quot; - quot.SetDivResid(val, div1); - - szPos -= 9; - Utils::String::Decimal::PrintNoZTerm(szPos, val.get_Val<1>(), 9); - - if (quot.IsZero()) - break; - val = quot; - } - - while ('0' == *szPos) - szPos++; - - Env::DocGroup gr(sz); - DocSetType("amount"); - Env::DocAddText("value", szPos); - - } - else - DocAddAmount(sz, valLo); - -} - -void DocAddAid(const char* sz, AssetID aid) -{ - Env::DocGroup gr(sz); - DocSetType("aid"); - Env::DocAddNum("value", aid); -} - -void DocAddAidAmount(const char* sz, AssetID aid, Amount amount) -{ - Env::DocArray gr(sz); - DocAddAid("", aid); - DocAddAmount("", amount); -} - -void DocAddCid(const char* sz, const ContractID& cid) -{ - Env::DocGroup gr(sz); - DocSetType("cid"); - Env::DocAddBlob_T("value", cid); -} - -void DocAddFloat(const char* sz, MultiPrecision::Float x) -{ - char szBuf[MultiPrecision::Float::DecimalForm::s_LenScientificMax + 1]; - x.get_Decimal().PrintAuto(szBuf); - Env::DocAddText(sz, szBuf); -} - -void DocAddFloatDbg(const char* sz, MultiPrecision::Float x) -{ - // convenient for debugging, to try the exact values on host - char szBuf[Utils::String::Hex::DigitsMax::N + Utils::String::Decimal::DigitsMax::N + 10]; - Utils::String::Hex::Print(szBuf, x.m_Num, Utils::String::Hex::DigitsMax::N); - uint32_t n = Utils::String::Hex::DigitsMax::N; - szBuf[n++] = ' '; - - if (x.m_Order >= 0) - szBuf[n++] = '+'; - else - { - szBuf[n++] = '-'; - x.m_Order = -x.m_Order; - } - - n += Utils::String::Decimal::Print(szBuf + n, x.m_Order); - szBuf[n] = 0; - - Env::DocAddText(sz, szBuf); -} - -void DocAddPerc(const char* sz, MultiPrecision::Float x, uint32_t nDigsAfterDot = 3) -{ - MultiPrecision::Float::DecimalForm df; - df.Assign(x); - df.m_Order10 += 2; // to perc - - MultiPrecision::Float::DecimalForm::PrintOptions po; - po.m_DigitsAfterDot = nDigsAfterDot; - - // remove unnecessary extra precision - auto df2 = df; - int32_t nExtra = -(po.m_DigitsAfterDot + df2.m_Order10); - if (nExtra > 0) - { - // loose extra precision - if (df2.m_NumDigits > (uint32_t)nExtra) - df2.LimitPrecision(df2.m_NumDigits - nExtra); - else - { - // loose all, make it 0 - df2.m_Num = 0; - df2.m_Order10 = 0; - df2.m_NumDigits = 1; - } - } - - char szBuf[MultiPrecision::Float::DecimalForm::s_LenScientificMax + 1]; - if (df2.get_TextLenStd(po) < _countof(szBuf)) - df2.PrintStd(szBuf, po); - else - { - df.LimitPrecision(nDigsAfterDot + 2); - po.m_DigitsAfterDot = -1; - df.PrintScientific(szBuf, po); - } - - Env::DocAddText(sz, szBuf); -} - -void DocAddFixedPoint(const char* sz, uint64_t val, uint64_t one, uint32_t nDigsAfterDot) -{ - char szVal[Utils::String::Decimal::DigitsMax::N + 10]; - auto n1 = Utils::String::Decimal::Print(szVal, val / one); - - if (nDigsAfterDot) - { - szVal[n1++] = '.'; - - while (true) - { - val %= one; - val *= 10; - szVal[n1++] = Utils::String::Decimal::ToChar(val / one); - - if (!--nDigsAfterDot) - break; - } - - szVal[n1] = 0; - } - - Env::DocAddText(sz, szVal); -} - - -#define HandleContractsStd(macro) \ - macro(Vault, Vault::s_SID) \ - macro(VaultAnon, VaultAnon::s_SID) \ - macro(Faucet, Faucet::s_SID) \ - macro(Faucet2, Faucet2::s_SID) \ - macro(Minter, Minter::s_SID) \ - macro(BlackHole, BlackHole::s_SID) \ - macro(Bridge_L2, SidechainPos::L2::s_SID) \ - macro(PBFT_DPOS, PBFT_DPOS::s_SID) \ - macro(PBFT_STAT, PBFT_STAT::s_SID) \ - -#define HandleContractsVer(macro) \ - macro(Oracle2, Oracle2::s_pSID) \ - macro(Nephrite, Nephrite::s_pSID) \ - macro(DaoVault, DaoVault::s_pSID) \ - macro(Bans, NameService::s_pSID) \ - macro(DEX, Amm::s_pSID) \ - macro(DaoCore2, DaoCore2::s_pSID) \ - macro(DaoAccumulator, DaoAccumulator::s_pSID) \ - macro(DaoVote, DaoVote::s_pSID) \ - macro(Bridge_L1, SidechainPos::L1::s_pSID) \ - -#define HandleContractsWrappers(macro) \ - macro(Upgradable, Upgradable::s_SID) \ - macro(Upgradable2, Upgradable2::s_SID) \ - -#define HandleContractsWrapped(macro) \ - macro(DaoCore, DaoCore::s_SID) \ - macro(DaoCore_Masternet, Masternet::DaoCore::s_SID) \ - macro(DaoCore_Testnet, Testnet::DaoCore::s_SID) \ - macro(Gallery_0, Gallery::s_pSID[0]) \ - macro(Gallery_1, Gallery::s_pSID[1]) \ - macro(Gallery_2, Gallery::s_pSID[2]) \ - -struct ParserContext -{ - const ShaderID& m_Sid; - const ContractID& m_Cid; - uint32_t m_iMethod; - const void* m_pArg; - uint32_t m_nArg; - - bool m_Method = false; - bool m_State = false; - - template - const T* get_ArgsAs() const - { - return (m_nArg < sizeof(T)) ? nullptr : (const T*) m_pArg; - } - - ParserContext(const ShaderID& sid, const ContractID& cid) - :m_Sid(sid) - ,m_Cid(cid) - { - } - - static void OnName(const char* sz) - { - Env::DocAddText("kind", sz); - } - -#define VER_TXT " v" - - static void OnNameVer2(const char* sz, uint32_t iVer, char* szBuf, uint32_t nNameLen) - { - Env::Memcpy(szBuf, sz, nNameLen); - Env::Memcpy(szBuf + nNameLen, VER_TXT, sizeof(VER_TXT) - 1); - Utils::String::Decimal::Print(szBuf + nNameLen + _countof(VER_TXT) - 1, iVer); - - OnName(szBuf); - } - - template - static void OnNameVer(const char* sz, uint32_t iVer) - { - char szBuf[nNameLen + Utils::String::Decimal::DigitsMax::N + _countof(VER_TXT)]; - OnNameVer2(sz, iVer, szBuf, nNameLen); - } - - static void OnNameUpgradable(const char* sz, const ShaderID& sid) - { - Env::DocGroup gr("kind"); - if (sz) - Env::DocAddText("Wrapper", sz); - DocAddMonoblob("subtype", sid); - } - - void OnMethod(const char* sz) - { - assert(m_Method); - Env::DocAddText("method", sz); - } - - struct GroupArgs :public Env::DocGroup { - GroupArgs() :Env::DocGroup("params") {} - }; - - struct GroupDbg :public Env::DocGroup { - GroupDbg() :Env::DocGroup("dbg") {} - }; - -#define THE_MACRO(name, sid) \ - void OnMethod_##name(); \ - void OnState_##name(); - HandleContractsStd(THE_MACRO) - HandleContractsWrapped(THE_MACRO) -#undef THE_MACRO - -#define THE_MACRO(name, psid) \ - void OnMethod_##name(uint32_t iVer); \ - void OnState_##name(uint32_t iVer); - HandleContractsVer(THE_MACRO) -#undef THE_MACRO - -#define THE_MACRO(name, sid) void On_##name(); - HandleContractsWrappers(THE_MACRO) -#undef THE_MACRO - -#define THE_MACRO(name, sid) \ - void On_##name() \ - { \ - OnName(#name); \ - if (m_Method) \ - OnMethod_##name(); \ - if (m_State) \ - { \ - Env::DocGroup gr("State"); \ - OnState_##name(); \ - } \ - } - - HandleContractsStd(THE_MACRO) -#undef THE_MACRO - -#define THE_MACRO(name, psid) \ - void On_##name(uint32_t iVer) \ - { \ - OnNameVer<_countof(#name) - 1>(#name, iVer); \ - if (m_Method) \ - OnMethod_##name(iVer); \ - if (m_State) \ - { \ - Env::DocGroup gr("State"); \ - OnState_##name(iVer); \ - } \ - } - - HandleContractsVer(THE_MACRO) -#undef THE_MACRO - -#define THE_MACRO(name, sid) \ - void On_##name() \ - { \ - OnName("Impl-" #name); \ - if (m_Method) \ - OnMethod_##name(); \ - } - - HandleContractsWrapped(THE_MACRO) -#undef THE_MACRO - - bool Parse(); - - struct Wrapped - { - enum Enum { -#define THE_MACRO(name, sid) name, - HandleContractsWrapped(THE_MACRO) -#undef THE_MACRO - count - }; - - static Enum Recognize(const ShaderID&); - }; - - void get_WrappedState(Wrapped::Enum); - - static void WriteUpgradeParams(const Upgradable::Next&); - static void WriteUpgradeParams(const Upgradable2::Next&); - void WriteUpgradeParams(const Upgradable3::NextVersion&, uint32_t nSizeShader); - static void WriteUpgradeParams(const ContractID&, Height); - void WriteUpgradeParams(Height, const ShaderID&); - static void WriteUpgradeSettings(const Upgradable2::Settings&); - static void WriteUpgradeSettings(const Upgradable3::Settings&); - static void WriteUpgradeSettingsInternal(const Upgradable3::Settings&); - void WriteUpgrade3State(); - void OnUpgrade3Method(); - static void WriteUpgradeAdminsMask(uint32_t nApproveMask); - static void WriteNephriteSettings(const Nephrite::Settings&); - void DumpNephriteDbgStatus(); - static void WriteSposSettings(const SidechainPos::L1::Settings&); - static void WriteSposValidators(const SidechainPos::L1::Validator*, uint32_t); - void OnSposBridgeOp(const SidechainPos::L1::Method::BridgeOp&); - static void WriteOracle2Settings(const Oracle2::Settings&); - static bool get_Oracle2Median(MultiPrecision::Float&, const ContractID& cid); - static void WriteBansSettings(const NameService::Settings&); - static void WriteMinterSettings(const Minter::Settings&); - template - void DocSetBansName_T(const T& x) { - DocSetBansNameEx(&x + 1, x.m_NameLen); - } - void DocSetBansNameEx(const void* p, uint32_t nLen); - - static void WriteAmmSettings(const Amm::Settings&); - static void DocSetAmmPool(const Amm::Pool::ID&); - static const char* get_AmmKind(const Amm::Pool::ID&); - - void AddNephiriteTroveNumber(const Nephrite::Method::BaseTxTrove*); - - static void WriteDaoVoteCfg(const DaoVote::Cfg&); - - template - struct NephriteEpochStorage - { - const ContractID& m_Cid; - NephriteEpochStorage(const ContractID& cid) :m_Cid(cid) {} - - template - void Load(uint32_t iEpoch, HomogenousPool::Epoch& e) - { - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract.m_Tag = nTag; - k.m_KeyInContract.m_iEpoch = iEpoch; - - Env::Halt_if(!Env::VarReader::Read_T(k, e)); - } - - template - void Save(uint32_t iEpoch, const HomogenousPool::Epoch& e) { - } - void Del(uint32_t iEpoch) { - } - }; - - - void OnDaoAccumulator_UserWithdraw(uint8_t nType); - void OnState_DaoAccumulator_Pool(DaoAccumulator::Pool&, const char* szName); - void OnState_DaoAccumulator_Users(DaoAccumulator::Pool&, uint8_t type, const char* szName); - - void On_PBFT_Settings(const PBFT_DPOS::Settings&); - void On_PBFT_ValidatorAddr(const PBFT_DPOS::Address&); - void On_PBFT_DelegatorAddr(const PubKey&); - void On_PBFT_Status(const char*, I_PBFT::State::Validator::Status); - void On_PBFT_Commission(uint16_t, bool bIsTbl = false); - -}; - -bool ParserContext::Parse() -{ - if (m_Method) - { - switch (m_iMethod) - { - case 0: - OnMethod("Create"); - break; - - case 1: - OnMethod("Destroy"); - } - } - -#define THE_MACRO(name, sid) \ - if (_POD_(m_Sid) == sid) \ - { \ - On_##name(); \ - return true; \ - } - - HandleContractsStd(THE_MACRO) - HandleContractsWrappers(THE_MACRO) - HandleContractsWrapped(THE_MACRO) -#undef THE_MACRO - -#define THE_MACRO(name, psid) \ - for (uint32_t i = 0; i < _countof(psid); i++) \ - if (_POD_(m_Sid) == psid[i]) \ - { \ - On_##name(i); \ - return true; \ - } - - HandleContractsVer(THE_MACRO) -#undef THE_MACRO - - return false; -} - -ParserContext::Wrapped::Enum ParserContext::Wrapped::Recognize(const ShaderID& sidArg) -{ -#define THE_MACRO(name, sid) \ - if (_POD_(sidArg) == sid) \ - { \ - OnName(#name); \ - return Wrapped::name; \ - } - - HandleContractsWrapped(THE_MACRO) -#undef THE_MACRO - - return Wrapped::count; -} - -void ParserContext::get_WrappedState(Wrapped::Enum e) -{ - switch (e) - { -#define THE_MACRO(name, sid) \ - case Wrapped::name: \ - OnState_##name(); \ - return; - - HandleContractsWrapped(THE_MACRO) -#undef THE_MACRO - - default: - return; // suppress warning - } -} - - -void ParserContext::On_Upgradable() -{ - // Get state, discover which cid actually operates the contract - Upgradable::State us; - - if (m_Method && !m_iMethod) - { - // c'tor, the state doesn't exist yet. Initial cid should be in the args - auto pArg = get_ArgsAs(); - if (!pArg) - return; - - _POD_(Cast::Down(us)) = *pArg; - _POD_(Cast::Down(us)).SetZero(); - - GroupArgs gr; - DocAddPk("owner", us.m_Pk); - } - else - { - Env::Key_T uk; - _POD_(uk.m_Prefix.m_Cid) = m_Cid; - uk.m_KeyInContract = Upgradable::State::s_Key; - - if (!Env::VarReader::Read_T(uk, us)) - return; - } - - ShaderID sid; - if (!Utils::Shader::get_Sid_FromContract(sid, us.m_Cid)) - return; - - auto eType = Wrapped::Recognize(sid); - if (Wrapped::count == eType) - OnNameUpgradable("upgradable", sid); - - if (m_State) - { - Env::DocGroup gr("State"); - - get_WrappedState(eType); - - { - Env::DocGroup gr("upgradable"); - DocAddPk("owner", us.m_Pk); - WriteUpgradeParams(us); - } - - } - - if (m_Method) - { - switch (m_iMethod) - { - case Upgradable::ScheduleUpgrade::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (!pArg) - return; // don't care of partial result - - OnMethod("Schedule upgrade"); - - GroupArgs gr; - WriteUpgradeParams(*pArg); - } - break; - - default: - OnMethod("Passthrough"); - } - } -} - -void ParserContext::On_Upgradable2() -{ - // Get state, discover which cid actually operates the contract - - Upgradable2::State us; - Upgradable2::Settings stg; - if (m_Method && !m_iMethod) - { - // c'tor, the state doesn't exist yet. Initial cid should be in the args - auto pArg = get_ArgsAs(); - if (!pArg) - return; - - _POD_(us.m_Active) = pArg->m_Active; - _POD_(us.m_Next).SetZero(); - _POD_(stg) = pArg->m_Settings; - - GroupArgs gr; - WriteUpgradeSettings(stg); - } - else - { - Env::Key_T uk; - _POD_(uk.m_Prefix.m_Cid) = m_Cid; - uk.m_KeyInContract = Upgradable2::State::s_Key; - - if (!Env::VarReader::Read_T(uk, us)) - return; - - uk.m_KeyInContract = Upgradable2::Settings::s_Key; - if (!Env::VarReader::Read_T(uk, stg)) - return; - } - - ShaderID sid; - if (!Utils::Shader::get_Sid_FromContract(sid, us.m_Active.m_Cid)) - return; - - auto eType = Wrapped::Recognize(sid); - if (Wrapped::count == eType) - OnNameUpgradable("upgradable2", sid); - - if (m_State) - { - Env::DocGroup gr("State"); - - get_WrappedState(eType); - - { - Env::DocGroup gr("upgradable2"); - WriteUpgradeSettings(stg); - WriteUpgradeParams(us.m_Next); - } - - } - - if (m_Method) - { - if (Upgradable2::Control::s_iMethod != m_iMethod) - { - OnMethod("Passthrough"); - return; - } - - auto pCtl = get_ArgsAs(); - if (!pCtl) - return; // don't care of partial result - - switch (pCtl->m_Type) - { - case Upgradable2::Control::ExplicitUpgrade::s_Type: - OnMethod("explicit upgrade"); - break; - - case Upgradable2::Control::ScheduleUpgrade::s_Type: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Schedule upgrade"); - - GroupArgs gr; - - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - WriteUpgradeParams(pArg->m_Next); - } - } - break; - - case Upgradable2::Control::ReplaceAdmin::s_Type: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("replace admin"); - - GroupArgs gr; - - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - - Env::DocAddNum("iAdmin", pArg->m_iAdmin); - DocAddPk("pk", pArg->m_Pk); - } - } - break; - - case Upgradable2::Control::SetApprovers::s_Type: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("set min approvers"); - - GroupArgs gr; - - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - - Env::DocAddNum("num", pArg->m_NewVal); - } - } - break; - } - } -} - -void ParserContext::WriteUpgradeParams(const Upgradable::Next& us) -{ - WriteUpgradeParams(us.m_cidNext, us.m_hNextActivate); -} - -void ParserContext::WriteUpgradeParams(const Upgradable2::Next& us) -{ - WriteUpgradeParams(us.m_Cid, us.m_hTarget); -} - -void ParserContext::WriteUpgradeAdminsMask(uint32_t nApproveMask) -{ - //const uint32_t nDigs = Utils::String::Hex::DigitsMax::N; - //char szBuf[nDigs + 1]; - //Utils::String::Hex::Print(szBuf, nApproveMask, nDigs); - - //Env::DocAddText("approve-mask", szBuf); - - Env::DocArray gr("Approvers"); - - for (uint32_t i = 0; i < (sizeof(nApproveMask) << 3); i++) - { - uint32_t msk = 1u << i; - if (!(nApproveMask & msk)) - continue; - - Env::DocAddNum("", i); - } -} - -void ParserContext::WriteUpgradeParams(const ContractID& cid, Height h) -{ - if (!_POD_(cid).IsZero()) - { - ShaderID sid; - if (!Utils::Shader::get_Sid_FromContract(sid, cid)) - return; - - ParserContext pc2(sid, sid); // use sid as dummy cid. It won't be used anyway - pc2.WriteUpgradeParams(h, sid); - } -} - -void ParserContext::WriteUpgradeParams(Height h, const ShaderID& sid) -{ - Env::DocGroup gr("Next upgrade"); - - DocAddHeight("Height", h); - - ParserContext pc2(sid, m_Cid); - if (!pc2.Parse()) - pc2.OnNameUpgradable(nullptr, sid); -} - -void ParserContext::WriteUpgradeParams(const Upgradable3::NextVersion& x, uint32_t nSizeShader) -{ - ShaderID sid; - Utils::Shader::get_Sid(sid, &x + 1, nSizeShader); - - WriteUpgradeParams(x.m_hTarget, sid); -} - -void ParserContext::WriteUpgradeSettings(const Upgradable2::Settings& stg) -{ - WriteUpgradeSettingsInternal(Cast::Reinterpret(stg)); -} - -void ParserContext::WriteUpgradeSettings(const Upgradable3::Settings& stg) -{ - Env::DocGroup gr("Upgradable3"); - WriteUpgradeSettingsInternal(stg); -} - -void ParserContext::WriteUpgradeSettingsInternal(const Upgradable3::Settings& stg) -{ - Env::DocAddNum("Delay", stg.m_hMinUpgradeDelay); - Env::DocAddNum("Min approvers", stg.m_MinApprovers); - - { - Env::DocGroup gr1("Admins"); - DocSetType("table"); - Env::DocArray gr2("value"); - - { - Env::DocArray gr3(""); - DocAddTableHeader("Index"); - DocAddTableHeader("Key"); - } - - for (uint32_t i = 0; i < _countof(stg.m_pAdmin); i++) - { - const auto& pk = stg.m_pAdmin[i]; - if (_POD_(pk).IsZero()) - continue; - - Env::DocArray gr3(""); - - Env::DocAddNum("", i); - DocAddPk("", pk); - } - - } -} - -void ParserContext::WriteUpgrade3State() -{ - Env::DocGroup gr("Upgradable3"); - - { - Env::Key_T sk; - _POD_(sk.m_Prefix.m_Cid) = m_Cid; - - Upgradable3::Settings stg; - if (Env::VarReader::Read_T(sk, stg)) - { - Env::DocGroup gr1("Settings"); - WriteUpgradeSettingsInternal(stg); - } - } - - { - Env::Key_T vk; - _POD_(vk.m_Prefix.m_Cid) = m_Cid; - - Env::VarReader r(vk, vk); - uint32_t nKey = 0, nVal = 0; - if (r.MoveNext(nullptr, nKey, nullptr, nVal, 0) && (nVal >= sizeof(Upgradable3::NextVersion))) - { - auto* pVal = (Upgradable3::NextVersion*) Env::Heap_Alloc(nVal); - - nKey = 0; - r.MoveNext(nullptr, nKey, pVal, nVal, 1); - - Env::DocGroup gr1("Schedule upgrade"); - - WriteUpgradeParams(*pVal, nVal - sizeof(Upgradable3::NextVersion)); - - Env::Heap_Free(pVal); - } - } -} - -void ParserContext::OnUpgrade3Method() -{ - using namespace Upgradable3; - - assert(m_Method == (Method::Control::s_iMethod == m_iMethod)); - - auto pCtl = get_ArgsAs(); - if (!pCtl) - return; - - switch (pCtl->m_Type) - { - case Method::Control::ExplicitUpgrade::s_Type: - OnMethod("explicit upgrade"); - break; - - case Method::Control::OnUpgraded::s_Type: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("On Upgraded"); - GroupArgs gr; - - Env::DocAddNum("Prev version", pArg->m_PrevVersion); - } - } - break; - - case Method::Control::ScheduleUpgrade::s_Type: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Schedule upgrade"); - GroupArgs gr; - - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - - if (pArg->m_SizeShader <= m_nArg - sizeof(*pArg)) - WriteUpgradeParams(pArg->m_Next, pArg->m_SizeShader); - } - } - break; - - case Method::Control::ReplaceAdmin::s_Type: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("replace admin"); - GroupArgs gr; - - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - - Env::DocAddNum("iAdmin", pArg->m_iAdmin); - DocAddPk("pk", pArg->m_Pk); - } - } - break; - - case Method::Control::SetApprovers::s_Type: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("set min approvers"); - GroupArgs gr; - - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - Env::DocAddNum("num", pArg->m_NewVal); - } - } - break; - } - -} - -void ParserContext::OnMethod_Vault() -{ - switch (m_iMethod) - { - case Vault::Deposit::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Deposit"); - GroupArgs gr; - DocAddPk("User", pArg->m_Account); - } - } - break; - - case Vault::Withdraw::s_iMethod: - OnMethod("Withdraw"); - // no need to include the account, it's visible in the sigs list - break; - } -} - -void ParserContext::OnState_Vault() -{ -} - -void ParserContext::OnMethod_VaultAnon() -{ - switch (m_iMethod) - { - case VaultAnon::Method::Deposit::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Deposit"); - GroupArgs gr; - - DocAddPk("User", pArg->m_Key.m_pkOwner); - } - } - break; - - case VaultAnon::Method::Withdraw::s_iMethod: - OnMethod("Withdraw"); - // no need to include the account, it's visible in the sigs list - break; - } -} - -void ParserContext::OnState_PBFT_DPOS() -{ - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = PBFT_DPOS::State::Tag::s_Global; - - PBFT_DPOS::State::Global g; - if (!Env::VarReader::Read_T(k, g)) - return; - - g.FlushRewardPending(); - - const Amount nProbeOnePercent = 100000000; - - PBFT_DPOS::State::Global g2; - _POD_(g2) = g; - g2.m_RewardPending = nProbeOnePercent * 100; - g2.FlushRewardPending(); - - struct ValidatorPlus - { - PBFT_DPOS::State::ValidatorPlus m_Validador; - PBFT_DPOS::Address m_Address; - - bool HasVotingPower() const { - return m_Validador.m_Status < I_PBFT::State::Validator::Status::Suspended; - } - - void operator = (const ValidatorPlus& x) { - _POD_(*this) = x; - } - - bool operator < (const ValidatorPlus& x) const { - // 1. stake. The more - the better - if (m_Validador.m_Weight > x.m_Validador.m_Weight) - return true; - if (m_Validador.m_Weight < x.m_Validador.m_Weight) - return false; - - // 2. status. The less - the better - if (m_Validador.m_Status < x.m_Validador.m_Status) - return true; - if (m_Validador.m_Status > x.m_Validador.m_Status) - return false; - - // 3. Address - return _POD_(m_Address).Cmp(x.m_Address) < 0; - } - }; - - Utils::Vector vVals; - Amount totalStake = 0; - uint64_t totalPower = 0; - //uint32_t nCountWithPower = 0; - - { - Env::Key_T vk0, vk1; - _POD_(vk0.m_Prefix.m_Cid) = m_Cid; - _POD_(vk1.m_Prefix.m_Cid) = m_Cid; - _POD_(vk0.m_KeyInContract.m_Address).SetZero(); - _POD_(vk1.m_KeyInContract.m_Address).SetObject(0xff); - - for (Env::VarReader r(vk0, vk1); ; ) - { - auto& x = vVals.emplace_back(); - if (!r.MoveNext_T(vk0, x.m_Validador)) - { - vVals.m_Count--; - break; - } - - _POD_(x.m_Address) = vk0.m_KeyInContract.m_Address; - totalStake += x.m_Validador.m_Weight; - - if (x.HasVotingPower()) - { - totalPower += x.m_Validador.m_Weight; - //nCountWithPower++; - } - } - } - - { - Env::DocGroup gr("Settings"); - On_PBFT_Settings(g.m_Settings); - } - - DocAddAmount("Total stake", totalStake); - - vVals.Prepare(vVals.m_Count * 2); - auto* pVals = MergeSort::Do(vVals.m_p, vVals.m_p + vVals.m_Count, vVals.m_Count); - -/* - { - Env::DocGroup gr2("Validators"); - - DocSetType("table"); - Env::DocArray gr3("value"); - - { - Env::DocArray gr4(""); - DocAddTableHeader("Address"); - DocAddTableHeader("Status"); - DocAddTableHeader("Stake"); - DocAddTableHeader("Voting Power %"); - DocAddTableHeader("Commission"); - } - - for (uint32_t i = 0; i < vVals.m_Count; i++) - { - auto& x = pVals[i]; - Env::DocArray gr5(""); - - DocAddMonoblob("", x.m_Address); - On_PBFT_Status("", x.m_Validador.m_Status); - DocAddAmount("", x.m_Validador.m_Weight); - - if (x.HasVotingPower()) - DocAddFixedPoint("", x.m_Validador.m_Weight * 100, totalPower, 4); - else - Env::DocAddNum32("", 0); - - On_PBFT_Commission(x.m_Validador.m_Commission_cpc, true); - } - - } -*/ - - { - Env::DocGroup gr2("Validators/Delegators"); - - DocSetType("table"); - Env::DocArray gr3("value"); - - { - Env::DocArray gr4(""); - DocAddTableHeader("Validator"); - DocAddTableHeader("Delegator"); - DocAddTableHeader("Status"); - DocAddTableHeader("Commission"); - DocAddTableHeader("Voting Power %"); - DocAddTableHeader("Stake"); - DocAddTableHeader("Reward Pending"); - DocAddTableHeader("Reward %"); - } - - Env::Key_T dk0, dk1; - _POD_(dk0.m_Prefix.m_Cid) = m_Cid; - _POD_(dk1.m_Prefix.m_Cid) = m_Cid; - - for (uint32_t iV = 0; iV < vVals.m_Count; iV++) - { - auto& x = pVals[iV]; - auto& vp = x.m_Validador; - - PBFT_DPOS::State::ValidatorPlus vp2; - _POD_(vp2) = vp; - vp2.FlushRewardPending(g2); - vp.FlushRewardPending(g); - - _POD_(dk0.m_KeyInContract.m_Validator) = x.m_Address; - _POD_(dk0.m_KeyInContract.m_Delegator) = vp.m_Self.m_Delegator; - - auto weight = x.HasVotingPower() ? vp.m_Weight : 0; - - // self delegator - PBFT_DPOS::State::Delegator dp, dp2; - Amount dpStake = 0; - - bool bFoundSelf = Env::VarReader::Read_T(dk0, dp); - if (bFoundSelf) - { - _POD_(dp2) = dp; - dp2.Pop(vp2, g2); - dp2.m_RewardRemaining += vp2.m_Self.m_Commission; - - dpStake = dp.Pop(vp, g); - dp.m_RewardRemaining += vp.m_Self.m_Commission; - } - else - { - _POD_(dp).SetZero(); - _POD_(dp2).SetZero(); - } - - { - Env::DocArray gr4(""); - - DocAddMonoblob("", x.m_Address); - DocAddMonoblob("", vp.m_Self.m_Delegator); - - On_PBFT_Status("", vp.m_Status); - On_PBFT_Commission(vp.m_Commission_cpc, true); - - DocAddFixedPoint("", weight * 100, totalPower, 4); - - DocAddAmount("", dpStake); - DocAddAmount("", dp.m_RewardRemaining); - DocAddFixedPoint("", dp2.m_RewardRemaining - dp.m_RewardRemaining, nProbeOnePercent, 4); - } - - // other delegators - _POD_(dk1.m_KeyInContract.m_Validator) = x.m_Address; - - _POD_(dk0.m_KeyInContract.m_Delegator).SetZero(); - _POD_(dk1.m_KeyInContract.m_Delegator).SetObject(0xff); - - for (Env::VarReader r2(dk0, dk1); ; ) - { - if (!r2.MoveNext_T(dk0, dp)) - break; - - if (_POD_(vp.m_Self.m_Delegator) == dk0.m_KeyInContract.m_Delegator) - continue; // already handled - - _POD_(dp2) = dp; - dp2.Pop(vp2, g2); - - dpStake = dp.Pop(vp, g); - - Env::DocArray gr4(""); - Env::DocAddText("", ""); - DocAddMonoblob("", dk0.m_KeyInContract.m_Delegator); - Env::DocAddText("", ""); - Env::DocAddText("", ""); - Env::DocAddText("", ""); - DocAddAmount("", dpStake); - DocAddAmount("", dp.m_RewardRemaining); - DocAddFixedPoint("", dp2.m_RewardRemaining - dp.m_RewardRemaining, nProbeOnePercent, 4); - } - - } - - } -} - -void ParserContext::OnMethod_PBFT_DPOS() -{ - switch (m_iMethod) - { - case PBFT_DPOS::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - On_PBFT_Settings(pArg->m_Settings); - } - } - break; - - case PBFT_DPOS::Method::ValidatorStatusUpdate::s_iMethod: - OnMethod("ValidatorStatusUpdate"); - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - On_PBFT_ValidatorAddr(pArg->m_Address); - On_PBFT_Status("Status", pArg->m_Status); - } - } - break; - - case PBFT_DPOS::Method::AddReward::s_iMethod: - OnMethod("AddReward"); - break; - - case PBFT_DPOS::Method::DelegatorUpdate::s_iMethod: - OnMethod("DelegatorUpdate"); - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - DocAddMonoblob("Delegator", pArg->m_Delegator); - - if (pArg->m_RewardClaim || pArg->m_StakeBond) - { - DocAddMonoblob("Validator", pArg->m_Validator); - DocAddAmountSigned("Bond_change", pArg->m_StakeBond); - } - } - } - break; - - case PBFT_DPOS::Method::ValidatorRegister::s_iMethod: - OnMethod("ValidatorRegister"); - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - On_PBFT_ValidatorAddr(pArg->m_Validator); - On_PBFT_DelegatorAddr(pArg->m_Delegator); - DocAddAmountSigned("Stake", pArg->m_Stake, true); - On_PBFT_Commission(pArg->m_Commission_cpc); - } - } - break; - - case PBFT_DPOS::Method::ValidatorUpdate::s_iMethod: - OnMethod("ValidatorUpdate"); - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - On_PBFT_ValidatorAddr(pArg->m_Validator); - if (PBFT_DPOS::State::ValidatorPlus::s_CommissionTagTomb == pArg->m_Commission_cpc) - Env::DocAddText("Action", "Tomb"); - else - On_PBFT_Commission(pArg->m_Commission_cpc); - } - } - break; - } -} - -void ParserContext::On_PBFT_Settings(const PBFT_DPOS::Settings& stg) -{ - DocAddAid("Stake-Aid", stg.m_aidStake); - Env::DocAddNum("Unbond lock", stg.m_hUnbondLock); - DocAddAmount("Min stake", stg.m_MinValidatorStake); -} - -void ParserContext::On_PBFT_ValidatorAddr(const PBFT_DPOS::Address& addr) -{ - DocAddMonoblob("Address", addr); -} - -void ParserContext::On_PBFT_DelegatorAddr(const PubKey& addr) -{ - DocAddMonoblob("Delegator", addr); -} - -void ParserContext::On_PBFT_Status(const char* szName, I_PBFT::State::Validator::Status status) -{ - const char* szStatus = nullptr; - switch (status) - { - case I_PBFT::State::Validator::Status::Active: szStatus = "Active"; break; - case I_PBFT::State::Validator::Status::Jailed: szStatus = "Jailed"; break; - case I_PBFT::State::Validator::Status::Suspended: szStatus = "Suspended"; break; - case I_PBFT::State::Validator::Status::Tombed: szStatus = "Tombed"; break; - case I_PBFT::State::Validator::Status::Slash: szStatus = "Slash"; break; - - default: - Env::DocAddNum(szName, static_cast(status)); - return; - } - - Env::DocAddText(szName, szStatus); -} - -void ParserContext::On_PBFT_Commission(uint16_t commission_cpc, bool bIsTbl /* = false */) -{ - DocAddFixedPoint(bIsTbl ? "" : "Commission", commission_cpc, 100, 2); -} - -void ParserContext::OnState_PBFT_STAT() -{ - { - Env::DocGroup gr2("Validators"); - - DocSetType("table"); - Env::DocArray gr3("value"); - - { - Env::DocArray gr4(""); - DocAddTableHeader("Validator"); - DocAddTableHeader("Status"); - DocAddTableHeader("Weight"); - } - - Env::Key_T vk0, vk1; - _POD_(vk0.m_Prefix.m_Cid) = m_Cid; - _POD_(vk1.m_Prefix.m_Cid) = m_Cid; - _POD_(vk0.m_KeyInContract.m_Address).SetZero(); - _POD_(vk1.m_KeyInContract.m_Address).SetObject(0xff); - - for (Env::VarReader r(vk0, vk1); ; ) - { - I_PBFT::State::Validator vp; - if (!r.MoveNext_T(vk0, vp)) - break; - - Env::DocArray gr4(""); - - DocAddMonoblob("", vk0.m_KeyInContract.m_Address); - On_PBFT_Status("", vp.m_Status); - - DocAddAmount("", vp.m_Weight); - } - - } -} - -void ParserContext::OnMethod_PBFT_STAT() -{ - switch (m_iMethod) - { - case I_PBFT::Method::ValidatorStatusUpdate::s_iMethod: - OnMethod("ValidatorStatusUpdate"); - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - On_PBFT_ValidatorAddr(pArg->m_Address); - On_PBFT_Status("Status", pArg->m_Status); - } - } - break; - - case PBFT_DPOS::Method::AddReward::s_iMethod: - OnMethod("AddReward"); - break; - } -} - -void ParserContext::OnState_VaultAnon() -{ -} - -void ParserContext::OnMethod_Faucet() -{ - switch (m_iMethod) - { - case 0: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - Env::DocAddNum("Backlog period", pArg->m_BacklogPeriod); - DocAddAmount("Max withdraw", pArg->m_MaxWithdraw); - } - } - break; - - case Faucet::Deposit::s_iMethod: OnMethod("deposit"); break; - case Faucet::Withdraw::s_iMethod: OnMethod("withdraw"); break; - } -} - -void ParserContext::OnState_Faucet() -{ -} - -void ParserContext::OnMethod_Faucet2() -{ - switch (m_iMethod) - { - case Faucet2::Method::Create::s_iMethod: - OnMethod("Create"); - break; - - case Faucet2::Method::Deposit::s_iMethod: - OnMethod("Deposit"); - break; - - case Faucet2::Method::Withdraw::s_iMethod: - OnMethod("Withdraw"); - break; - - case Faucet2::Method::AdminCtl::s_iMethod: - { - OnMethod("Admin-Ctl"); - - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - Env::DocAddNum32("Enable", pArg->m_Enable); - - } - } - break; - - case Faucet2::Method::AdminWithdraw::s_iMethod: - OnMethod("Admin-Withdraw"); - break; - } -} - -void ParserContext::OnState_Faucet2() -{ - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = Faucet2::State::s_Key; - - Faucet2::State s; - if (!Env::VarReader::Read_T(k, s)) - return; - - Env::DocAddNum("Enabled", (uint32_t) s.m_Enabled); - DocAddHeight1("Last withdraw", s.m_Epoch.m_Height); - DocAddAmount("Epoch withdraw remaining", s.m_Epoch.m_Amount); - - { - Env::DocGroup gr("Settings"); - - Env::DocAddNum("Epoch duration", s.m_Params.m_Limit.m_Height); - DocAddAmount("Epoch Withdraw limit", s.m_Params.m_Limit.m_Amount); - DocAddPk("Admin", s.m_Params.m_pkAdmin); - } -} - -void ParserContext::OnMethod_DaoCore() -{ - OnName("Dao-Core"); - - if (m_Method) - { - switch (m_iMethod) - { - case DaoCore::GetPreallocated::s_iMethod: OnMethod("Get Preallocated"); break; - case DaoCore::UpdPosFarming::s_iMethod: OnMethod("Farming Upd"); break; - - case DaoCore2::Method::AdminWithdraw::s_iMethod: - { - OnMethod("Admin Withdraw"); - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - } - } - break; - } - } -} - -void ParserContext::OnMethod_DaoCore_Masternet() { - OnMethod_DaoCore(); -} -void ParserContext::OnMethod_DaoCore_Testnet() { - OnMethod_DaoCore(); -} -void ParserContext::OnMethod_DaoCore2(uint32_t /* iVer */) { - OnMethod_DaoCore(); -} - - -void ParserContext::OnState_DaoCore() -{ -} - -void ParserContext::OnState_DaoCore_Masternet() { - OnState_DaoCore(); -} -void ParserContext::OnState_DaoCore_Testnet() { - OnState_DaoCore(); -} -void ParserContext::OnState_DaoCore2(uint32_t /* iVer */) { - OnState_DaoCore(); -} - -void WriteGalleryAdrID(Gallery::Masterpiece::ID id) -{ - Env::DocAddNum("art_id", Utils::FromBE(id)); -} - -void WriteGalleryPrice(const Gallery::AmountWithAsset& x) -{ - DocAddAidAmount("Price", x.m_Aid, x.m_Amount); -} - -void ParserContext::OnMethod_Gallery_0() -{ - On_Gallery_2(); // same, we only added methods -} - -void ParserContext::OnMethod_Gallery_1() -{ - On_Gallery_2(); -} - -void ParserContext::OnMethod_Gallery_2() -{ - switch (m_iMethod) - { - case Gallery::Method::AddExhibit::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("AddExhibit"); - GroupArgs gr; - - DocAddPk("pkUser", pArg->m_pkArtist); - Env::DocAddNum("size", pArg->m_Size); - } - } - break; - - case Gallery::Method::ManageArtist::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("ManageArtist"); - GroupArgs gr; - - DocAddPk("pkUser", pArg->m_pkArtist); - DocAddTextLen("name", pArg + 1, pArg->m_LabelLen); - } - } - break; - - - case Gallery::Method::SetPrice::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("SetPrice"); - GroupArgs gr; - - WriteGalleryAdrID(pArg->m_ID); - WriteGalleryPrice(pArg->m_Price); - } - } - break; - - case Gallery::Method::Buy::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Buy"); - GroupArgs gr; - - WriteGalleryAdrID(pArg->m_ID); - - DocAddPk("pkUser", pArg->m_pkUser); - Env::DocAddNum32("hasAid", pArg->m_HasAid); - DocAddAmount("payMax", pArg->m_PayMax); - } - } - break; - - case Gallery::Method::Transfer::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Transfer"); - GroupArgs gr; - - WriteGalleryAdrID(pArg->m_ID); - DocAddPk("newPkUser", pArg->m_pkNewOwner); - } - } - break; - - - case Gallery::Method::Withdraw::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Withdraw"); - GroupArgs gr; - - // TODO roman - DocAddPk("key", pArg->m_Key.m_pkUser); - DocAddAidAmount("Value", pArg->m_Key.m_Aid, pArg->m_Value); - } - } - break; - - case Gallery::Method::AddVoteRewards::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("AddVoteRewards"); - GroupArgs gr; - - DocAddAmount("amount", pArg->m_Amount); - } - } - break; - - case Gallery::Method::Vote::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Vote"); - GroupArgs gr; - - WriteGalleryAdrID(pArg->m_ID.m_MasterpieceID); - Env::DocAddNum("impression", pArg->m_Impression.m_Value); - } - } - break; - - case Gallery::Method::AdminDelete::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("AdminDelete"); - GroupArgs gr; - - WriteGalleryAdrID(pArg->m_ID); - } - } - break; - } -} - -void ParserContext::OnState_Gallery_0() -{ - OnState_Gallery_2(); -} -void ParserContext::OnState_Gallery_1() -{ - OnState_Gallery_2(); -} -void ParserContext::OnState_Gallery_2() -{ - OnState_Gallery_2(); -} - - -void ParserContext::WriteNephriteSettings(const Nephrite::Settings& stg) -{ - DocAddCid("oracle", stg.m_cidOracle1); - DocAddCid("oracle-backup", stg.m_cidOracle2); - DocAddCid("Dao-Vault", stg.m_cidDaoVault); - DocAddAmount("Liquidation Reserve", stg.m_TroveLiquidationReserve); - DocAddHeight("Min Redemption Height", stg.m_hMinRedemptionHeight); - DocAddAid("Gov Token", stg.m_AidGov); -} - -void ParserContext::AddNephiriteTroveNumber(const Nephrite::Method::BaseTxTrove* pArg) -{ - uint32_t iTrove; - - if (pArg && pArg->m_iPrev0) - { - Env::Key_T tk; - _POD_(tk.m_Prefix.m_Cid) = m_Cid; - tk.m_KeyInContract.m_iTrove = pArg->m_iPrev0; - - Nephrite::Trove t; - if (!Env::VarReader::Read_T(tk, t)) - return; - - iTrove = t.m_iNext; - } - else - { - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = Nephrite::Tags::s_State; - - Nephrite::Global g; - if (!Env::VarReader::Read_T(k, g)) - return; - - iTrove = pArg ? g.m_Troves.m_iHead : (g.m_Troves.m_iLastCreated + 1); - } - - Env::DocAddNum("Number", iTrove); -} - - -void ParserContext::OnMethod_Nephrite(uint32_t /* iVer */) -{ - switch (m_iMethod) - { - case Nephrite::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - WriteNephriteSettings(pArg->m_Settings); - WriteUpgradeSettings(pArg->m_Upgradable); - } - } - break; - - case Upgradable3::Method::Control::s_iMethod: - OnUpgrade3Method(); - break; - - case Nephrite::Method::TroveOpen::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Trove Open"); - GroupArgs gr; - - AddNephiriteTroveNumber(nullptr); - DocAddAmount("Col", pArg->m_Amounts.Col); - DocAddAmount("Tok", pArg->m_Amounts.Tok); - } - } - break; - - case Nephrite::Method::TroveClose::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Trove Close"); - GroupArgs gr; - AddNephiriteTroveNumber(pArg); - } - } - break; - - case Nephrite::Method::TroveModify::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Trove Modify"); - GroupArgs gr; - AddNephiriteTroveNumber(pArg); - DocAddAmount("Col", pArg->m_Amounts.Col); - DocAddAmount("Tok", pArg->m_Amounts.Tok); - } - } - break; - - case Nephrite::Method::FundsAccess::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Funds Access"); - GroupArgs gr; - } - } - break; - - case Nephrite::Method::UpdStabPool::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Stability Pool update"); - GroupArgs gr; - - DocAddAmount("New Amount", pArg->m_NewAmount); - } - } - break; - - case Nephrite::Method::Liquidate::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Liquidate troves"); - GroupArgs gr; - - Env::DocAddNum("Count", pArg->m_Count); - } - } - break; - - case Nephrite::Method::Redeem::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Redeem"); - GroupArgs gr; - - DocAddAmount("Amount", pArg->m_Amount); - } - } - break; - - case Nephrite::Method::AddStabPoolReward::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Add Stability Pool Reward"); - GroupArgs gr; - - DocAddAmount("Amount", pArg->m_Amount); - } - } - break; - } - - DumpNephriteDbgStatus(); -} - -void ParserContext::OnState_Nephrite(uint32_t /* iVer */) -{ - WriteUpgrade3State(); - - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = Nephrite::Tags::s_State; - - Nephrite::Global g; - if (!Env::VarReader::Read_T(k, g)) - return; - - { - Env::DocGroup gr2("Settings"); - WriteNephriteSettings(g.m_Settings); - } - - DocAddAid("Token", g.m_Aid); - Env::DocAddNum("Troves created", g.m_Troves.m_iLastCreated); - - { - Env::DocGroup gr2("Totals"); - DocAddAmount("Col", g.m_Troves.m_Totals.Col); - DocAddAmount("Tok", g.m_Troves.m_Totals.Tok); - } - - Nephrite::Global::Price price; - const char* szPriceSource; - bool bHavePrice = true; - - if (get_Oracle2Median(price.m_Value, g.m_Settings.m_cidOracle1) && price.IsSane(price.m_Value)) - szPriceSource = "Main Oracle"; - else - { - if (get_Oracle2Median(price.m_Value, g.m_Settings.m_cidOracle2) && price.IsSane(price.m_Value)) - szPriceSource = "Backup Oracle"; - else - { - szPriceSource = "Unavailable";; - bHavePrice = false; - } - } - - Env::DocAddText("Price feed", szPriceSource); - if (bHavePrice) - { - DocAddFloat("Price", price.m_Value); - - if (g.m_Troves.m_iHead) - { - DocAddPerc("TCR", price.ToCR(g.m_Troves.m_Totals.get_Rcr())); - Env::DocAddText("Recovery mode", g.IsRecovery(price) ? "Yes" : "No"); - } - } - - g.m_BaseRate.Decay(); - DocAddPerc("Fee boost", g.m_BaseRate.m_k); - - { - Env::DocGroup gr2("Troves"); - - DocSetType("table"); - Env::DocArray gr3("value"); - - { - Env::DocArray gr4(""); - DocAddTableHeader("Number"); - DocAddTableHeader("Key"); - DocAddTableHeader("Col"); - DocAddTableHeader("Tok"); - DocAddTableHeader("ICR"); - } - - Utils::Vector vec; - vec.Prepare(g.m_Troves.m_iLastCreated); - - { - Env::Key_T tk0, tk1; - _POD_(tk0.m_Prefix.m_Cid) = m_Cid; - _POD_(tk1.m_Prefix.m_Cid) = m_Cid; - tk0.m_KeyInContract.m_iTrove = 0; - tk1.m_KeyInContract.m_iTrove = (Nephrite::Trove::ID) -1; - - for (Env::VarReader r(tk0, tk1); ; ) - { - Nephrite::Trove t; - if (!r.MoveNext_T(tk0, t)) - break; - - vec.Prepare(tk0.m_KeyInContract.m_iTrove); - _POD_(vec.m_p[tk0.m_KeyInContract.m_iTrove - 1]) = t; - } - } - - for (auto iTrove = g.m_Troves.m_iHead; iTrove; ) - { - Nephrite::Trove& t = vec.m_p[iTrove - 1]; - - NephriteEpochStorage storR(m_Cid); - auto vals = g.m_RedistPool.get_UpdatedAmounts(t, storR); - - Env::DocArray gr4(""); - - Env::DocAddNum("", iTrove); - DocAddPk("", t.m_pkOwner); - DocAddAmount("", vals.Col); - DocAddAmount("", vals.Tok); - - if (bHavePrice) - DocAddPerc("", price.ToCR(t.m_Amounts.get_Rcr())); - else - Env::DocAddText("", ""); - - iTrove = t.m_iNext; - } - - } - - g.m_StabPool.AddReward(Env::get_Height()); - - { - Env::DocGroup gr2("Stability pool"); - - DocAddAmount("Tok", g.m_StabPool.get_TotalSell()); - DocAddAmount("Col", g.m_StabPool.m_Active.m_pDim[0].m_Buy + g.m_StabPool.m_Draining.m_pDim[0].m_Buy); - DocAddAmount("BeamX", g.m_StabPool.m_Active.m_pDim[1].m_Buy + g.m_StabPool.m_Draining.m_pDim[1].m_Buy); - } - - DocAddAmount("BeamX reward remaining", g.m_StabPool.m_Reward.m_Remaining); - - DumpNephriteDbgStatus(); -} - -void TestEqual(Amount a, Amount b, const char* szErr) -{ - // allow for little error - a = (a >= b) ? (a - b) : (b - a); - if (a > 10) - Env::DocAddNum(szErr, a); -} - -void ParserContext::DumpNephriteDbgStatus() -{ -/* - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = Nephrite::Tags::s_State; - - Nephrite::Global g; - if (!Env::VarReader::Read_T(k, g)) - return; - - GroupDbg gr0; - - { - Env::DocGroup gr1("Totals"); - Env::DocAddNum("Tok", g.m_Troves.m_Totals.Tok); - Env::DocAddNum("Col", g.m_Troves.m_Totals.Col); - } - - { - Env::DocGroup gr1("stab"); - Env::DocAddNum("Tok", g.m_StabPool.get_TotalSell()); - Env::DocAddNum("Col", g.m_StabPool.m_Active.m_pDim[0].m_Buy + g.m_StabPool.m_Active.m_pDim[1].m_Buy); - - } - - Nephrite::Pair trovesTotalsOrg, trovesTotalsAdj; - _POD_(trovesTotalsOrg).SetZero(); - _POD_(trovesTotalsAdj).SetZero(); - - MultiPrecision::Float weight(0u); - - { - Env::DocGroup gr1("troves"); - - Env::Key_T tk0, tk1; - _POD_(tk0.m_Prefix.m_Cid) = m_Cid; - _POD_(tk1.m_Prefix.m_Cid) = m_Cid; - tk0.m_KeyInContract.m_iTrove = 0; - tk1.m_KeyInContract.m_iTrove = (Nephrite::Trove::ID)-1; - - for (Env::VarReader r(tk0, tk1); ; ) - { - Nephrite::Trove t; - if (!r.MoveNext_T(tk0, t)) - break; - - char sz[Utils::String::Decimal::DigitsMax::N + 1]; - Utils::String::Decimal::Print(sz, tk0.m_KeyInContract.m_iTrove); - Env::DocGroup gr2(sz); - - { - Env::DocGroup gr2("org"); - Env::DocAddNum("Tok", t.m_Amounts.Tok); - Env::DocAddNum("Col", t.m_Amounts.Col); - } - - trovesTotalsOrg.Tok += t.m_Amounts.Tok; - trovesTotalsOrg.Col += t.m_Amounts.Col; - - auto vals = g.m_RedistPool.get_UpdatedAmounts(t); - - { - Env::DocGroup gr2("adj"); - Env::DocAddNum("Tok", vals.Tok); - Env::DocAddNum("Col", vals.Col); - } - - trovesTotalsAdj.Tok += vals.Tok; - trovesTotalsAdj.Col += vals.Col; - - DocAddFloatSc("weight", t.m_RedistUser.m_Weight); - DocAddFloatSc("Sigma", t.m_RedistUser.m_pSigma0[0]); - - weight += t.m_RedistUser.m_Weight; - - } - } - - { - Env::DocGroup gr1("redist"); - Env::DocAddNum("Tok", g.m_RedistPool.m_Active.m_Sell); - Env::DocAddNum("Col", g.m_RedistPool.m_Active.m_pDim[0].m_Buy); - DocAddFloatSc("Weight0", g.m_RedistPool.m_Active.m_Weight); - DocAddFloatSc("Weight1", weight); - DocAddFloatSc("Sigma", g.m_RedistPool.m_Active.m_pDim[0].m_Sigma); - } - - // Totals must be equal to the sum of effective (adjusted) trove amounts - TestEqual(g.m_Troves.m_Totals.Tok, trovesTotalsAdj.Tok, "errz-1-Tok"); - TestEqual(g.m_Troves.m_Totals.Col, trovesTotalsAdj.Col, "errz-1-Col"); - - // All troves must be part of redist pool - if (g.m_Troves.m_Totals.Tok != g.m_RedistPool.m_Active.m_Sell) - Env::DocAddText("errz-2", ""); - - // extra collateral in the redist pool must be equal to diff of ordinal vs adjusted trove values - TestEqual(g.m_RedistPool.m_Active.m_pDim[0].m_Buy, g.m_Troves.m_Totals.Col - trovesTotalsOrg.Col, "errz-3"); -*/ -} - -void ParserContext::WriteSposSettings(const SidechainPos::L1::Settings& stg) -{ - DocAddAid("Staking Token", stg.m_aidStaking); - DocAddAid("Liquidity Token", stg.m_aidLiquidity); - DocAddHeight("Per-phase End", stg.m_hPreEnd); -} - -void ParserContext::WriteSposValidators(const SidechainPos::L1::Validator* pV, uint32_t nV) -{ - Env::DocGroup gr1("Validators"); - DocSetType("table"); - Env::DocArray gr2("value"); - - { - Env::DocArray gr3(""); - DocAddTableHeader("Index"); - DocAddTableHeader("Key"); - } - - for (uint32_t i = 0; i < nV; i++) - { - const auto& v = pV[i]; - - Env::DocArray gr3(""); - Env::DocAddNum("", i); - DocAddPk("", v.m_pk); - } -} - -void ParserContext::OnMethod_Bridge_L1(uint32_t /* iVer */) -{ - switch (m_iMethod) - { - case SidechainPos::L1::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - WriteSposSettings(pArg->m_Settings); - WriteUpgradeSettings(pArg->m_Upgradable); - - if (m_nArg >= sizeof(*pArg) + sizeof(SidechainPos::L1::Validator) * pArg->m_Validators) - WriteSposValidators((const SidechainPos::L1::Validator*) (pArg + 1), pArg->m_Validators); - } - } - break; - - case Upgradable3::Method::Control::s_iMethod: - OnUpgrade3Method(); - break; - - case SidechainPos::L1::Method::UserStake::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("User stake"); - GroupArgs gr; - - DocAddAmount("Amount", pArg->m_Amount); - DocAddPk("Pk", pArg->m_pkUser); - } - } - break; - - case SidechainPos::L1::Method::BridgeExport::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Bridge Export"); - GroupArgs gr; - OnSposBridgeOp(*pArg); - } - } - break; - - case SidechainPos::L1::Method::BridgeImport::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Bridge Import"); - GroupArgs gr; - OnSposBridgeOp(*pArg); - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - } - } - break; - } - -} - -void ParserContext::OnSposBridgeOp(const SidechainPos::L1::Method::BridgeOp& op) -{ - DocAddAidAmount("Value", op.m_Aid, op.m_Amount); - DocAddMonoblob("cookie", op.m_Cookie); - DocAddPk("pk", op.m_pk); -} - -void ParserContext::OnState_Bridge_L1(uint32_t /* iVer */) -{ - WriteUpgrade3State(); - - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = SidechainPos::L1::Tags::s_State; - - SidechainPos::L1::State s; - if (!Env::VarReader::Read_T(k, s)) - return; - - { - Env::DocGroup gr2("Settings"); - WriteSposSettings(s.m_Settings); - } - - - { - k.m_KeyInContract = SidechainPos::L1::Tags::s_Validators; - Env::VarReader r(k, k); - - SidechainPos::L1::Validator pV[SidechainPos::L1::Validator::s_Max]; - uint32_t nKey = 0, nVal = sizeof(pV); - - if (r.MoveNext(nullptr, nKey, pV, nVal, 0) && (nVal >= sizeof(SidechainPos::L1::Validator)) && (nVal <= sizeof(pV))) - WriteSposValidators(pV, nVal / sizeof(SidechainPos::L1::Validator)); - - } -} - -void ParserContext::OnMethod_Bridge_L2() -{ - switch (m_iMethod) - { - case SidechainPos::L2::Method::BridgeEmit::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Mint"); - GroupArgs gr; - OnSposBridgeOp(*pArg); - } - } - break; - - case SidechainPos::L2::Method::BridgeBurn::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Burn"); - GroupArgs gr; - OnSposBridgeOp(*pArg); - } - } - break; - } - -} - - -void ParserContext::OnState_Bridge_L2() -{ - // no state -} - -void ParserContext::WriteOracle2Settings(const Oracle2::Settings& stg) -{ - Env::DocAddNum("Validity Period", stg.m_hValidity); - Env::DocAddNum("Min Providers", stg.m_MinProviders); -} - -bool ParserContext::get_Oracle2Median(MultiPrecision::Float& ret, const ContractID& cid) -{ - Env::Key_T key; - _POD_(key.m_Prefix.m_Cid) = cid; - key.m_KeyInContract = Oracle2::Tags::s_Median; - - Oracle2::Median med; - if (!Env::VarReader::Read_T(key, med)) - return false; - - if (med.m_hEnd < Env::get_Height()) - return false; - - ret = med.m_Res; - return true; -} - -void ParserContext::OnMethod_Oracle2(uint32_t /* iVer */) -{ - switch (m_iMethod) - { - case Oracle2::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - WriteOracle2Settings(pArg->m_Settings); - WriteUpgradeSettings(pArg->m_Upgradable); - } - } - break; - - case Oracle2::Method::Get::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Get"); - - GroupArgs gr; - - MultiPrecision::Float val; - if (get_Oracle2Median(val, m_Cid)) - DocAddFloat("Result", val); - else - Env::DocAddText("Result", "NaN"); - } - } - break; - - case Oracle2::Method::FeedData::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("FeedData"); - GroupArgs gr; - - Env::DocAddNum("iProvider", pArg->m_iProvider); - DocAddFloat("Value", pArg->m_Value); - } - } - break; - - case Oracle2::Method::SetSettings::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("SetSettings"); - GroupArgs gr; - - WriteOracle2Settings(pArg->m_Settings); - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - } - } - break; - - case Oracle2::Method::ProviderAdd::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("ProviderAdd"); - GroupArgs gr; - - DocAddPk("pk", pArg->m_pk); - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - } - } - break; - - case Oracle2::Method::ProviderDel::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("ProviderDel"); - GroupArgs gr; - - Env::DocAddNum("iProvider", pArg->m_iProvider); - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - } - } - break; - - } -} - -void ParserContext::OnState_Oracle2(uint32_t /* iVer */) -{ - Oracle2::StateMax g; - uint32_t nProvs = 0; - - Env::Key_T key; - _POD_(key.m_Prefix.m_Cid) = m_Cid; - key.m_KeyInContract = Oracle2::Tags::s_StateFull; - - { - Env::VarReader r(key, key); - uint32_t nKey = 0, nVal = sizeof(g); - if (!r.MoveNext(nullptr, nKey, &g, nVal, 0)) - return; - - nProvs = (nVal - sizeof(Oracle2::State0)) / sizeof(Oracle2::State0::Entry); // don't care about overflow - if (nProvs > g.s_ProvsMax) - return; - } - - { - Env::DocGroup gr1("Settings"); - - WriteUpgrade3State(); - WriteOracle2Settings(g.m_Settings); - } - - Height h = Env::get_Height(); - - { - Env::DocGroup gr1("Feeds"); - DocSetType("table"); - Env::DocArray gr2("value"); - - { - Env::DocArray gr3(""); - DocAddTableHeader("Index"); - DocAddTableHeader("Key"); - DocAddTableHeader("Last Value"); - DocAddTableHeader("Last Height"); - DocAddTableHeader("Comment"); - } - - Height h1 = (h > g.m_Settings.m_hValidity) ? (h - g.m_Settings.m_hValidity) : 0; - - for (uint32_t i = 0; i < nProvs; i++) - { - const auto& x = g.m_pE[i]; - if (_POD_(x.m_Pk).IsZero()) - continue; - - Env::DocArray gr3(""); - - Env::DocAddNum("", i); - DocAddPk("", x.m_Pk); - DocAddFloat("", x.m_Val); - DocAddHeight1("", x.m_hUpdated); - - Env::DocAddText("", (x.m_hUpdated > h1) ? "" : "outdated"); - - } - } - - { - key.m_KeyInContract = Oracle2::Tags::s_Median; - Oracle2::Median med; - if (Env::VarReader::Read_T(key, med)) - { - bool bValid = (med.m_hEnd >= h); - if (bValid) - DocAddFloat("Median", med.m_Res); - else - Env::DocAddText("Median", ""); - } - } -} - -void ParserContext::OnMethod_DaoVault(uint32_t /* iVer */) -{ - switch (m_iMethod) - { - case DaoVault::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - WriteUpgradeSettings(pArg->m_Upgradable); - } - } - break; - - case Upgradable3::Method::Control::s_iMethod: - OnUpgrade3Method(); - break; - - case DaoVault::Method::Deposit::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Deposit"); - //GroupArgs gr; - - //DocAddAidAmount("Value", pArg->m_Aid, pArg->m_Amount); - } - } - break; - - case DaoVault::Method::Withdraw::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Withdraw"); - //GroupArgs gr; - - //DocAddAidAmount("Value", pArg->m_Aid, pArg->m_Amount); - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - } - } - break; - } -} - -void ParserContext::OnState_DaoVault(uint32_t /* iVer */) -{ - WriteUpgrade3State(); -} - -void ParserContext::WriteBansSettings(const NameService::Settings& stg) -{ - DocAddCid("Price oracle", stg.m_cidOracle); - DocAddCid("Dao-Vault", stg.m_cidDaoVault); - DocAddCid("Anon-Vault", stg.m_cidVault); - DocAddHeight("Activation height", stg.m_h0); -} - -void ParserContext::DocSetBansNameEx(const void* p, uint32_t nLen) -{ - if (nLen > NameService::Domain::s_MaxLen) - return; - - uint32_t n0 = ((const uint8_t*) p) - ((const uint8_t*) m_pArg); - if (n0 + nLen > m_nArg) - return; - - char sz[NameService::Domain::s_MaxLen + 1]; - Env::Memcpy(sz, p, nLen); - sz[nLen] = 0; - - Env::DocAddText("name", sz); -} - -void ParserContext::OnMethod_Bans(uint32_t /* iVer */) -{ - switch (m_iMethod) - { - case NameService::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - WriteBansSettings(pArg->m_Settings); - WriteUpgradeSettings(pArg->m_Upgradable); - } - } - break; - - case Upgradable3::Method::Control::s_iMethod: - OnUpgrade3Method(); - break; - - case NameService::Method::SetOwner::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Set Owner"); - GroupArgs gr; - - DocSetBansName_T(*pArg); - DocAddPk("New owner", pArg->m_pkNewOwner); - } - } - break; - - case NameService::Method::Extend::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Extend period"); - GroupArgs gr; - - DocSetBansName_T(*pArg); - Env::DocAddNum32("Periods", pArg->m_Periods); - } - } - break; - - case NameService::Method::SetPrice::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod(pArg->m_Price.m_Amount ? "Set Price" : "Remove Price"); - GroupArgs gr; - - DocSetBansName_T(*pArg); - - if (pArg->m_Price.m_Amount) - DocAddAidAmount("Price", pArg->m_Price.m_Aid, pArg->m_Price.m_Amount); - } - } - break; - - case NameService::Method::Buy::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Buy"); - GroupArgs gr; - - DocSetBansName_T(*pArg); - DocAddPk("New owner", pArg->m_pkNewOwner); - - } - } - break; - - case NameService::Method::Register::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Register"); - GroupArgs gr; - - DocSetBansName_T(*pArg); - DocAddPk("Owner", pArg->m_pkOwner); - Env::DocAddNum32("Periods", pArg->m_Periods); - } - } - break; - - } -} - -void ParserContext::OnState_Bans(uint32_t /* iVer */) -{ - WriteUpgrade3State(); - - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = NameService::Tags::s_Settings; - - NameService::Settings s; - if (!Env::VarReader::Read_T(k, s)) - return; - - { - Env::DocGroup gr2("Settings"); - WriteBansSettings(s); - } - - { - Env::DocGroup gr2("Domains"); - DocSetType("table"); - Env::DocArray gr3("value"); - - { - Env::DocArray gr4(""); - DocAddTableHeader("Name"); - DocAddTableHeader("Owner"); - DocAddTableHeader("Expiration height"); - DocAddTableHeader("Status"); - DocAddTableHeader("Sell price"); - } - - Env::Key_T k0; - _POD_(k0.m_Prefix.m_Cid) = m_Cid; - _POD_(k0.m_KeyInContract.m_sz).SetZero(); - -#pragma pack (push, 1) - struct KeyPlus { - Env::Key_T k; - char m_chTerm; // 1 more byte, to place 0-terminator - } k1; -#pragma pack (pop) - - _POD_(k1.k.m_Prefix.m_Cid) = m_Cid; - Env::Memset(k1.k.m_KeyInContract.m_sz, 0xff, NameService::Domain::s_MaxLen); - - Height h = Env::get_Height(); - for (Env::VarReader r(k0, k1.k); ; ) - { - NameService::Domain d; - uint32_t nKey = sizeof(k1.k), nVal = sizeof(d); - if (!r.MoveNext(&k1.k, nKey, &d, nVal, 0)) - break; - - if (sizeof(d) != nVal) - continue; - - nKey -= (sizeof(k0) - NameService::Domain::s_MinLen); - if (nKey > NameService::Domain::s_MaxLen) - continue; - - k1.k.m_KeyInContract.m_sz[nKey] = 0; - - Env::DocArray gr4(""); - - Env::DocAddText("", k1.k.m_KeyInContract.m_sz); - DocAddPk("", d.m_pkOwner); - DocAddHeight("", d.m_hExpire); - - const char* szStatus = - (d.m_hExpire > h) ? "" : - (d.m_hExpire + NameService::Domain::s_PeriodHold > h) ? "On Hold" : - "Expired"; - Env::DocAddText("", szStatus); - - if (d.m_Price.m_Amount) - DocAddAidAmount("", d.m_Price.m_Aid, d.m_Price.m_Amount); - else - Env::DocAddText("", ""); - } - - } - -} - -void ParserContext::WriteMinterSettings(const Minter::Settings& stg) -{ - DocAddCid("Dao-Vault", stg.m_cidDaoVault); - DocAddAmount("Issuance fee", stg.m_IssueFee); -} - -void ParserContext::OnMethod_Minter() -{ - switch (m_iMethod) - { - case Minter::Method::Init::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - WriteMinterSettings(pArg->m_Settings); - } - } - break; - - case Minter::Method::View::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("View"); - GroupArgs gr; - - DocAddAid("aid", pArg->m_Aid); - } - } - break; - - case Minter::Method::CreateToken::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Create token"); - GroupArgs gr; - - DocAddAmountBig("Limit", pArg->m_Limit.m_Lo, pArg->m_Limit.m_Hi); - - if (Minter::PubKeyFlag::s_Cid == pArg->m_pkOwner.m_Y) - DocAddCid("Owner", pArg->m_pkOwner.m_X); - else - DocAddPk("Owner", pArg->m_pkOwner); - - // TODO - aid - } - } - break; - - case Minter::Method::Withdraw::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Withdraw"); - GroupArgs gr; - - DocAddAmount("amount", pArg->m_Value); - DocAddAid("aid", pArg->m_Aid); - } - } - break; - } -} - -void ParserContext::OnState_Minter() -{ - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = Minter::Tags::s_Settings; - - Minter::Settings s; - if (!Env::VarReader::Read_T(k, s)) - return; - - { - Env::DocGroup gr2("Settings"); - WriteMinterSettings(s); - } - - { - Env::DocGroup gr2("Tokens"); - DocSetType("table"); - Env::DocArray gr3("value"); - - { - Env::DocArray gr4(""); - DocAddTableHeader("Aid"); - DocAddTableHeader("Metadata"); - DocAddTableHeader("Owner"); - DocAddTableHeader("Minted"); - DocAddTableHeader("Limit"); - } - - Env::Key_T k0, k1; - _POD_(k0.m_Prefix.m_Cid) = m_Cid; - _POD_(k1.m_Prefix.m_Cid) = m_Cid; - k0.m_KeyInContract.m_Aid = 0; - k1.m_KeyInContract.m_Aid = (AssetID) -1; - - for (Env::VarReader r(k0, k1); ; ) - { - Minter::Token mt; - if (!r.MoveNext_T(k0, mt)) - break; - - Env::DocArray gr4(""); - - DocAddAid("", k0.m_KeyInContract.m_Aid); - - char szMetadata[1024 * 16 + 1]; // max metadata size is 16K - AssetInfo ai; - auto nMetadata = Env::get_AssetInfo(k0.m_KeyInContract.m_Aid, ai, szMetadata, sizeof(szMetadata) - 1); - szMetadata[nMetadata] = 0; - - Env::DocAddText("", szMetadata); - - if (Minter::PubKeyFlag::s_Cid & mt.m_pkOwner.m_Y) - DocAddCid("", mt.m_pkOwner.m_X); - else - DocAddMonoblob("", mt.m_pkOwner); - - - DocAddAmountBig("", mt.m_Minted.m_Lo, mt.m_Minted.m_Hi); - DocAddAmountBig("", mt.m_Limit.m_Lo, mt.m_Limit.m_Hi); - } - } -} - -void ParserContext::OnMethod_BlackHole() -{ - switch (m_iMethod) - { - case BlackHole::Method::Deposit::s_iMethod: - OnMethod("Deposit"); - break; - } -} - -void ParserContext::OnState_BlackHole() -{ -} - -void ParserContext::WriteAmmSettings(const Amm::Settings& stg) -{ - DocAddCid("Dao-Vault", stg.m_cidDaoVault); -} - -void ParserContext::DocSetAmmPool(const Amm::Pool::ID& pid) -{ - DocAddAid("Aid1", pid.m_Aid1); - DocAddAid("Aid2", pid.m_Aid2); - Env::DocAddText("Volatility", get_AmmKind(pid)); -} - -const char* ParserContext::get_AmmKind(const Amm::Pool::ID& pid) -{ - switch (pid.m_Fees.m_Kind) - { - case 0: return "Low"; - case 1: return "Medium"; - case 2: return "High"; - } - return ""; -} - - -void ParserContext::OnMethod_DEX(uint32_t /* iVer */) -{ - switch (m_iMethod) - { - case Amm::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - - WriteAmmSettings(pArg->m_Settings); - WriteUpgradeSettings(pArg->m_Upgradable); - } - } - break; - - case Upgradable3::Method::Control::s_iMethod: - OnUpgrade3Method(); - break; - - case Amm::Method::PoolCreate::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Pool Create"); - GroupArgs gr; - - DocSetAmmPool(pArg->m_Pid); - DocAddPk("Creator", pArg->m_pkCreator); - } - } - break; - - case Amm::Method::PoolDestroy::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Pool Destroy"); - GroupArgs gr; - DocSetAmmPool(pArg->m_Pid); - } - } - break; - - case Amm::Method::AddLiquidity::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Liquidity Add"); - GroupArgs gr; - DocSetAmmPool(pArg->m_Pid); - } - } - break; - - case Amm::Method::Withdraw::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Liquidity Withdraw"); - GroupArgs gr; - DocSetAmmPool(pArg->m_Pid); - } - } - break; - - case Amm::Method::Trade::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Trade"); - GroupArgs gr; - DocSetAmmPool(pArg->m_Pid); - } - } - break; - } -} - -void ParserContext::OnState_DEX(uint32_t /* iVer */) -{ - WriteUpgrade3State(); - - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = Amm::Tags::s_Settings; - - Amm::Settings s; - if (!Env::VarReader::Read_T(k, s)) - return; - - { - Env::DocGroup gr2("Settings"); - WriteAmmSettings(s); - } - - { - Env::DocGroup gr2("Pools"); - DocSetType("table"); - Env::DocArray gr3("value"); - - { - Env::DocArray gr4(""); - DocAddTableHeader("Aid1"); - DocAddTableHeader("Aid2"); - DocAddTableHeader("Volatility"); - DocAddTableHeader("LP-Token"); - DocAddTableHeader("Amount1"); - DocAddTableHeader("Amount2"); - DocAddTableHeader("Amount-LP-Token"); - DocAddTableHeader("Rate 1:2"); - DocAddTableHeader("Rate 2:2"); - } - - Env::Key_T k0, k1; - _POD_(k0.m_Prefix.m_Cid) = m_Cid; - _POD_(k1.m_Prefix.m_Cid) = m_Cid; - _POD_(k0.m_KeyInContract.m_ID).SetZero(); - _POD_(k1.m_KeyInContract.m_ID).SetObject(0xff); - - for (Env::VarReader r(k0, k1); ; ) - { - Amm::Pool p; - if (!r.MoveNext_T(k0, p)) - break; - - Env::DocArray gr4(""); - - DocAddAid("", k0.m_KeyInContract.m_ID.m_Aid1); - DocAddAid("", k0.m_KeyInContract.m_ID.m_Aid2); - Env::DocAddText("", get_AmmKind(k0.m_KeyInContract.m_ID)); - DocAddAid("", p.m_aidCtl); - DocAddAmount("", p.m_Totals.m_Tok1); - DocAddAmount("", p.m_Totals.m_Tok2); - DocAddAmount("", p.m_Totals.m_Ctl); - - if (p.m_Totals.m_Tok1 && p.m_Totals.m_Tok2) - { - char szBuf[MultiPrecision::Float::DecimalForm::s_LenScientificMax + 1]; - - MultiPrecision::Float f1(p.m_Totals.m_Tok1); - MultiPrecision::Float f2(p.m_Totals.m_Tok2); - - for (uint32_t i = 0; i < 2; i++) - { - auto k = i ? (f2 / f1) : (f1 / f2); - auto df = k.get_Decimal(); - - // print the ratio nicely. Limit to 8 precision digits, prefer std notation - const uint32_t nPrecision = 8; - df.LimitPrecision(nPrecision); - - MultiPrecision::Float::DecimalForm::PrintOptions po; - - if (df.get_TextLenStd(po) <= nPrecision + 2) - df.PrintStd(szBuf, po); - else - df.PrintScientific(szBuf, po); - - Env::DocAddText("", szBuf); - } - - } - else - { - Env::DocAddText("", ""); - Env::DocAddText("", ""); - } - } - - } - -} - -void OnDaoAccumulator_PoolType(uint8_t nType) -{ - static const char s_szName[] = "Pool"; - switch (nType) - { - case DaoAccumulator::Method::UserLock::Type::BeamX_PrePhase: - Env::DocAddText(s_szName, "Beam-BeamX pre-phase"); - break; - - case DaoAccumulator::Method::UserLock::Type::BeamX: - Env::DocAddText(s_szName, "Beam-BeamX"); - break; - - case DaoAccumulator::Method::UserLock::Type::Nph: - Env::DocAddText(s_szName, "Beam-Nph"); - break; - } -} - -void ParserContext::OnDaoAccumulator_UserWithdraw(uint8_t nType) -{ - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Withdraw"); - GroupArgs gr; - - OnDaoAccumulator_PoolType(nType); - - DocAddPk("pk", pArg->m_pkUser); - } -} - -void ParserContext::OnMethod_DaoAccumulator(uint32_t /* iVer */) -{ - switch (m_iMethod) - { - case DaoAccumulator::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - WriteUpgradeSettings(pArg->m_Upgradable); - DocAddAid("beamX", pArg->m_aidBeamX); - DocAddHeight("Per-phase end", pArg->m_hPrePhaseEnd); - } - } - break; - - case Upgradable3::Method::Control::s_iMethod: - OnUpgrade3Method(); - break; - - case DaoAccumulator::Method::FarmStart::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Farm Start"); - GroupArgs gr; - - WriteUpgradeAdminsMask(pArg->m_ApproveMask); - DocAddAid("LP-Token", pArg->m_aidLpToken); - DocAddAmount("Total Reward", pArg->m_FarmBeamX); - Env::DocAddNum("Total Duration", pArg->m_hFarmDuration); - - } - } - break; - - case DaoAccumulator::Method::UserLock::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Lock"); - GroupArgs gr; - OnDaoAccumulator_PoolType(pArg->m_PoolType); - DocAddPk("pk", pArg->m_pkUser); - DocAddHeight("hEnd", pArg->m_hEnd); - } - } - break; - - case DaoAccumulator::Method::UserWithdraw_FromBeamNph::s_iMethod: - OnDaoAccumulator_UserWithdraw(DaoAccumulator::Method::UserLock::Type::Nph); - break; - - case DaoAccumulator::Method::UserWithdraw_FromBeamBeamX::s_iMethod: - OnDaoAccumulator_UserWithdraw(DaoAccumulator::Method::UserLock::Type::BeamX); - break; - } -} - -void ParserContext::OnState_DaoAccumulator_Pool(DaoAccumulator::Pool& p, const char* szName) -{ - Env::DocGroup gr(szName); - - p.Update(Env::get_Height()); - - DocAddAmount("Reward remaining", p.m_AmountRemaining); - Env::DocAddNum("Farming duration remaining", p.m_hRemaining); -} - -void ParserContext::OnState_DaoAccumulator_Users(DaoAccumulator::Pool& p, uint8_t type, const char* szName) -{ - Env::DocGroup gr2(szName); - DocSetType("table"); - Env::DocArray gr3("value"); - - { - Env::DocArray gr4(""); - DocAddTableHeader("LP-Tokens"); - DocAddTableHeader("Locked until"); - DocAddTableHeader("Reward"); - DocAddTableHeader("Key"); - } - - Env::Key_T k0, k1; - k0.m_KeyInContract.m_Tag = type; - k1.m_KeyInContract.m_Tag = type; - _POD_(k0.m_Prefix.m_Cid) = m_Cid; - _POD_(k1.m_Prefix.m_Cid) = m_Cid; - _POD_(k0.m_KeyInContract.m_pk).SetZero(); - _POD_(k1.m_KeyInContract.m_pk).SetObject(0xff); - - for (Env::VarReader r(k0, k1); ; ) - { - DaoAccumulator::User u; - if (!r.MoveNext_T(k0, u)) - break; - - Env::DocArray gr4(""); - - DocAddAmount("", u.m_LpToken); - DocAddHeight("", u.m_hEnd); - - u.m_EarnedBeamX += p.Remove(u.m_PoolUser); - DocAddAmount("", u.m_EarnedBeamX); - - DocAddPk("", k0.m_KeyInContract.m_pk); - } -} - -void ParserContext::OnState_DaoAccumulator(uint32_t /* iVer */) -{ - WriteUpgrade3State(); - - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = DaoAccumulator::Tags::s_State; - - DaoAccumulator::State s; - if (!Env::VarReader::Read_T(k, s)) - return; - - DocAddAid("BeamX", s.m_aidBeamX); - DocAddHeight("Pre-phaseend height ", s.m_hPreEnd); - - if (s.m_aidLpToken) - { - DocAddAid("LP-token", s.m_aidLpToken); - - OnState_DaoAccumulator_Pool(s.m_Pool, "Pool Beam/BeamX"); - } - - DaoAccumulator::Pool p_Nph; - k.m_KeyInContract = DaoAccumulator::Tags::s_PoolBeamNph; - - if (Env::VarReader::Read_T(k, p_Nph)) - OnState_DaoAccumulator_Pool(p_Nph, "Pool Beam/Nph"); - else - _POD_(p_Nph).SetZero(); - - OnState_DaoAccumulator_Users(s.m_Pool, DaoAccumulator::Tags::s_User, "Beam/BeamX users"); - OnState_DaoAccumulator_Users(p_Nph, DaoAccumulator::Tags::s_UserBeamNph, "Beam/Nph users"); -} - - - - - -void ParserContext::OnMethod_DaoVote(uint32_t /* iVer */) -{ - switch (m_iMethod) - { - case DaoVote::Method::Create::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - GroupArgs gr; - WriteUpgradeSettings(pArg->m_Upgradable); - WriteDaoVoteCfg(pArg->m_Cfg); - } - } - break; - - case Upgradable3::Method::Control::s_iMethod: - OnUpgrade3Method(); - break; - - case DaoVote::Method::AddProposal::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Add proposal"); - GroupArgs gr; - - DocAddPk("moderator", pArg->m_pkModerator); - } - } - break; - - case DaoVote::Method::MoveFunds::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - OnMethod(pArg->m_Lock ? "Funds Lock" : "Funds Unlock"); - } - break; - - case DaoVote::Method::Vote::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Vote"); - } - } - break; - - case DaoVote::Method::AddDividend::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - OnMethod("Add dividend"); - } - break; - - case DaoVote::Method::GetResults::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - OnMethod("Get results"); - } - break; - - case DaoVote::Method::SetModerator::s_iMethod: - { - auto pArg = get_ArgsAs(); - if (pArg) - { - OnMethod("Set moderator"); - GroupArgs gr; - - DocAddPk("moderator", pArg->m_pk); - Env::DocAddNum32("Enable", pArg->m_Enable); - } - } - break; - } -} - -void ParserContext::OnState_DaoVote(uint32_t /* iVer */) -{ - WriteUpgrade3State(); - - Env::Key_T k; - _POD_(k.m_Prefix.m_Cid) = m_Cid; - k.m_KeyInContract = DaoVote::Tags::s_State; - - DaoVote::State s; - if (!Env::VarReader::Read_T(k, s)) - return; - - { - Env::DocGroup gr("Settings"); - WriteDaoVoteCfg(s.m_Cfg); - } - -} - -void ParserContext::WriteDaoVoteCfg(const DaoVote::Cfg& cfg) -{ - DocAddAid("Voting asset", cfg.m_Aid); - Env::DocAddNum("Epoch duration", cfg.m_hEpochDuration); - DocAddPk("Admin", cfg.m_pkAdmin); -} - - - -BEAM_EXPORT void Method_0(const ShaderID& sid, const ContractID& cid, uint32_t iMethod, const void* pArg, uint32_t nArg) -{ - Env::DocGroup gr(""); - - ParserContext pc(sid, cid); - pc.m_Method = true; - pc.m_iMethod = iMethod; - pc.m_pArg = pArg; - pc.m_nArg = nArg; - - pc.Parse(); -} - -BEAM_EXPORT void Method_1(const ShaderID& sid, const ContractID& cid) -{ - Env::DocGroup gr(""); - - ParserContext pc(sid, cid); - pc.Parse(); -} - -BEAM_EXPORT void Method_2(const ShaderID& sid, const ContractID& cid) -{ - Env::DocGroup gr(""); - - ParserContext pc(sid, cid); - //pc.m_Name = false; - pc.m_State = true; - pc.Parse(); -} diff --git a/bvm/Shaders/Explorer/Parser.wasm b/bvm/Shaders/Explorer/Parser.wasm deleted file mode 100644 index 4cfd23076c..0000000000 Binary files a/bvm/Shaders/Explorer/Parser.wasm and /dev/null differ diff --git a/bvm/Shaders/Explorer/modules/amm.parser.wasm b/bvm/Shaders/Explorer/modules/amm.parser.wasm new file mode 100755 index 0000000000..038b73e2d3 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/amm.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/bans.parser.wasm b/bvm/Shaders/Explorer/modules/bans.parser.wasm new file mode 100755 index 0000000000..cce3885b9e Binary files /dev/null and b/bvm/Shaders/Explorer/modules/bans.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/blackhole.parser.wasm b/bvm/Shaders/Explorer/modules/blackhole.parser.wasm new file mode 100755 index 0000000000..bfaf64b15d Binary files /dev/null and b/bvm/Shaders/Explorer/modules/blackhole.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/dao-accumulator.parser.wasm b/bvm/Shaders/Explorer/modules/dao-accumulator.parser.wasm new file mode 100755 index 0000000000..564f6fde0b Binary files /dev/null and b/bvm/Shaders/Explorer/modules/dao-accumulator.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/dao-core.parser.wasm b/bvm/Shaders/Explorer/modules/dao-core.parser.wasm new file mode 100755 index 0000000000..773b0535c0 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/dao-core.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/dao-core2.parser.wasm b/bvm/Shaders/Explorer/modules/dao-core2.parser.wasm new file mode 100755 index 0000000000..6d1d1ace91 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/dao-core2.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/dao-vault.parser.wasm b/bvm/Shaders/Explorer/modules/dao-vault.parser.wasm new file mode 100755 index 0000000000..fbf20f7275 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/dao-vault.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/dao-vote.parser.wasm b/bvm/Shaders/Explorer/modules/dao-vote.parser.wasm new file mode 100755 index 0000000000..c4ba83687d Binary files /dev/null and b/bvm/Shaders/Explorer/modules/dao-vote.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/faucet.parser.wasm b/bvm/Shaders/Explorer/modules/faucet.parser.wasm new file mode 100755 index 0000000000..f81ee119d1 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/faucet.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/faucet2.parser.wasm b/bvm/Shaders/Explorer/modules/faucet2.parser.wasm new file mode 100755 index 0000000000..004cc0033b Binary files /dev/null and b/bvm/Shaders/Explorer/modules/faucet2.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/gallery.parser.wasm b/bvm/Shaders/Explorer/modules/gallery.parser.wasm new file mode 100755 index 0000000000..737b3e9a73 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/gallery.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/minter.parser.wasm b/bvm/Shaders/Explorer/modules/minter.parser.wasm new file mode 100755 index 0000000000..7892f6a988 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/minter.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/nephrite.parser.wasm b/bvm/Shaders/Explorer/modules/nephrite.parser.wasm new file mode 100755 index 0000000000..90aaac2407 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/nephrite.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/oracle2.parser.wasm b/bvm/Shaders/Explorer/modules/oracle2.parser.wasm new file mode 100755 index 0000000000..6a0fa08610 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/oracle2.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/pbft.parser.wasm b/bvm/Shaders/Explorer/modules/pbft.parser.wasm new file mode 100755 index 0000000000..e4a7929d16 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/pbft.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/sidechain_pos.parser.wasm b/bvm/Shaders/Explorer/modules/sidechain_pos.parser.wasm new file mode 100755 index 0000000000..a05ba4173d Binary files /dev/null and b/bvm/Shaders/Explorer/modules/sidechain_pos.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/vault.parser.wasm b/bvm/Shaders/Explorer/modules/vault.parser.wasm new file mode 100755 index 0000000000..0fd20d83b5 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/vault.parser.wasm differ diff --git a/bvm/Shaders/Explorer/modules/vault_anon.parser.wasm b/bvm/Shaders/Explorer/modules/vault_anon.parser.wasm new file mode 100755 index 0000000000..57e41f7818 Binary files /dev/null and b/bvm/Shaders/Explorer/modules/vault_anon.parser.wasm differ diff --git a/bvm/Shaders/Explorer/parser_common.h b/bvm/Shaders/Explorer/parser_common.h new file mode 100644 index 0000000000..4be51ac1b1 --- /dev/null +++ b/bvm/Shaders/Explorer/parser_common.h @@ -0,0 +1,313 @@ +// Copyright 2018 The Beam Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "../common.h" +#include "../Float.h" +#include "../upgradable2/contract.h" +#include "../upgradable3/contract.h" + +template +inline void DocAddTextLen(const char* szID, const void* szValue, uint32_t nLen) +{ + char szBuf[nMaxLen + 1]; + nLen = std::min(nLen, nMaxLen); + + Env::Memcpy(szBuf, szValue, nLen); + szBuf[nLen] = 0; + + Env::DocAddText(szID, szBuf); +} + +inline void DocSetType(const char* sz) +{ + Env::DocAddText("type", sz); +} + +inline void DocAddTableHeader(const char* sz) +{ + Env::DocGroup gr(""); + DocSetType("th"); + Env::DocAddText("value", sz); +} + +inline void DocAddAmount(const char* sz, Amount x) +{ + Env::DocGroup gr(sz); + DocSetType("amount"); + Env::DocAddNum("value", x); +} + +inline void DocAddAmountSigned(const char* sz, Amount val, bool bPos) +{ + Env::DocGroup gr(sz); + DocSetType("amount"); + + char szBuf[Utils::String::Decimal::DigitsMax::N + 2]; + szBuf[0] = bPos ? '+' : '-'; + Utils::String::Decimal::Print(szBuf + 1, val); + + Env::DocAddText("value", szBuf); +} + +inline void DocAddAmountSigned(const char* sz, int64_t x) +{ + if (x > 0) + DocAddAmountSigned(sz, x, true); + else + if (x < 0) + DocAddAmountSigned(sz, -x, false); + else + DocAddAmount(sz, 0); +} + +inline void DocAddHeight(const char* sz, Height h) +{ + Env::DocGroup gr(sz); + DocSetType("height"); + Env::DocAddNum("value", h); +} + +inline void DocAddHeight1(const char* sz, Height h) +{ + DocAddHeight(sz, h + 1); +} + +template +inline void DocAddMonoblob(const char* sz, const T& x) +{ + Env::DocGroup gr(sz); + DocSetType("blob"); + Env::DocAddBlob_T("value", x); +} + +inline void DocAddPk(const char* sz, const PubKey& pk) +{ + DocAddMonoblob(sz, pk); +} + +inline void DocAddAmountBig(const char* sz, Amount valLo, Amount valHi) +{ + if (valHi) + { + MultiPrecision::UInt<4> val; + val.Set<2>(valHi); + val += MultiPrecision::UInt<2>(valLo); + + MultiPrecision::UInt<1> div1(1000000000ul); + + char szBuf[64]; // little extra + char* szPos = szBuf + _countof(szBuf) - 1; + szPos[0] = 0; + + while (true) + { + MultiPrecision::UInt<4> quot; + quot.SetDivResid(val, div1); + + szPos -= 9; + Utils::String::Decimal::PrintNoZTerm(szPos, val.get_Val<1>(), 9); + + if (quot.IsZero()) + break; + val = quot; + } + + while ('0' == *szPos) + szPos++; + + Env::DocGroup gr(sz); + DocSetType("amount"); + Env::DocAddText("value", szPos); + + } + else + DocAddAmount(sz, valLo); + +} + +inline void DocAddAid(const char* sz, AssetID aid) +{ + Env::DocGroup gr(sz); + DocSetType("aid"); + Env::DocAddNum("value", aid); +} + +inline void DocAddAidAmount(const char* sz, AssetID aid, Amount amount) +{ + Env::DocArray gr(sz); + DocAddAid("", aid); + DocAddAmount("", amount); +} + +inline void DocAddCid(const char* sz, const ContractID& cid) +{ + Env::DocGroup gr(sz); + DocSetType("cid"); + Env::DocAddBlob_T("value", cid); +} + +inline void DocAddFloat(const char* sz, MultiPrecision::Float x) +{ + char szBuf[MultiPrecision::Float::DecimalForm::s_LenScientificMax + 1]; + x.get_Decimal().PrintAuto(szBuf); + Env::DocAddText(sz, szBuf); +} + +inline void DocAddFloatDbg(const char* sz, MultiPrecision::Float x) +{ + // convenient for debugging, to try the exact values on host + char szBuf[Utils::String::Hex::DigitsMax::N + Utils::String::Decimal::DigitsMax::N + 10]; + Utils::String::Hex::Print(szBuf, x.m_Num, Utils::String::Hex::DigitsMax::N); + uint32_t n = Utils::String::Hex::DigitsMax::N; + szBuf[n++] = ' '; + + if (x.m_Order >= 0) + szBuf[n++] = '+'; + else + { + szBuf[n++] = '-'; + x.m_Order = -x.m_Order; + } + + n += Utils::String::Decimal::Print(szBuf + n, x.m_Order); + szBuf[n] = 0; + + Env::DocAddText(sz, szBuf); +} + +inline void DocAddPerc(const char* sz, MultiPrecision::Float x, uint32_t nDigsAfterDot = 3) +{ + MultiPrecision::Float::DecimalForm df; + df.Assign(x); + df.m_Order10 += 2; // to perc + + MultiPrecision::Float::DecimalForm::PrintOptions po; + po.m_DigitsAfterDot = nDigsAfterDot; + + // remove unnecessary extra precision + auto df2 = df; + int32_t nExtra = -(po.m_DigitsAfterDot + df2.m_Order10); + if (nExtra > 0) + { + // loose extra precision + if (df2.m_NumDigits > (uint32_t)nExtra) + df2.LimitPrecision(df2.m_NumDigits - nExtra); + else + { + // loose all, make it 0 + df2.m_Num = 0; + df2.m_Order10 = 0; + df2.m_NumDigits = 1; + } + } + + char szBuf[MultiPrecision::Float::DecimalForm::s_LenScientificMax + 1]; + if (df2.get_TextLenStd(po) < _countof(szBuf)) + df2.PrintStd(szBuf, po); + else + { + df.LimitPrecision(nDigsAfterDot + 2); + po.m_DigitsAfterDot = -1; + df.PrintScientific(szBuf, po); + } + + Env::DocAddText(sz, szBuf); +} + +inline void DocAddFixedPoint(const char* sz, uint64_t val, uint64_t one, uint32_t nDigsAfterDot) +{ + char szVal[Utils::String::Decimal::DigitsMax::N + 10]; + auto n1 = Utils::String::Decimal::Print(szVal, val / one); + + if (nDigsAfterDot) + { + szVal[n1++] = '.'; + + while (true) + { + val %= one; + val *= 10; + szVal[n1++] = Utils::String::Decimal::ToChar(val / one); + + if (!--nDigsAfterDot) + break; + } + + szVal[n1] = 0; + } + + Env::DocAddText(sz, szVal); +} + +// Upgradable-wrapper helpers. Free functions; do not depend on ParserContext. +// Per-contract parser modules and the explorer host both call these to render +// the upgradable plumbing (admins mask, settings table) consistently. + +inline void WriteUpgradeAdminsMask(uint32_t nApproveMask) +{ + Env::DocArray gr("Approvers"); + + for (uint32_t i = 0; i < (sizeof(nApproveMask) << 3); i++) + { + uint32_t msk = 1u << i; + if (!(nApproveMask & msk)) + continue; + + Env::DocAddNum("", i); + } +} + +inline void WriteUpgradeSettingsInternal(const Upgradable3::Settings& stg) +{ + Env::DocAddNum("Delay", stg.m_hMinUpgradeDelay); + Env::DocAddNum("Min approvers", stg.m_MinApprovers); + + { + Env::DocGroup gr1("Admins"); + DocSetType("table"); + Env::DocArray gr2("value"); + + { + Env::DocArray gr3(""); + DocAddTableHeader("Index"); + DocAddTableHeader("Key"); + } + + for (uint32_t i = 0; i < _countof(stg.m_pAdmin); i++) + { + const auto& pk = stg.m_pAdmin[i]; + if (_POD_(pk).IsZero()) + continue; + + Env::DocArray gr3(""); + + Env::DocAddNum("", i); + DocAddPk("", pk); + } + + } +} + +inline void WriteUpgradeSettings(const Upgradable2::Settings& stg) +{ + WriteUpgradeSettingsInternal(Cast::Reinterpret(stg)); +} + +inline void WriteUpgradeSettings(const Upgradable3::Settings& stg) +{ + Env::DocGroup gr("Upgradable3"); + WriteUpgradeSettingsInternal(stg); +} diff --git a/bvm/Shaders/Explorer/parser_module_abi.h b/bvm/Shaders/Explorer/parser_module_abi.h new file mode 100644 index 0000000000..f1fcfd4388 --- /dev/null +++ b/bvm/Shaders/Explorer/parser_module_abi.h @@ -0,0 +1,73 @@ +// Copyright 2018 The Beam Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "../common.h" +#include "parser_common.h" + +// Per-contract explorer parser module ABI. +// +// Every parser module exports four BEAM_EXPORT entrypoints: +// +// Method_0(sid, cid, iMethod, pArgs, nArgs) — parse a method invocation. +// Mirrors monolith Method_0. +// Method_1(sid, cid) — emit kind / identification only. +// Mirrors monolith Method_1. +// Method_2(sid, cid) — emit full state. +// Mirrors monolith Method_2. +// Method_3(out_buf, out_cap) — return the SIDs this module handles. +// Two-call protocol: +// call with out_buf=nullptr, out_cap=0 +// -> module returns N (count of SIDs). +// Host allocates N * sizeof(ShaderID), +// calls again -> module writes +// min(N, out_cap) entries and returns +// the actual count written. +// +// Method_0/1/2 keep monolith call shape so the host's existing wasm-call paths +// (ProcessorInfoParser::ParseExtraInfo / get_ContractDescr) keep working +// unchanged for per-module dispatch. Method_3 is new. +// +// A module may declare multiple SIDs (versioned contracts ship every entry of +// their s_pSID[] in one module). The module recovers iVer by scanning its own +// s_pSID[] inside Method_0/Method_2. +// +// All output goes to the host's doc stream via Env::Doc* and the helpers in +// parser_common.h. State lookups go through Env::VarReader keyed by the +// passed-in cid. Modules are restricted to the manager-mode Env import surface. + +// Convenience helper: copy `n` SIDs from `src` to `out_buf`, capped by `out_cap`. +// Returns `n` regardless of cap (the two-call protocol relies on the unclamped count). +inline uint32_t ParserModule_FillSids(ShaderID* out_buf, uint32_t out_cap, const ShaderID* src, uint32_t n) +{ + if (out_buf) + { + uint32_t nCopy = (n < out_cap) ? n : out_cap; + for (uint32_t i = 0; i < nCopy; i++) + _POD_(out_buf[i]) = src[i]; + } + return n; +} + +// Boilerplate macros for the common module shape. +// Use only when Method_1 and Method_2 are exactly `OnKind()` (no per-cid state body). + +#define PARSER_MODULE_EXPORT_SIDS(SIDS) \ + BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) { \ + return ParserModule_FillSids(out_buf, out_cap, SIDS, _countof(SIDS)); } + +#define PARSER_MODULE_EXPORT_KIND_ONLY(FN_KIND) \ + BEAM_EXPORT void Method_1(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); FN_KIND(); } \ + BEAM_EXPORT void Method_2(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); FN_KIND(); } diff --git a/bvm/Shaders/StableCoin/contract.wasm b/bvm/Shaders/StableCoin/contract.wasm old mode 100644 new mode 100755 index 85afb38999..0b8fa14bf9 Binary files a/bvm/Shaders/StableCoin/contract.wasm and b/bvm/Shaders/StableCoin/contract.wasm differ diff --git a/bvm/Shaders/amm/app.wasm b/bvm/Shaders/amm/app.wasm old mode 100644 new mode 100755 index d3269cfdf4..3ac5d8b3aa Binary files a/bvm/Shaders/amm/app.wasm and b/bvm/Shaders/amm/app.wasm differ diff --git a/bvm/Shaders/amm/contract.wasm b/bvm/Shaders/amm/contract.wasm old mode 100644 new mode 100755 index f7bc69d088..3447c50f3d Binary files a/bvm/Shaders/amm/contract.wasm and b/bvm/Shaders/amm/contract.wasm differ diff --git a/bvm/Shaders/amm/parser.cpp b/bvm/Shaders/amm/parser.cpp new file mode 100644 index 0000000000..d2ece25876 --- /dev/null +++ b/bvm/Shaders/amm/parser.cpp @@ -0,0 +1,208 @@ +// Parser module for Amm / DEX (versioned, behind Upgradable3). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static void OnKind() { Env::DocAddText("kind", "DEX"); } + +static void WriteAmmSettings(const Amm::Settings& stg) +{ + DocAddCid("Dao-Vault", stg.m_cidDaoVault); +} + +static const char* get_AmmKind(const Amm::Pool::ID& pid) +{ + switch (pid.m_Fees.m_Kind) + { + case 0: return "Low"; + case 1: return "Medium"; + case 2: return "High"; + } + return ""; +} + +static void DocSetAmmPool(const Amm::Pool::ID& pid) +{ + DocAddAid("Aid1", pid.m_Aid1); + DocAddAid("Aid2", pid.m_Aid2); + Env::DocAddText("Volatility", get_AmmKind(pid)); +} + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 1: Env::DocAddText("method", "Destroy"); break; + + case Amm::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(Amm::Method::Create)) + { + auto* p = (const Amm::Method::Create*) pArg; + Env::DocGroup gr("params"); + WriteAmmSettings(p->m_Settings); + WriteUpgradeSettings(p->m_Upgradable); + } + break; + + case Upgradable3::Method::Control::s_iMethod: + // Control method handling intentionally minimal — host emits wrapper info. + Env::DocAddText("method", "Upgradable3 Control"); + break; + + case Amm::Method::PoolCreate::s_iMethod: + if (nArg >= sizeof(Amm::Method::PoolCreate)) + { + auto* p = (const Amm::Method::PoolCreate*) pArg; + Env::DocAddText("method", "Pool Create"); + Env::DocGroup gr("params"); + DocSetAmmPool(p->m_Pid); + DocAddPk("Creator", p->m_pkCreator); + } + break; + + case Amm::Method::PoolDestroy::s_iMethod: + if (nArg >= sizeof(Amm::Method::PoolDestroy)) + { + auto* p = (const Amm::Method::PoolDestroy*) pArg; + Env::DocAddText("method", "Pool Destroy"); + Env::DocGroup gr("params"); + DocSetAmmPool(p->m_Pid); + } + break; + + case Amm::Method::AddLiquidity::s_iMethod: + if (nArg >= sizeof(Amm::Method::AddLiquidity)) + { + auto* p = (const Amm::Method::AddLiquidity*) pArg; + Env::DocAddText("method", "Liquidity Add"); + Env::DocGroup gr("params"); + DocSetAmmPool(p->m_Pid); + } + break; + + case Amm::Method::Withdraw::s_iMethod: + if (nArg >= sizeof(Amm::Method::Withdraw)) + { + auto* p = (const Amm::Method::Withdraw*) pArg; + Env::DocAddText("method", "Liquidity Withdraw"); + Env::DocGroup gr("params"); + DocSetAmmPool(p->m_Pid); + } + break; + + case Amm::Method::Trade::s_iMethod: + if (nArg >= sizeof(Amm::Method::Trade)) + { + auto* p = (const Amm::Method::Trade*) pArg; + Env::DocAddText("method", "Trade"); + Env::DocGroup gr("params"); + DocSetAmmPool(p->m_Pid); + } + break; + } +} + +static void OnState_Inner(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = Amm::Tags::s_Settings; + + Amm::Settings s; + if (!Env::VarReader::Read_T(k, s)) + return; + + { + Env::DocGroup gr2("Settings"); + WriteAmmSettings(s); + } + + { + Env::DocGroup gr2("Pools"); + DocSetType("table"); + Env::DocArray gr3("value"); + + { + Env::DocArray gr4(""); + DocAddTableHeader("Aid1"); + DocAddTableHeader("Aid2"); + DocAddTableHeader("Volatility"); + DocAddTableHeader("LP-Token"); + DocAddTableHeader("Amount1"); + DocAddTableHeader("Amount2"); + DocAddTableHeader("Amount-LP-Token"); + DocAddTableHeader("Rate 1:2"); + DocAddTableHeader("Rate 2:2"); + } + + Env::Key_T k0, k1; + _POD_(k0.m_Prefix.m_Cid) = cid; + _POD_(k1.m_Prefix.m_Cid) = cid; + _POD_(k0.m_KeyInContract.m_ID).SetZero(); + _POD_(k1.m_KeyInContract.m_ID).SetObject(0xff); + + for (Env::VarReader r(k0, k1); ; ) + { + Amm::Pool p; + if (!r.MoveNext_T(k0, p)) + break; + + Env::DocArray gr4(""); + DocAddAid("", k0.m_KeyInContract.m_ID.m_Aid1); + DocAddAid("", k0.m_KeyInContract.m_ID.m_Aid2); + Env::DocAddText("", get_AmmKind(k0.m_KeyInContract.m_ID)); + DocAddAid("", p.m_aidCtl); + DocAddAmount("", p.m_Totals.m_Tok1); + DocAddAmount("", p.m_Totals.m_Tok2); + DocAddAmount("", p.m_Totals.m_Ctl); + + if (p.m_Totals.m_Tok1 && p.m_Totals.m_Tok2) + { + char szBuf[MultiPrecision::Float::DecimalForm::s_LenScientificMax + 1]; + + MultiPrecision::Float f1(p.m_Totals.m_Tok1); + MultiPrecision::Float f2(p.m_Totals.m_Tok2); + + for (uint32_t i = 0; i < 2; i++) + { + auto kv = i ? (f2 / f1) : (f1 / f2); + auto df = kv.get_Decimal(); + + const uint32_t nPrecision = 8; + df.LimitPrecision(nPrecision); + + MultiPrecision::Float::DecimalForm::PrintOptions po; + + if (df.get_TextLenStd(po) <= nPrecision + 2) + df.PrintStd(szBuf, po); + else + df.PrintScientific(szBuf, po); + + Env::DocAddText("", szBuf); + } + } + else + { + Env::DocAddText("", ""); + Env::DocAddText("", ""); + } + } + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, Amm::s_pSID, _countof(Amm::s_pSID)); +} +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} +BEAM_EXPORT void Method_1(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); OnKind(); } +BEAM_EXPORT void Method_2(const ShaderID&, const ContractID& cid) +{ + Env::DocGroup gr(""); OnKind(); + { Env::DocGroup grSt("State"); OnState_Inner(cid); } +} diff --git a/bvm/Shaders/amm/parser.wasm b/bvm/Shaders/amm/parser.wasm new file mode 100755 index 0000000000..038b73e2d3 Binary files /dev/null and b/bvm/Shaders/amm/parser.wasm differ diff --git a/bvm/Shaders/aphorize/contract.wasm b/bvm/Shaders/aphorize/contract.wasm old mode 100644 new mode 100755 index 1ef3a2ec1f..88fba3cc06 Binary files a/bvm/Shaders/aphorize/contract.wasm and b/bvm/Shaders/aphorize/contract.wasm differ diff --git a/bvm/Shaders/asset_man/app.wasm b/bvm/Shaders/asset_man/app.wasm old mode 100644 new mode 100755 index ee41f20beb..38f350e735 Binary files a/bvm/Shaders/asset_man/app.wasm and b/bvm/Shaders/asset_man/app.wasm differ diff --git a/bvm/Shaders/asset_man/contract.wasm b/bvm/Shaders/asset_man/contract.wasm old mode 100644 new mode 100755 index 6d15048107..643f8f0bfc Binary files a/bvm/Shaders/asset_man/contract.wasm and b/bvm/Shaders/asset_man/contract.wasm differ diff --git a/bvm/Shaders/bans/app.wasm b/bvm/Shaders/bans/app.wasm old mode 100644 new mode 100755 index 3a3c0cac2b..0231f4b89e Binary files a/bvm/Shaders/bans/app.wasm and b/bvm/Shaders/bans/app.wasm differ diff --git a/bvm/Shaders/bans/contract.wasm b/bvm/Shaders/bans/contract.wasm old mode 100644 new mode 100755 index 6d1a7c50a2..8d3794270b Binary files a/bvm/Shaders/bans/contract.wasm and b/bvm/Shaders/bans/contract.wasm differ diff --git a/bvm/Shaders/bans/parser.cpp b/bvm/Shaders/bans/parser.cpp new file mode 100644 index 0000000000..a6326f2eb8 --- /dev/null +++ b/bvm/Shaders/bans/parser.cpp @@ -0,0 +1,209 @@ +// Parser module for NameService / Bans (versioned, behind Upgradable3). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static void OnKind() { Env::DocAddText("kind", "Bans"); } + +static void WriteBansSettings(const NameService::Settings& stg) +{ + DocAddCid("Price oracle", stg.m_cidOracle); + DocAddCid("Dao-Vault", stg.m_cidDaoVault); + DocAddCid("Anon-Vault", stg.m_cidVault); + DocAddHeight("Activation height", stg.m_h0); +} + +// emit "name" field from a name-prefixed method arg, bounded by the original arg buffer. +template +static void DocSetBansName(const void* pArg, uint32_t nArg, const T& x) +{ + uint32_t nameLen = x.m_NameLen; + if (nameLen > NameService::Domain::s_MaxLen) + return; + + const uint8_t* p = (const uint8_t*) (&x + 1); + uint32_t n0 = p - (const uint8_t*) pArg; + if (n0 + nameLen > nArg) + return; + + char sz[NameService::Domain::s_MaxLen + 1]; + Env::Memcpy(sz, p, nameLen); + sz[nameLen] = 0; + Env::DocAddText("name", sz); +} + +static void OnMethod_Inner(const void* pArg, uint32_t nArg, uint32_t iMethod) +{ + switch (iMethod) + { + case 1: Env::DocAddText("method", "Destroy"); break; + + case NameService::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(NameService::Method::Create)) + { + auto* p = (const NameService::Method::Create*) pArg; + Env::DocGroup gr("params"); + WriteBansSettings(p->m_Settings); + WriteUpgradeSettings(p->m_Upgradable); + } + break; + + case Upgradable3::Method::Control::s_iMethod: + // Control method handling intentionally minimal — host emits wrapper info. + Env::DocAddText("method", "Upgradable3 Control"); + break; + + case NameService::Method::SetOwner::s_iMethod: + if (nArg >= sizeof(NameService::Method::SetOwner)) + { + auto* p = (const NameService::Method::SetOwner*) pArg; + Env::DocAddText("method", "Set Owner"); + Env::DocGroup gr("params"); + DocSetBansName(pArg, nArg, *p); + DocAddPk("New owner", p->m_pkNewOwner); + } + break; + + case NameService::Method::Extend::s_iMethod: + if (nArg >= sizeof(NameService::Method::Extend)) + { + auto* p = (const NameService::Method::Extend*) pArg; + Env::DocAddText("method", "Extend period"); + Env::DocGroup gr("params"); + DocSetBansName(pArg, nArg, *p); + Env::DocAddNum32("Periods", p->m_Periods); + } + break; + + case NameService::Method::SetPrice::s_iMethod: + if (nArg >= sizeof(NameService::Method::SetPrice)) + { + auto* p = (const NameService::Method::SetPrice*) pArg; + Env::DocAddText("method", p->m_Price.m_Amount ? "Set Price" : "Remove Price"); + Env::DocGroup gr("params"); + DocSetBansName(pArg, nArg, *p); + if (p->m_Price.m_Amount) + DocAddAidAmount("Price", p->m_Price.m_Aid, p->m_Price.m_Amount); + } + break; + + case NameService::Method::Buy::s_iMethod: + if (nArg >= sizeof(NameService::Method::Buy)) + { + auto* p = (const NameService::Method::Buy*) pArg; + Env::DocAddText("method", "Buy"); + Env::DocGroup gr("params"); + DocSetBansName(pArg, nArg, *p); + DocAddPk("New owner", p->m_pkNewOwner); + } + break; + + case NameService::Method::Register::s_iMethod: + if (nArg >= sizeof(NameService::Method::Register)) + { + auto* p = (const NameService::Method::Register*) pArg; + Env::DocAddText("method", "Register"); + Env::DocGroup gr("params"); + DocSetBansName(pArg, nArg, *p); + DocAddPk("Owner", p->m_pkOwner); + Env::DocAddNum32("Periods", p->m_Periods); + } + break; + } +} + +static void OnState_Inner(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = NameService::Tags::s_Settings; + + NameService::Settings s; + if (!Env::VarReader::Read_T(k, s)) + return; + + { + Env::DocGroup gr2("Settings"); + WriteBansSettings(s); + } + + { + Env::DocGroup gr2("Domains"); + DocSetType("table"); + Env::DocArray gr3("value"); + + { + Env::DocArray gr4(""); + DocAddTableHeader("Name"); + DocAddTableHeader("Owner"); + DocAddTableHeader("Expiration height"); + DocAddTableHeader("Status"); + DocAddTableHeader("Sell price"); + } + + Env::Key_T k0; + _POD_(k0.m_Prefix.m_Cid) = cid; + _POD_(k0.m_KeyInContract.m_sz).SetZero(); + +#pragma pack (push, 1) + struct KeyPlus { + Env::Key_T k; + char m_chTerm; + } k1; +#pragma pack (pop) + + _POD_(k1.k.m_Prefix.m_Cid) = cid; + Env::Memset(k1.k.m_KeyInContract.m_sz, 0xff, NameService::Domain::s_MaxLen); + + Height h = Env::get_Height(); + for (Env::VarReader r(k0, k1.k); ; ) + { + NameService::Domain d; + uint32_t nKey = sizeof(k1.k), nVal = sizeof(d); + if (!r.MoveNext(&k1.k, nKey, &d, nVal, 0)) + break; + + if (sizeof(d) != nVal) + continue; + + nKey -= (sizeof(k0) - NameService::Domain::s_MinLen); + if (nKey > NameService::Domain::s_MaxLen) + continue; + + k1.k.m_KeyInContract.m_sz[nKey] = 0; + + Env::DocArray gr4(""); + Env::DocAddText("", k1.k.m_KeyInContract.m_sz); + DocAddPk("", d.m_pkOwner); + DocAddHeight("", d.m_hExpire); + + const char* szStatus = + (d.m_hExpire > h) ? "" : + (d.m_hExpire + NameService::Domain::s_PeriodHold > h) ? "On Hold" : + "Expired"; + Env::DocAddText("", szStatus); + + if (d.m_Price.m_Amount) + DocAddAidAmount("", d.m_Price.m_Aid, d.m_Price.m_Amount); + else + Env::DocAddText("", ""); + } + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, NameService::s_pSID, _countof(NameService::s_pSID)); +} +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(pArg, nArg, iMethod); +} +BEAM_EXPORT void Method_1(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); OnKind(); } +BEAM_EXPORT void Method_2(const ShaderID&, const ContractID& cid) +{ + Env::DocGroup gr(""); OnKind(); + { Env::DocGroup grSt("State"); OnState_Inner(cid); } +} diff --git a/bvm/Shaders/bans/parser.wasm b/bvm/Shaders/bans/parser.wasm new file mode 100755 index 0000000000..cce3885b9e Binary files /dev/null and b/bvm/Shaders/bans/parser.wasm differ diff --git a/bvm/Shaders/blackhole/app.wasm b/bvm/Shaders/blackhole/app.wasm old mode 100644 new mode 100755 index 3962daa229..43ccc4347e Binary files a/bvm/Shaders/blackhole/app.wasm and b/bvm/Shaders/blackhole/app.wasm differ diff --git a/bvm/Shaders/blackhole/contract.wasm b/bvm/Shaders/blackhole/contract.wasm old mode 100644 new mode 100755 index 90ab4d0e16..2192680568 Binary files a/bvm/Shaders/blackhole/contract.wasm and b/bvm/Shaders/blackhole/contract.wasm differ diff --git a/bvm/Shaders/blackhole/parser.cpp b/bvm/Shaders/blackhole/parser.cpp new file mode 100644 index 0000000000..1fb43d10f3 --- /dev/null +++ b/bvm/Shaders/blackhole/parser.cpp @@ -0,0 +1,29 @@ +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static const ShaderID s_pSid[] = { BlackHole::s_SID }; + +static void OnKind() { Env::DocAddText("kind", "BlackHole"); } + +static void OnMethod_Inner(uint32_t iMethod) +{ + switch (iMethod) + { + case 0: Env::DocAddText("method", "Create"); break; + case 1: Env::DocAddText("method", "Destroy"); break; + + case BlackHole::Method::Deposit::s_iMethod: + Env::DocAddText("method", "Deposit"); + break; + } +} + +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void*, uint32_t) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod); +} + +PARSER_MODULE_EXPORT_SIDS(s_pSid) +PARSER_MODULE_EXPORT_KIND_ONLY(OnKind) diff --git a/bvm/Shaders/blackhole/parser.wasm b/bvm/Shaders/blackhole/parser.wasm new file mode 100755 index 0000000000..bfaf64b15d Binary files /dev/null and b/bvm/Shaders/blackhole/parser.wasm differ diff --git a/bvm/Shaders/dao-accumulator/app.wasm b/bvm/Shaders/dao-accumulator/app.wasm old mode 100644 new mode 100755 index b5c9e24e48..24e8a026f6 Binary files a/bvm/Shaders/dao-accumulator/app.wasm and b/bvm/Shaders/dao-accumulator/app.wasm differ diff --git a/bvm/Shaders/dao-accumulator/contract.wasm b/bvm/Shaders/dao-accumulator/contract.wasm old mode 100644 new mode 100755 index d4dabc47b9..756a632925 Binary files a/bvm/Shaders/dao-accumulator/contract.wasm and b/bvm/Shaders/dao-accumulator/contract.wasm differ diff --git a/bvm/Shaders/dao-accumulator/parser.cpp b/bvm/Shaders/dao-accumulator/parser.cpp new file mode 100644 index 0000000000..47bc17b452 --- /dev/null +++ b/bvm/Shaders/dao-accumulator/parser.cpp @@ -0,0 +1,180 @@ +// Parser module for DaoAccumulator (versioned, behind Upgradable3). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static void OnKind() { Env::DocAddText("kind", "DaoAccumulator"); } + +static void OnPoolType(uint8_t nType) +{ + static const char s_szName[] = "Pool"; + switch (nType) + { + case DaoAccumulator::Method::UserLock::Type::BeamX_PrePhase: Env::DocAddText(s_szName, "Beam-BeamX pre-phase"); break; + case DaoAccumulator::Method::UserLock::Type::BeamX: Env::DocAddText(s_szName, "Beam-BeamX"); break; + case DaoAccumulator::Method::UserLock::Type::Nph: Env::DocAddText(s_szName, "Beam-Nph"); break; + } +} + +static void OnUserWithdraw(uint8_t nType, const void* pArg, uint32_t nArg) +{ + if (nArg < sizeof(DaoAccumulator::Method::UserWithdraw_Base)) + return; + auto* p = (const DaoAccumulator::Method::UserWithdraw_Base*) pArg; + Env::DocAddText("method", "Withdraw"); + Env::DocGroup gr("params"); + OnPoolType(nType); + DocAddPk("pk", p->m_pkUser); +} + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 1: Env::DocAddText("method", "Destroy"); break; + + case DaoAccumulator::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(DaoAccumulator::Method::Create)) + { + auto* p = (const DaoAccumulator::Method::Create*) pArg; + Env::DocGroup gr("params"); + WriteUpgradeSettings(p->m_Upgradable); + DocAddAid("beamX", p->m_aidBeamX); + DocAddHeight("Per-phase end", p->m_hPrePhaseEnd); + } + break; + + case Upgradable3::Method::Control::s_iMethod: + // Control method handling intentionally minimal — host emits wrapper info. + Env::DocAddText("method", "Upgradable3 Control"); + break; + + case DaoAccumulator::Method::FarmStart::s_iMethod: + if (nArg >= sizeof(DaoAccumulator::Method::FarmStart)) + { + auto* p = (const DaoAccumulator::Method::FarmStart*) pArg; + Env::DocAddText("method", "Farm Start"); + Env::DocGroup gr("params"); + WriteUpgradeAdminsMask(p->m_ApproveMask); + DocAddAid("LP-Token", p->m_aidLpToken); + DocAddAmount("Total Reward", p->m_FarmBeamX); + Env::DocAddNum("Total Duration", p->m_hFarmDuration); + } + break; + + case DaoAccumulator::Method::UserLock::s_iMethod: + if (nArg >= sizeof(DaoAccumulator::Method::UserLock)) + { + auto* p = (const DaoAccumulator::Method::UserLock*) pArg; + Env::DocAddText("method", "Lock"); + Env::DocGroup gr("params"); + OnPoolType(p->m_PoolType); + DocAddPk("pk", p->m_pkUser); + DocAddHeight("hEnd", p->m_hEnd); + } + break; + + case DaoAccumulator::Method::UserWithdraw_FromBeamNph::s_iMethod: + OnUserWithdraw(DaoAccumulator::Method::UserLock::Type::Nph, pArg, nArg); + break; + + case DaoAccumulator::Method::UserWithdraw_FromBeamBeamX::s_iMethod: + OnUserWithdraw(DaoAccumulator::Method::UserLock::Type::BeamX, pArg, nArg); + break; + } +} + +static void OnState_Pool(DaoAccumulator::Pool& p, const char* szName) +{ + Env::DocGroup gr(szName); + p.Update(Env::get_Height()); + DocAddAmount("Reward remaining", p.m_AmountRemaining); + Env::DocAddNum("Farming duration remaining", p.m_hRemaining); +} + +static void OnState_Users(const ContractID& cid, DaoAccumulator::Pool& p, uint8_t type, const char* szName) +{ + Env::DocGroup gr2(szName); + DocSetType("table"); + Env::DocArray gr3("value"); + + { + Env::DocArray gr4(""); + DocAddTableHeader("LP-Tokens"); + DocAddTableHeader("Locked until"); + DocAddTableHeader("Reward"); + DocAddTableHeader("Key"); + } + + Env::Key_T k0, k1; + k0.m_KeyInContract.m_Tag = type; + k1.m_KeyInContract.m_Tag = type; + _POD_(k0.m_Prefix.m_Cid) = cid; + _POD_(k1.m_Prefix.m_Cid) = cid; + _POD_(k0.m_KeyInContract.m_pk).SetZero(); + _POD_(k1.m_KeyInContract.m_pk).SetObject(0xff); + + for (Env::VarReader r(k0, k1); ; ) + { + DaoAccumulator::User u; + if (!r.MoveNext_T(k0, u)) + break; + + Env::DocArray gr4(""); + DocAddAmount("", u.m_LpToken); + DocAddHeight("", u.m_hEnd); + + u.m_EarnedBeamX += p.Remove(u.m_PoolUser); + DocAddAmount("", u.m_EarnedBeamX); + + DocAddPk("", k0.m_KeyInContract.m_pk); + } +} + +static void OnState_Inner(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = DaoAccumulator::Tags::s_State; + + DaoAccumulator::State s; + if (!Env::VarReader::Read_T(k, s)) + return; + + DocAddAid("BeamX", s.m_aidBeamX); + DocAddHeight("Pre-phaseend height ", s.m_hPreEnd); + + if (s.m_aidLpToken) + { + DocAddAid("LP-token", s.m_aidLpToken); + OnState_Pool(s.m_Pool, "Pool Beam/BeamX"); + } + + DaoAccumulator::Pool p_Nph; + k.m_KeyInContract = DaoAccumulator::Tags::s_PoolBeamNph; + + if (Env::VarReader::Read_T(k, p_Nph)) + OnState_Pool(p_Nph, "Pool Beam/Nph"); + else + _POD_(p_Nph).SetZero(); + + OnState_Users(cid, s.m_Pool, DaoAccumulator::Tags::s_User, "Beam/BeamX users"); + OnState_Users(cid, p_Nph, DaoAccumulator::Tags::s_UserBeamNph, "Beam/Nph users"); +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, DaoAccumulator::s_pSID, _countof(DaoAccumulator::s_pSID)); +} +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} +BEAM_EXPORT void Method_1(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); OnKind(); } +BEAM_EXPORT void Method_2(const ShaderID&, const ContractID& cid) +{ + Env::DocGroup gr(""); OnKind(); + { Env::DocGroup grSt("State"); OnState_Inner(cid); } +} diff --git a/bvm/Shaders/dao-accumulator/parser.wasm b/bvm/Shaders/dao-accumulator/parser.wasm new file mode 100755 index 0000000000..564f6fde0b Binary files /dev/null and b/bvm/Shaders/dao-accumulator/parser.wasm differ diff --git a/bvm/Shaders/dao-core-masternet/app-admin.wasm b/bvm/Shaders/dao-core-masternet/app-admin.wasm old mode 100644 new mode 100755 index 7ae56acbc2..66a30defdc Binary files a/bvm/Shaders/dao-core-masternet/app-admin.wasm and b/bvm/Shaders/dao-core-masternet/app-admin.wasm differ diff --git a/bvm/Shaders/dao-core-masternet/app.wasm b/bvm/Shaders/dao-core-masternet/app.wasm old mode 100644 new mode 100755 index 38968887c4..c0824a1b2a Binary files a/bvm/Shaders/dao-core-masternet/app.wasm and b/bvm/Shaders/dao-core-masternet/app.wasm differ diff --git a/bvm/Shaders/dao-core-masternet/contract.wasm b/bvm/Shaders/dao-core-masternet/contract.wasm old mode 100644 new mode 100755 index f8ecab8a36..4652dbc496 Binary files a/bvm/Shaders/dao-core-masternet/contract.wasm and b/bvm/Shaders/dao-core-masternet/contract.wasm differ diff --git a/bvm/Shaders/dao-core-testnet/app-admin.wasm b/bvm/Shaders/dao-core-testnet/app-admin.wasm old mode 100644 new mode 100755 index fac846d916..191364a73f Binary files a/bvm/Shaders/dao-core-testnet/app-admin.wasm and b/bvm/Shaders/dao-core-testnet/app-admin.wasm differ diff --git a/bvm/Shaders/dao-core-testnet/app.wasm b/bvm/Shaders/dao-core-testnet/app.wasm old mode 100644 new mode 100755 index 160856b60a..c13333f690 Binary files a/bvm/Shaders/dao-core-testnet/app.wasm and b/bvm/Shaders/dao-core-testnet/app.wasm differ diff --git a/bvm/Shaders/dao-core-testnet/contract.wasm b/bvm/Shaders/dao-core-testnet/contract.wasm old mode 100644 new mode 100755 index 26818c8b35..ccba0a9ad1 Binary files a/bvm/Shaders/dao-core-testnet/contract.wasm and b/bvm/Shaders/dao-core-testnet/contract.wasm differ diff --git a/bvm/Shaders/dao-core/app-admin.wasm b/bvm/Shaders/dao-core/app-admin.wasm old mode 100644 new mode 100755 index 62199cc8ea..c9c64c2b9e Binary files a/bvm/Shaders/dao-core/app-admin.wasm and b/bvm/Shaders/dao-core/app-admin.wasm differ diff --git a/bvm/Shaders/dao-core/app.wasm b/bvm/Shaders/dao-core/app.wasm old mode 100644 new mode 100755 index 385999479f..f9d2dbe768 Binary files a/bvm/Shaders/dao-core/app.wasm and b/bvm/Shaders/dao-core/app.wasm differ diff --git a/bvm/Shaders/dao-core/contract.wasm b/bvm/Shaders/dao-core/contract.wasm old mode 100644 new mode 100755 index 92a90011fa..4a3a56b648 Binary files a/bvm/Shaders/dao-core/contract.wasm and b/bvm/Shaders/dao-core/contract.wasm differ diff --git a/bvm/Shaders/dao-core/parser.cpp b/bvm/Shaders/dao-core/parser.cpp new file mode 100644 index 0000000000..e17c852694 --- /dev/null +++ b/bvm/Shaders/dao-core/parser.cpp @@ -0,0 +1,50 @@ +// Parser module for DaoCore — handles mainnet, masternet, and testnet variants. +// All three share identical method dispatch; SIDs differ. +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "../dao-core2/contract.h" +#include "contract.h" +namespace Masternet { +#include "../dao-core-masternet/contract.h" +} +namespace Testnet { +#include "../dao-core-testnet/contract.h" +} + +static const ShaderID s_pSid[] = { + DaoCore::s_SID, + Masternet::DaoCore::s_SID, + Testnet::DaoCore::s_SID, +}; + +static void OnKind() { Env::DocAddText("kind", "Dao-Core"); } + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 0: Env::DocAddText("method", "Create"); break; + case 1: Env::DocAddText("method", "Destroy"); break; + case DaoCore::GetPreallocated::s_iMethod: Env::DocAddText("method", "Get Preallocated"); break; + case DaoCore::UpdPosFarming::s_iMethod: Env::DocAddText("method", "Farming Upd"); break; + + case DaoCore2::Method::AdminWithdraw::s_iMethod: + Env::DocAddText("method", "Admin Withdraw"); + if (nArg >= sizeof(DaoCore2::Method::AdminWithdraw)) + { + auto* p = (const DaoCore2::Method::AdminWithdraw*) pArg; + Env::DocGroup gr("params"); + WriteUpgradeAdminsMask(p->m_ApproveMask); + } + break; + } +} + +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} + +PARSER_MODULE_EXPORT_SIDS(s_pSid) +PARSER_MODULE_EXPORT_KIND_ONLY(OnKind) diff --git a/bvm/Shaders/dao-core/parser.wasm b/bvm/Shaders/dao-core/parser.wasm new file mode 100755 index 0000000000..773b0535c0 Binary files /dev/null and b/bvm/Shaders/dao-core/parser.wasm differ diff --git a/bvm/Shaders/dao-core2/app.wasm b/bvm/Shaders/dao-core2/app.wasm old mode 100644 new mode 100755 index 2e1d703d33..0b6113c3b1 Binary files a/bvm/Shaders/dao-core2/app.wasm and b/bvm/Shaders/dao-core2/app.wasm differ diff --git a/bvm/Shaders/dao-core2/contract.wasm b/bvm/Shaders/dao-core2/contract.wasm old mode 100644 new mode 100755 index 194b0637e7..5740c88280 Binary files a/bvm/Shaders/dao-core2/contract.wasm and b/bvm/Shaders/dao-core2/contract.wasm differ diff --git a/bvm/Shaders/dao-core2/parser.cpp b/bvm/Shaders/dao-core2/parser.cpp new file mode 100644 index 0000000000..8353d83891 --- /dev/null +++ b/bvm/Shaders/dao-core2/parser.cpp @@ -0,0 +1,37 @@ +// Parser module for DaoCore2 (versioned, behind Upgradable3). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "../dao-core/contract.h" +#include "contract.h" + +static void OnKind() { Env::DocAddText("kind", "Dao-Core"); } + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 0: Env::DocAddText("method", "Create"); break; + case 1: Env::DocAddText("method", "Destroy"); break; + case DaoCore::GetPreallocated::s_iMethod: Env::DocAddText("method", "Get Preallocated"); break; + case DaoCore::UpdPosFarming::s_iMethod: Env::DocAddText("method", "Farming Upd"); break; + + case DaoCore2::Method::AdminWithdraw::s_iMethod: + Env::DocAddText("method", "Admin Withdraw"); + if (nArg >= sizeof(DaoCore2::Method::AdminWithdraw)) + { + auto* p = (const DaoCore2::Method::AdminWithdraw*) pArg; + Env::DocGroup gr("params"); + WriteUpgradeAdminsMask(p->m_ApproveMask); + } + break; + } +} + +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} + +PARSER_MODULE_EXPORT_SIDS(DaoCore2::s_pSID) +PARSER_MODULE_EXPORT_KIND_ONLY(OnKind) diff --git a/bvm/Shaders/dao-core2/parser.wasm b/bvm/Shaders/dao-core2/parser.wasm new file mode 100755 index 0000000000..6d1d1ace91 Binary files /dev/null and b/bvm/Shaders/dao-core2/parser.wasm differ diff --git a/bvm/Shaders/dao-vault/app.wasm b/bvm/Shaders/dao-vault/app.wasm old mode 100644 new mode 100755 index 2d595fd676..c3231fd3ee Binary files a/bvm/Shaders/dao-vault/app.wasm and b/bvm/Shaders/dao-vault/app.wasm differ diff --git a/bvm/Shaders/dao-vault/contract.wasm b/bvm/Shaders/dao-vault/contract.wasm old mode 100644 new mode 100755 index 5a8b4c74b1..e4f9237a78 Binary files a/bvm/Shaders/dao-vault/contract.wasm and b/bvm/Shaders/dao-vault/contract.wasm differ diff --git a/bvm/Shaders/dao-vault/parser.cpp b/bvm/Shaders/dao-vault/parser.cpp new file mode 100644 index 0000000000..4b6a3cd3ac --- /dev/null +++ b/bvm/Shaders/dao-vault/parser.cpp @@ -0,0 +1,55 @@ +// Parser module for DaoVault (versioned, behind Upgradable3). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static void OnKind() { Env::DocAddText("kind", "DaoVault"); } + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 1: Env::DocAddText("method", "Destroy"); break; + + case DaoVault::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(DaoVault::Method::Create)) + { + auto* p = (const DaoVault::Method::Create*) pArg; + Env::DocGroup gr("params"); + WriteUpgradeSettings(p->m_Upgradable); + } + break; + + case Upgradable3::Method::Control::s_iMethod: + // Control method handling intentionally minimal — host emits wrapper info. + Env::DocAddText("method", "Upgradable3 Control"); + break; + + case DaoVault::Method::Deposit::s_iMethod: + Env::DocAddText("method", "Deposit"); + break; + + case DaoVault::Method::Withdraw::s_iMethod: + if (nArg >= sizeof(DaoVault::Method::Withdraw)) + { + auto* p = (const DaoVault::Method::Withdraw*) pArg; + Env::DocAddText("method", "Withdraw"); + Env::DocGroup gr("params"); + WriteUpgradeAdminsMask(p->m_ApproveMask); + } + break; + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, DaoVault::s_pSID, _countof(DaoVault::s_pSID)); +} +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} +BEAM_EXPORT void Method_1(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); OnKind(); } +BEAM_EXPORT void Method_2(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); OnKind(); } diff --git a/bvm/Shaders/dao-vault/parser.wasm b/bvm/Shaders/dao-vault/parser.wasm new file mode 100755 index 0000000000..fbf20f7275 Binary files /dev/null and b/bvm/Shaders/dao-vault/parser.wasm differ diff --git a/bvm/Shaders/dao-vote/app.wasm b/bvm/Shaders/dao-vote/app.wasm old mode 100644 new mode 100755 index d84820aad8..b2e5e6fcd4 Binary files a/bvm/Shaders/dao-vote/app.wasm and b/bvm/Shaders/dao-vote/app.wasm differ diff --git a/bvm/Shaders/dao-vote/contract.wasm b/bvm/Shaders/dao-vote/contract.wasm old mode 100644 new mode 100755 index f69225177e..992ca6e7f4 Binary files a/bvm/Shaders/dao-vote/contract.wasm and b/bvm/Shaders/dao-vote/contract.wasm differ diff --git a/bvm/Shaders/dao-vote/parser.cpp b/bvm/Shaders/dao-vote/parser.cpp new file mode 100644 index 0000000000..540bab4fb2 --- /dev/null +++ b/bvm/Shaders/dao-vote/parser.cpp @@ -0,0 +1,110 @@ +// Parser module for DaoVote (versioned, behind Upgradable3). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static void OnKind() { Env::DocAddText("kind", "DaoVote"); } + +static void WriteDaoVoteCfg(const DaoVote::Cfg& cfg) +{ + DocAddAid("Voting asset", cfg.m_Aid); + Env::DocAddNum("Epoch duration", cfg.m_hEpochDuration); + DocAddPk("Admin", cfg.m_pkAdmin); +} + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 1: Env::DocAddText("method", "Destroy"); break; + + case DaoVote::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(DaoVote::Method::Create)) + { + auto* p = (const DaoVote::Method::Create*) pArg; + Env::DocGroup gr("params"); + WriteUpgradeSettings(p->m_Upgradable); + WriteDaoVoteCfg(p->m_Cfg); + } + break; + + case Upgradable3::Method::Control::s_iMethod: + // Control method handling intentionally minimal — host emits wrapper info. + Env::DocAddText("method", "Upgradable3 Control"); + break; + + case DaoVote::Method::AddProposal::s_iMethod: + if (nArg >= sizeof(DaoVote::Method::AddProposal)) + { + auto* p = (const DaoVote::Method::AddProposal*) pArg; + Env::DocAddText("method", "Add proposal"); + Env::DocGroup gr("params"); + DocAddPk("moderator", p->m_pkModerator); + } + break; + + case DaoVote::Method::MoveFunds::s_iMethod: + if (nArg >= sizeof(DaoVote::Method::MoveFunds)) + { + auto* p = (const DaoVote::Method::MoveFunds*) pArg; + Env::DocAddText("method", p->m_Lock ? "Funds Lock" : "Funds Unlock"); + } + break; + + case DaoVote::Method::Vote::s_iMethod: + Env::DocAddText("method", "Vote"); + break; + + case DaoVote::Method::AddDividend::s_iMethod: + Env::DocAddText("method", "Add dividend"); + break; + + case DaoVote::Method::GetResults::s_iMethod: + Env::DocAddText("method", "Get results"); + break; + + case DaoVote::Method::SetModerator::s_iMethod: + if (nArg >= sizeof(DaoVote::Method::SetModerator)) + { + auto* p = (const DaoVote::Method::SetModerator*) pArg; + Env::DocAddText("method", "Set moderator"); + Env::DocGroup gr("params"); + DocAddPk("moderator", p->m_pk); + Env::DocAddNum32("Enable", p->m_Enable); + } + break; + } +} + +static void OnState_Inner(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = DaoVote::Tags::s_State; + + DaoVote::State s; + if (!Env::VarReader::Read_T(k, s)) + return; + + { + Env::DocGroup gr("Settings"); + WriteDaoVoteCfg(s.m_Cfg); + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, DaoVote::s_pSID, _countof(DaoVote::s_pSID)); +} +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} +BEAM_EXPORT void Method_1(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); OnKind(); } +BEAM_EXPORT void Method_2(const ShaderID&, const ContractID& cid) +{ + Env::DocGroup gr(""); OnKind(); + { Env::DocGroup grSt("State"); OnState_Inner(cid); } +} diff --git a/bvm/Shaders/dao-vote/parser.wasm b/bvm/Shaders/dao-vote/parser.wasm new file mode 100755 index 0000000000..c4ba83687d Binary files /dev/null and b/bvm/Shaders/dao-vote/parser.wasm differ diff --git a/bvm/Shaders/dummy/app.wasm b/bvm/Shaders/dummy/app.wasm old mode 100644 new mode 100755 index d5b1bf9a0a..acf0a21c0c Binary files a/bvm/Shaders/dummy/app.wasm and b/bvm/Shaders/dummy/app.wasm differ diff --git a/bvm/Shaders/dummy/contract.wasm b/bvm/Shaders/dummy/contract.wasm old mode 100644 new mode 100755 index 96faf41edb..169a37693e Binary files a/bvm/Shaders/dummy/contract.wasm and b/bvm/Shaders/dummy/contract.wasm differ diff --git a/bvm/Shaders/faucet/app.wasm b/bvm/Shaders/faucet/app.wasm old mode 100644 new mode 100755 index 02e568fde0..1356b7e82f Binary files a/bvm/Shaders/faucet/app.wasm and b/bvm/Shaders/faucet/app.wasm differ diff --git a/bvm/Shaders/faucet/contract.wasm b/bvm/Shaders/faucet/contract.wasm old mode 100644 new mode 100755 index f1b72b4a67..1d0a458a79 Binary files a/bvm/Shaders/faucet/contract.wasm and b/bvm/Shaders/faucet/contract.wasm differ diff --git a/bvm/Shaders/faucet/parser.cpp b/bvm/Shaders/faucet/parser.cpp new file mode 100644 index 0000000000..dc9640cf4b --- /dev/null +++ b/bvm/Shaders/faucet/parser.cpp @@ -0,0 +1,38 @@ +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static const ShaderID s_pSid[] = { Faucet::s_SID }; + +static void OnKind() { Env::DocAddText("kind", "Faucet"); } + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 0: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(Faucet::Params)) + { + auto* p = (const Faucet::Params*) pArg; + Env::DocGroup gr("params"); + Env::DocAddNum("Backlog period", p->m_BacklogPeriod); + DocAddAmount("Max withdraw", p->m_MaxWithdraw); + } + break; + + case 1: Env::DocAddText("method", "Destroy"); break; + + case Faucet::Deposit::s_iMethod: Env::DocAddText("method", "deposit"); break; + case Faucet::Withdraw::s_iMethod: Env::DocAddText("method", "withdraw"); break; + } +} + +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} + +PARSER_MODULE_EXPORT_SIDS(s_pSid) +PARSER_MODULE_EXPORT_KIND_ONLY(OnKind) diff --git a/bvm/Shaders/faucet/parser.wasm b/bvm/Shaders/faucet/parser.wasm new file mode 100755 index 0000000000..f81ee119d1 Binary files /dev/null and b/bvm/Shaders/faucet/parser.wasm differ diff --git a/bvm/Shaders/faucet2/app.wasm b/bvm/Shaders/faucet2/app.wasm old mode 100644 new mode 100755 index cb85aca997..081e3a60a5 Binary files a/bvm/Shaders/faucet2/app.wasm and b/bvm/Shaders/faucet2/app.wasm differ diff --git a/bvm/Shaders/faucet2/contract.wasm b/bvm/Shaders/faucet2/contract.wasm old mode 100644 new mode 100755 index 4fab4dbcc5..d439f24c12 Binary files a/bvm/Shaders/faucet2/contract.wasm and b/bvm/Shaders/faucet2/contract.wasm differ diff --git a/bvm/Shaders/faucet2/parser.cpp b/bvm/Shaders/faucet2/parser.cpp new file mode 100644 index 0000000000..d4a7642c53 --- /dev/null +++ b/bvm/Shaders/faucet2/parser.cpp @@ -0,0 +1,92 @@ +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static const ShaderID s_pSid[] = { Faucet2::s_SID }; + +static void OnKind() { Env::DocAddText("kind", "Faucet2"); } + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case Faucet2::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + break; + + case 1: Env::DocAddText("method", "Destroy"); break; + + case Faucet2::Method::Deposit::s_iMethod: + Env::DocAddText("method", "Deposit"); + break; + + case Faucet2::Method::Withdraw::s_iMethod: + Env::DocAddText("method", "Withdraw"); + break; + + case Faucet2::Method::AdminCtl::s_iMethod: + Env::DocAddText("method", "Admin-Ctl"); + if (nArg >= sizeof(Faucet2::Method::AdminCtl)) + { + auto* p = (const Faucet2::Method::AdminCtl*) pArg; + Env::DocGroup gr("params"); + Env::DocAddNum32("Enable", p->m_Enable); + } + break; + + case Faucet2::Method::AdminWithdraw::s_iMethod: + Env::DocAddText("method", "Admin-Withdraw"); + break; + } +} + +static void OnState_Inner(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = Faucet2::State::s_Key; + + Faucet2::State s; + if (!Env::VarReader::Read_T(k, s)) + return; + + Env::DocAddNum("Enabled", (uint32_t) s.m_Enabled); + DocAddHeight1("Last withdraw", s.m_Epoch.m_Height); + DocAddAmount("Epoch withdraw remaining", s.m_Epoch.m_Amount); + + { + Env::DocGroup gr("Settings"); + + Env::DocAddNum("Epoch duration", s.m_Params.m_Limit.m_Height); + DocAddAmount("Epoch Withdraw limit", s.m_Params.m_Limit.m_Amount); + DocAddPk("Admin", s.m_Params.m_pkAdmin); + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, s_pSid, _countof(s_pSid)); +} + +BEAM_EXPORT void Method_0(const ShaderID& /*sid*/, const ContractID& /*cid*/, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); + OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} + +BEAM_EXPORT void Method_1(const ShaderID& /*sid*/, const ContractID& /*cid*/) +{ + Env::DocGroup gr(""); + OnKind(); +} + +BEAM_EXPORT void Method_2(const ShaderID& /*sid*/, const ContractID& cid) +{ + Env::DocGroup gr(""); + OnKind(); + { + Env::DocGroup grSt("State"); + OnState_Inner(cid); + } +} diff --git a/bvm/Shaders/faucet2/parser.wasm b/bvm/Shaders/faucet2/parser.wasm new file mode 100755 index 0000000000..004cc0033b Binary files /dev/null and b/bvm/Shaders/faucet2/parser.wasm differ diff --git a/bvm/Shaders/fuddle/contract.wasm b/bvm/Shaders/fuddle/contract.wasm old mode 100644 new mode 100755 index 12b6d0e14d..e7a1c0c511 Binary files a/bvm/Shaders/fuddle/contract.wasm and b/bvm/Shaders/fuddle/contract.wasm differ diff --git a/bvm/Shaders/gallery/app-admin.wasm b/bvm/Shaders/gallery/app-admin.wasm old mode 100644 new mode 100755 index 4b65a83114..8ce180cad8 Binary files a/bvm/Shaders/gallery/app-admin.wasm and b/bvm/Shaders/gallery/app-admin.wasm differ diff --git a/bvm/Shaders/gallery/app.wasm b/bvm/Shaders/gallery/app.wasm old mode 100644 new mode 100755 index da1b9a708b..6fbe81a464 Binary files a/bvm/Shaders/gallery/app.wasm and b/bvm/Shaders/gallery/app.wasm differ diff --git a/bvm/Shaders/gallery/contract.wasm b/bvm/Shaders/gallery/contract.wasm old mode 100644 new mode 100755 index aee67bf463..f3bf6bf056 Binary files a/bvm/Shaders/gallery/contract.wasm and b/bvm/Shaders/gallery/contract.wasm differ diff --git a/bvm/Shaders/gallery/parser.cpp b/bvm/Shaders/gallery/parser.cpp new file mode 100644 index 0000000000..3cd0dd1c71 --- /dev/null +++ b/bvm/Shaders/gallery/parser.cpp @@ -0,0 +1,142 @@ +// Parser module for Gallery (versions 0, 1, 2 — same method shape). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static void OnKind(const ShaderID& sid) +{ + for (uint32_t i = 0; i < _countof(Gallery::s_pSID); i++) + { + if (_POD_(sid) == Gallery::s_pSID[i]) + { + char szBuf[16] = "Gallery v"; + Utils::String::Decimal::Print(szBuf + 9, i); + Env::DocAddText("kind", szBuf); + return; + } + } + Env::DocAddText("kind", "Gallery"); +} + +static void WriteGalleryAdrID(Gallery::Masterpiece::ID id) { Env::DocAddNum("art_id", Utils::FromBE(id)); } +static void WriteGalleryPrice(const Gallery::AmountWithAsset& x) { DocAddAidAmount("Price", x.m_Aid, x.m_Amount); } + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 0: Env::DocAddText("method", "Create"); break; + case 1: Env::DocAddText("method", "Destroy"); break; + + case Gallery::Method::AddExhibit::s_iMethod: + if (nArg >= sizeof(Gallery::Method::AddExhibit)) + { + auto* p = (const Gallery::Method::AddExhibit*) pArg; + Env::DocAddText("method", "AddExhibit"); + Env::DocGroup gr("params"); + DocAddPk("pkUser", p->m_pkArtist); + Env::DocAddNum("size", p->m_Size); + } + break; + + case Gallery::Method::ManageArtist::s_iMethod: + if (nArg >= sizeof(Gallery::Method::ManageArtist)) + { + auto* p = (const Gallery::Method::ManageArtist*) pArg; + Env::DocAddText("method", "ManageArtist"); + Env::DocGroup gr("params"); + DocAddPk("pkUser", p->m_pkArtist); + DocAddTextLen("name", p + 1, p->m_LabelLen); + } + break; + + case Gallery::Method::SetPrice::s_iMethod: + if (nArg >= sizeof(Gallery::Method::SetPrice)) + { + auto* p = (const Gallery::Method::SetPrice*) pArg; + Env::DocAddText("method", "SetPrice"); + Env::DocGroup gr("params"); + WriteGalleryAdrID(p->m_ID); + WriteGalleryPrice(p->m_Price); + } + break; + + case Gallery::Method::Buy::s_iMethod: + if (nArg >= sizeof(Gallery::Method::Buy)) + { + auto* p = (const Gallery::Method::Buy*) pArg; + Env::DocAddText("method", "Buy"); + Env::DocGroup gr("params"); + WriteGalleryAdrID(p->m_ID); + DocAddPk("pkUser", p->m_pkUser); + Env::DocAddNum32("hasAid", p->m_HasAid); + DocAddAmount("payMax", p->m_PayMax); + } + break; + + case Gallery::Method::Transfer::s_iMethod: + if (nArg >= sizeof(Gallery::Method::Transfer)) + { + auto* p = (const Gallery::Method::Transfer*) pArg; + Env::DocAddText("method", "Transfer"); + Env::DocGroup gr("params"); + WriteGalleryAdrID(p->m_ID); + DocAddPk("newPkUser", p->m_pkNewOwner); + } + break; + + case Gallery::Method::Withdraw::s_iMethod: + if (nArg >= sizeof(Gallery::Method::Withdraw)) + { + auto* p = (const Gallery::Method::Withdraw*) pArg; + Env::DocAddText("method", "Withdraw"); + Env::DocGroup gr("params"); + DocAddPk("key", p->m_Key.m_pkUser); + DocAddAidAmount("Value", p->m_Key.m_Aid, p->m_Value); + } + break; + + case Gallery::Method::AddVoteRewards::s_iMethod: + if (nArg >= sizeof(Gallery::Method::AddVoteRewards)) + { + auto* p = (const Gallery::Method::AddVoteRewards*) pArg; + Env::DocAddText("method", "AddVoteRewards"); + Env::DocGroup gr("params"); + DocAddAmount("amount", p->m_Amount); + } + break; + + case Gallery::Method::Vote::s_iMethod: + if (nArg >= sizeof(Gallery::Method::Vote)) + { + auto* p = (const Gallery::Method::Vote*) pArg; + Env::DocAddText("method", "Vote"); + Env::DocGroup gr("params"); + WriteGalleryAdrID(p->m_ID.m_MasterpieceID); + Env::DocAddNum("impression", p->m_Impression.m_Value); + } + break; + + case Gallery::Method::AdminDelete::s_iMethod: + if (nArg >= sizeof(Gallery::Method::AdminDelete)) + { + auto* p = (const Gallery::Method::AdminDelete*) pArg; + Env::DocAddText("method", "AdminDelete"); + Env::DocGroup gr("params"); + WriteGalleryAdrID(p->m_ID); + } + break; + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, Gallery::s_pSID, _countof(Gallery::s_pSID)); +} +BEAM_EXPORT void Method_0(const ShaderID& sid, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(sid); + OnMethod_Inner(iMethod, pArg, nArg); +} +BEAM_EXPORT void Method_1(const ShaderID& sid, const ContractID&) { Env::DocGroup gr(""); OnKind(sid); } +BEAM_EXPORT void Method_2(const ShaderID& sid, const ContractID&) { Env::DocGroup gr(""); OnKind(sid); } diff --git a/bvm/Shaders/gallery/parser.wasm b/bvm/Shaders/gallery/parser.wasm new file mode 100755 index 0000000000..737b3e9a73 Binary files /dev/null and b/bvm/Shaders/gallery/parser.wasm differ diff --git a/bvm/Shaders/make_all.sh b/bvm/Shaders/make_all.sh new file mode 100755 index 0000000000..9e9e025767 --- /dev/null +++ b/bvm/Shaders/make_all.sh @@ -0,0 +1,113 @@ +#!/bin/sh +# Build every shader. Optional --export [out_dir] also collects per-contract +# parser modules into a single folder ready for an explorer's +# --contract_rich_parser_folder. Default out_dir: Explorer/modules/ +# +# Usage: +# make_all.sh # build only +# make_all.sh --export # build, export to Explorer/modules/ +# make_all.sh --export # build, export to +set -e +cd "$(dirname "$0")" + +EXPORT_FLAGS="" +if [ "$1" = "--export" ]; then + OUT_DIR="${2:-Explorer/modules}" + EXPORT_FLAGS="--export $OUT_DIR" + mkdir -p "$OUT_DIR" + find "$OUT_DIR" -name '*.wasm' -delete +fi + +build() { + ./make_shader.sh $EXPORT_FLAGS "$1" +} + +build amm/app +build amm/contract +build amm/parser +build asset_man/app +build asset_man/contract +build bans/app +build bans/contract +build bans/parser +build blackhole/app +build blackhole/contract +build blackhole/parser +build aphorize/contract +build dao-accumulator/app +build dao-accumulator/contract +build dao-accumulator/parser +build dao-core/app +build dao-core/app-admin +build dao-core/contract +build dao-core/parser +build dao-core-masternet/app +build dao-core-masternet/app-admin +build dao-core-masternet/contract +build dao-core-testnet/app +build dao-core-testnet/app-admin +build dao-core-testnet/contract +build dao-core2/app +build dao-core2/contract +build dao-core2/parser +build dao-vote/app +build dao-vote/contract +build dao-vote/parser +build dao-vault/app +build dao-vault/contract +build dao-vault/parser +build dummy/app +build dummy/contract +build faucet/app +build faucet/contract +build faucet/parser +build faucet2/app +build faucet2/contract +build faucet2/parser +build fuddle/contract +build gallery/app +build gallery/app-admin +build gallery/contract +build gallery/parser +build minter/app +build minter/contract +build minter/parser +build mirrorcoin/app +build mirrorcoin/contract +build nephrite/app +build nephrite/contract +build nephrite/parser +build oracle/contract +build oracle2/app +build oracle2/contract +build oracle2/parser +build perpetual/app +build perpetual/contract +build pipe/contract +build playground/app +build playground/contract +build profit_pool/app +build profit_pool/contract +build roulette/app +build roulette/contract +build sidechain/contract +build sidechain_pos/parser +build pbft/parser +build StableCoin/contract +build upgradable/contract +build upgradable2/contract +build upgradable2/Test/test_app +build upgradable2/Test/test_v0 +build upgradable2/Test/test_v1 +build upgradable3/Test/test_app +build upgradable3/Test/test_v0 +build upgradable3/Test/test_v1 +build upgradable3/Test/test_v0_migrate +build vault/app +build vault/contract +build vault/parser +build vault_anon/app +build vault_anon/contract +build vault_anon/parser +build voting/app +build voting/contract diff --git a/bvm/Shaders/make_shader.sh b/bvm/Shaders/make_shader.sh new file mode 100755 index 0000000000..972aacfc1b --- /dev/null +++ b/bvm/Shaders/make_shader.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# Build a wasm shader. Optional --export additionally copies +# parser modules (basename "parser") into for bundling into +# an explorer --contract_rich_parser_folder. No-op for non-parser targets. +# +# Usage: +# make_shader.sh # build only +# make_shader.sh --export # build, then export if parser + +CLANG="${CLANG:-/opt/homebrew/opt/llvm/bin/clang}" + +EXPORT_DIR="" +if [ "$1" = "--export" ]; then + EXPORT_DIR="$2" + shift 2 +fi + +NAME="$1" + +"$CLANG" -O3 --target=wasm32 -std=c++17 -fno-rtti \ + -Wl,--export-dynamic,--no-entry,--allow-undefined \ + -nostdlib "$NAME.cpp" --output "$NAME.wasm" + +if [ -n "$EXPORT_DIR" ]; then + case "$NAME" in + */parser) + mkdir -p "$EXPORT_DIR" + BASENAME=$(dirname "$NAME") + cp "$NAME.wasm" "$EXPORT_DIR/$BASENAME.parser.wasm" + ;; + esac +fi diff --git a/bvm/Shaders/minter/app.wasm b/bvm/Shaders/minter/app.wasm old mode 100644 new mode 100755 index 67399805cb..d5e0b79579 Binary files a/bvm/Shaders/minter/app.wasm and b/bvm/Shaders/minter/app.wasm differ diff --git a/bvm/Shaders/minter/contract.wasm b/bvm/Shaders/minter/contract.wasm old mode 100644 new mode 100755 index 5a193734db..354e01120f Binary files a/bvm/Shaders/minter/contract.wasm and b/bvm/Shaders/minter/contract.wasm differ diff --git a/bvm/Shaders/minter/parser.cpp b/bvm/Shaders/minter/parser.cpp new file mode 100644 index 0000000000..a40b5850ff --- /dev/null +++ b/bvm/Shaders/minter/parser.cpp @@ -0,0 +1,157 @@ +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static const ShaderID s_pSid[] = { Minter::s_SID }; + +static void OnKind() { Env::DocAddText("kind", "Minter"); } + +static void WriteMinterSettings(const Minter::Settings& stg) +{ + DocAddCid("Dao-Vault", stg.m_cidDaoVault); + DocAddAmount("Issuance fee", stg.m_IssueFee); +} + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case Minter::Method::Init::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(Minter::Method::Init)) + { + auto* p = (const Minter::Method::Init*) pArg; + Env::DocGroup gr("params"); + WriteMinterSettings(p->m_Settings); + } + break; + + case 1: Env::DocAddText("method", "Destroy"); break; + + case Minter::Method::View::s_iMethod: + if (nArg >= sizeof(Minter::Method::View)) + { + auto* p = (const Minter::Method::View*) pArg; + Env::DocAddText("method", "View"); + Env::DocGroup gr("params"); + DocAddAid("aid", p->m_Aid); + } + break; + + case Minter::Method::CreateToken::s_iMethod: + if (nArg >= sizeof(Minter::Method::CreateToken)) + { + auto* p = (const Minter::Method::CreateToken*) pArg; + Env::DocAddText("method", "Create token"); + Env::DocGroup gr("params"); + DocAddAmountBig("Limit", p->m_Limit.m_Lo, p->m_Limit.m_Hi); + if (Minter::PubKeyFlag::s_Cid == p->m_pkOwner.m_Y) + DocAddCid("Owner", p->m_pkOwner.m_X); + else + DocAddPk("Owner", p->m_pkOwner); + } + break; + + case Minter::Method::Withdraw::s_iMethod: + if (nArg >= sizeof(Minter::Method::Withdraw)) + { + auto* p = (const Minter::Method::Withdraw*) pArg; + Env::DocAddText("method", "Withdraw"); + Env::DocGroup gr("params"); + DocAddAmount("amount", p->m_Value); + DocAddAid("aid", p->m_Aid); + } + break; + } +} + +static void OnState_Inner(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = Minter::Tags::s_Settings; + + Minter::Settings s; + if (!Env::VarReader::Read_T(k, s)) + return; + + { + Env::DocGroup gr2("Settings"); + WriteMinterSettings(s); + } + + { + Env::DocGroup gr2("Tokens"); + DocSetType("table"); + Env::DocArray gr3("value"); + + { + Env::DocArray gr4(""); + DocAddTableHeader("Aid"); + DocAddTableHeader("Metadata"); + DocAddTableHeader("Owner"); + DocAddTableHeader("Minted"); + DocAddTableHeader("Limit"); + } + + Env::Key_T k0, k1; + _POD_(k0.m_Prefix.m_Cid) = cid; + _POD_(k1.m_Prefix.m_Cid) = cid; + k0.m_KeyInContract.m_Aid = 0; + k1.m_KeyInContract.m_Aid = (AssetID) -1; + + for (Env::VarReader r(k0, k1); ; ) + { + Minter::Token mt; + if (!r.MoveNext_T(k0, mt)) + break; + + Env::DocArray gr4(""); + + DocAddAid("", k0.m_KeyInContract.m_Aid); + + char szMetadata[1024 * 16 + 1]; + AssetInfo ai; + auto nMetadata = Env::get_AssetInfo(k0.m_KeyInContract.m_Aid, ai, szMetadata, sizeof(szMetadata) - 1); + szMetadata[nMetadata] = 0; + + Env::DocAddText("", szMetadata); + + if (Minter::PubKeyFlag::s_Cid & mt.m_pkOwner.m_Y) + DocAddCid("", mt.m_pkOwner.m_X); + else + DocAddMonoblob("", mt.m_pkOwner); + + DocAddAmountBig("", mt.m_Minted.m_Lo, mt.m_Minted.m_Hi); + DocAddAmountBig("", mt.m_Limit.m_Lo, mt.m_Limit.m_Hi); + } + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, s_pSid, _countof(s_pSid)); +} + +BEAM_EXPORT void Method_0(const ShaderID& /*sid*/, const ContractID& /*cid*/, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); + OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} + +BEAM_EXPORT void Method_1(const ShaderID& /*sid*/, const ContractID& /*cid*/) +{ + Env::DocGroup gr(""); + OnKind(); +} + +BEAM_EXPORT void Method_2(const ShaderID& /*sid*/, const ContractID& cid) +{ + Env::DocGroup gr(""); + OnKind(); + { + Env::DocGroup grSt("State"); + OnState_Inner(cid); + } +} diff --git a/bvm/Shaders/minter/parser.wasm b/bvm/Shaders/minter/parser.wasm new file mode 100755 index 0000000000..7892f6a988 Binary files /dev/null and b/bvm/Shaders/minter/parser.wasm differ diff --git a/bvm/Shaders/mirrorcoin/app.wasm b/bvm/Shaders/mirrorcoin/app.wasm old mode 100644 new mode 100755 index b789ee1e90..f3de137116 Binary files a/bvm/Shaders/mirrorcoin/app.wasm and b/bvm/Shaders/mirrorcoin/app.wasm differ diff --git a/bvm/Shaders/mirrorcoin/contract.wasm b/bvm/Shaders/mirrorcoin/contract.wasm old mode 100644 new mode 100755 index aa283e8acc..e1722f66a6 Binary files a/bvm/Shaders/mirrorcoin/contract.wasm and b/bvm/Shaders/mirrorcoin/contract.wasm differ diff --git a/bvm/Shaders/nephrite/app.wasm b/bvm/Shaders/nephrite/app.wasm old mode 100644 new mode 100755 index b869bfa937..b4c75058d1 Binary files a/bvm/Shaders/nephrite/app.wasm and b/bvm/Shaders/nephrite/app.wasm differ diff --git a/bvm/Shaders/nephrite/contract.wasm b/bvm/Shaders/nephrite/contract.wasm old mode 100644 new mode 100755 index 12cc15c559..4e3d815a0b Binary files a/bvm/Shaders/nephrite/contract.wasm and b/bvm/Shaders/nephrite/contract.wasm differ diff --git a/bvm/Shaders/nephrite/parser.cpp b/bvm/Shaders/nephrite/parser.cpp new file mode 100644 index 0000000000..cb72c2b204 --- /dev/null +++ b/bvm/Shaders/nephrite/parser.cpp @@ -0,0 +1,324 @@ +// Parser module for Nephrite (versioned, behind Upgradable3). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "../oracle2/contract.h" +#include "contract.h" + +template +struct NephriteEpochStorage +{ + const ContractID& m_Cid; + NephriteEpochStorage(const ContractID& cid) :m_Cid(cid) {} + + template + void Load(uint32_t iEpoch, HomogenousPool::Epoch& e) + { + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = m_Cid; + k.m_KeyInContract.m_Tag = nTag; + k.m_KeyInContract.m_iEpoch = iEpoch; + Env::Halt_if(!Env::VarReader::Read_T(k, e)); + } + + template + void Save(uint32_t, const HomogenousPool::Epoch&) {} + void Del(uint32_t) {} +}; + +static void OnKind() { Env::DocAddText("kind", "Nephrite"); } + +static void WriteNephriteSettings(const Nephrite::Settings& stg) +{ + DocAddCid("oracle", stg.m_cidOracle1); + DocAddCid("oracle-backup", stg.m_cidOracle2); + DocAddCid("Dao-Vault", stg.m_cidDaoVault); + DocAddAmount("Liquidation Reserve", stg.m_TroveLiquidationReserve); + DocAddHeight("Min Redemption Height", stg.m_hMinRedemptionHeight); + DocAddAid("Gov Token", stg.m_AidGov); +} + +static bool get_Oracle2Median(MultiPrecision::Float& ret, const ContractID& cid) +{ + Env::Key_T key; + _POD_(key.m_Prefix.m_Cid) = cid; + key.m_KeyInContract = Oracle2::Tags::s_Median; + + Oracle2::Median med; + if (!Env::VarReader::Read_T(key, med)) + return false; + + if (med.m_hEnd < Env::get_Height()) + return false; + + ret = med.m_Res; + return true; +} + +static void AddTroveNumber(const ContractID& cid, const Nephrite::Method::BaseTxTrove* pArg) +{ + uint32_t iTrove; + + if (pArg && pArg->m_iPrev0) + { + Env::Key_T tk; + _POD_(tk.m_Prefix.m_Cid) = cid; + tk.m_KeyInContract.m_iTrove = pArg->m_iPrev0; + + Nephrite::Trove t; + if (!Env::VarReader::Read_T(tk, t)) + return; + + iTrove = t.m_iNext; + } + else + { + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = Nephrite::Tags::s_State; + + Nephrite::Global g; + if (!Env::VarReader::Read_T(k, g)) + return; + + iTrove = pArg ? g.m_Troves.m_iHead : (g.m_Troves.m_iLastCreated + 1); + } + + Env::DocAddNum("Number", iTrove); +} + +static void OnMethod_Inner(const ContractID& cid, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 1: Env::DocAddText("method", "Destroy"); break; + + case Nephrite::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(Nephrite::Method::Create)) + { + auto* p = (const Nephrite::Method::Create*) pArg; + Env::DocGroup gr("params"); + WriteNephriteSettings(p->m_Settings); + WriteUpgradeSettings(p->m_Upgradable); + } + break; + + case Upgradable3::Method::Control::s_iMethod: + // Control method handling intentionally minimal — host emits wrapper info. + Env::DocAddText("method", "Upgradable3 Control"); + break; + + case Nephrite::Method::TroveOpen::s_iMethod: + if (nArg >= sizeof(Nephrite::Method::TroveOpen)) + { + auto* p = (const Nephrite::Method::TroveOpen*) pArg; + Env::DocAddText("method", "Trove Open"); + Env::DocGroup gr("params"); + AddTroveNumber(cid, nullptr); + DocAddAmount("Col", p->m_Amounts.Col); + DocAddAmount("Tok", p->m_Amounts.Tok); + } + break; + + case Nephrite::Method::TroveClose::s_iMethod: + if (nArg >= sizeof(Nephrite::Method::TroveClose)) + { + auto* p = (const Nephrite::Method::TroveClose*) pArg; + Env::DocAddText("method", "Trove Close"); + Env::DocGroup gr("params"); + AddTroveNumber(cid, p); + } + break; + + case Nephrite::Method::TroveModify::s_iMethod: + if (nArg >= sizeof(Nephrite::Method::TroveModify)) + { + auto* p = (const Nephrite::Method::TroveModify*) pArg; + Env::DocAddText("method", "Trove Modify"); + Env::DocGroup gr("params"); + AddTroveNumber(cid, p); + DocAddAmount("Col", p->m_Amounts.Col); + DocAddAmount("Tok", p->m_Amounts.Tok); + } + break; + + case Nephrite::Method::FundsAccess::s_iMethod: + Env::DocAddText("method", "Funds Access"); + break; + + case Nephrite::Method::UpdStabPool::s_iMethod: + if (nArg >= sizeof(Nephrite::Method::UpdStabPool)) + { + auto* p = (const Nephrite::Method::UpdStabPool*) pArg; + Env::DocAddText("method", "Stability Pool update"); + Env::DocGroup gr("params"); + DocAddAmount("New Amount", p->m_NewAmount); + } + break; + + case Nephrite::Method::Liquidate::s_iMethod: + if (nArg >= sizeof(Nephrite::Method::Liquidate)) + { + auto* p = (const Nephrite::Method::Liquidate*) pArg; + Env::DocAddText("method", "Liquidate troves"); + Env::DocGroup gr("params"); + Env::DocAddNum("Count", p->m_Count); + } + break; + + case Nephrite::Method::Redeem::s_iMethod: + if (nArg >= sizeof(Nephrite::Method::Redeem)) + { + auto* p = (const Nephrite::Method::Redeem*) pArg; + Env::DocAddText("method", "Redeem"); + Env::DocGroup gr("params"); + DocAddAmount("Amount", p->m_Amount); + } + break; + + case Nephrite::Method::AddStabPoolReward::s_iMethod: + if (nArg >= sizeof(Nephrite::Method::AddStabPoolReward)) + { + auto* p = (const Nephrite::Method::AddStabPoolReward*) pArg; + Env::DocAddText("method", "Add Stability Pool Reward"); + Env::DocGroup gr("params"); + DocAddAmount("Amount", p->m_Amount); + } + break; + } +} + +static void OnState_Inner(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = Nephrite::Tags::s_State; + + Nephrite::Global g; + if (!Env::VarReader::Read_T(k, g)) + return; + + { + Env::DocGroup gr2("Settings"); + WriteNephriteSettings(g.m_Settings); + } + + DocAddAid("Token", g.m_Aid); + Env::DocAddNum("Troves created", g.m_Troves.m_iLastCreated); + + { + Env::DocGroup gr2("Totals"); + DocAddAmount("Col", g.m_Troves.m_Totals.Col); + DocAddAmount("Tok", g.m_Troves.m_Totals.Tok); + } + + Nephrite::Global::Price price; + const char* szPriceSource; + bool bHavePrice = true; + + if (get_Oracle2Median(price.m_Value, g.m_Settings.m_cidOracle1) && price.IsSane(price.m_Value)) + szPriceSource = "Main Oracle"; + else if (get_Oracle2Median(price.m_Value, g.m_Settings.m_cidOracle2) && price.IsSane(price.m_Value)) + szPriceSource = "Backup Oracle"; + else + { + szPriceSource = "Unavailable"; + bHavePrice = false; + } + + Env::DocAddText("Price feed", szPriceSource); + if (bHavePrice) + { + DocAddFloat("Price", price.m_Value); + if (g.m_Troves.m_iHead) + { + DocAddPerc("TCR", price.ToCR(g.m_Troves.m_Totals.get_Rcr())); + Env::DocAddText("Recovery mode", g.IsRecovery(price) ? "Yes" : "No"); + } + } + + g.m_BaseRate.Decay(); + DocAddPerc("Fee boost", g.m_BaseRate.m_k); + + { + Env::DocGroup gr2("Troves"); + DocSetType("table"); + Env::DocArray gr3("value"); + + { + Env::DocArray gr4(""); + DocAddTableHeader("Number"); + DocAddTableHeader("Key"); + DocAddTableHeader("Col"); + DocAddTableHeader("Tok"); + DocAddTableHeader("ICR"); + } + + Utils::Vector vec; + vec.Prepare(g.m_Troves.m_iLastCreated); + + { + Env::Key_T tk0, tk1; + _POD_(tk0.m_Prefix.m_Cid) = cid; + _POD_(tk1.m_Prefix.m_Cid) = cid; + tk0.m_KeyInContract.m_iTrove = 0; + tk1.m_KeyInContract.m_iTrove = (Nephrite::Trove::ID) -1; + + for (Env::VarReader r(tk0, tk1); ; ) + { + Nephrite::Trove t; + if (!r.MoveNext_T(tk0, t)) + break; + vec.Prepare(tk0.m_KeyInContract.m_iTrove); + _POD_(vec.m_p[tk0.m_KeyInContract.m_iTrove - 1]) = t; + } + } + + for (auto iTrove = g.m_Troves.m_iHead; iTrove; ) + { + Nephrite::Trove& t = vec.m_p[iTrove - 1]; + NephriteEpochStorage storR(cid); + auto vals = g.m_RedistPool.get_UpdatedAmounts(t, storR); + + Env::DocArray gr4(""); + Env::DocAddNum("", iTrove); + DocAddPk("", t.m_pkOwner); + DocAddAmount("", vals.Col); + DocAddAmount("", vals.Tok); + + if (bHavePrice) + DocAddPerc("", price.ToCR(t.m_Amounts.get_Rcr())); + else + Env::DocAddText("", ""); + + iTrove = t.m_iNext; + } + } + + g.m_StabPool.AddReward(Env::get_Height()); + + { + Env::DocGroup gr2("Stability pool"); + DocAddAmount("Tok", g.m_StabPool.get_TotalSell()); + DocAddAmount("Col", g.m_StabPool.m_Active.m_pDim[0].m_Buy + g.m_StabPool.m_Draining.m_pDim[0].m_Buy); + DocAddAmount("BeamX", g.m_StabPool.m_Active.m_pDim[1].m_Buy + g.m_StabPool.m_Draining.m_pDim[1].m_Buy); + } + + DocAddAmount("BeamX reward remaining", g.m_StabPool.m_Reward.m_Remaining); +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, Nephrite::s_pSID, _countof(Nephrite::s_pSID)); +} +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID& cid, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(cid, iMethod, pArg, nArg); +} +BEAM_EXPORT void Method_1(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); OnKind(); } +BEAM_EXPORT void Method_2(const ShaderID&, const ContractID& cid) +{ + Env::DocGroup gr(""); OnKind(); + { Env::DocGroup grSt("State"); OnState_Inner(cid); } +} diff --git a/bvm/Shaders/nephrite/parser.wasm b/bvm/Shaders/nephrite/parser.wasm new file mode 100755 index 0000000000..90aaac2407 Binary files /dev/null and b/bvm/Shaders/nephrite/parser.wasm differ diff --git a/bvm/Shaders/oracle/contract.wasm b/bvm/Shaders/oracle/contract.wasm old mode 100644 new mode 100755 index d806478aa1..eb512c2d0e Binary files a/bvm/Shaders/oracle/contract.wasm and b/bvm/Shaders/oracle/contract.wasm differ diff --git a/bvm/Shaders/oracle2/app.wasm b/bvm/Shaders/oracle2/app.wasm old mode 100644 new mode 100755 index 5aca295168..7b6f31a461 Binary files a/bvm/Shaders/oracle2/app.wasm and b/bvm/Shaders/oracle2/app.wasm differ diff --git a/bvm/Shaders/oracle2/contract.wasm b/bvm/Shaders/oracle2/contract.wasm old mode 100644 new mode 100755 index 6088cc91c2..82ce8f7901 Binary files a/bvm/Shaders/oracle2/contract.wasm and b/bvm/Shaders/oracle2/contract.wasm differ diff --git a/bvm/Shaders/oracle2/parser.cpp b/bvm/Shaders/oracle2/parser.cpp new file mode 100644 index 0000000000..38e60d1905 --- /dev/null +++ b/bvm/Shaders/oracle2/parser.cpp @@ -0,0 +1,190 @@ +// Parser module for Oracle2 (versioned, behind Upgradable3). +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static void OnKind() { Env::DocAddText("kind", "Oracle2"); } + +static void WriteOracle2Settings(const Oracle2::Settings& stg) +{ + Env::DocAddNum("Validity Period", stg.m_hValidity); + Env::DocAddNum("Min Providers", stg.m_MinProviders); +} + +static bool get_Oracle2Median(MultiPrecision::Float& ret, const ContractID& cid) +{ + Env::Key_T key; + _POD_(key.m_Prefix.m_Cid) = cid; + key.m_KeyInContract = Oracle2::Tags::s_Median; + + Oracle2::Median med; + if (!Env::VarReader::Read_T(key, med)) + return false; + if (med.m_hEnd < Env::get_Height()) + return false; + + ret = med.m_Res; + return true; +} + +static void OnMethod_Inner(const ContractID& cid, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 1: Env::DocAddText("method", "Destroy"); break; + + case Oracle2::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(Oracle2::Method::Create)) + { + auto* p = (const Oracle2::Method::Create*) pArg; + Env::DocGroup gr("params"); + WriteOracle2Settings(p->m_Settings); + WriteUpgradeSettings(p->m_Upgradable); + } + break; + + case Oracle2::Method::Get::s_iMethod: + if (nArg >= sizeof(Oracle2::Method::Get)) + { + Env::DocAddText("method", "Get"); + Env::DocGroup gr("params"); + MultiPrecision::Float val; + if (get_Oracle2Median(val, cid)) + DocAddFloat("Result", val); + else + Env::DocAddText("Result", "NaN"); + } + break; + + case Oracle2::Method::FeedData::s_iMethod: + if (nArg >= sizeof(Oracle2::Method::FeedData)) + { + auto* p = (const Oracle2::Method::FeedData*) pArg; + Env::DocAddText("method", "FeedData"); + Env::DocGroup gr("params"); + Env::DocAddNum("iProvider", p->m_iProvider); + DocAddFloat("Value", p->m_Value); + } + break; + + case Oracle2::Method::SetSettings::s_iMethod: + if (nArg >= sizeof(Oracle2::Method::SetSettings)) + { + auto* p = (const Oracle2::Method::SetSettings*) pArg; + Env::DocAddText("method", "SetSettings"); + Env::DocGroup gr("params"); + WriteOracle2Settings(p->m_Settings); + WriteUpgradeAdminsMask(p->m_ApproveMask); + } + break; + + case Oracle2::Method::ProviderAdd::s_iMethod: + if (nArg >= sizeof(Oracle2::Method::ProviderAdd)) + { + auto* p = (const Oracle2::Method::ProviderAdd*) pArg; + Env::DocAddText("method", "ProviderAdd"); + Env::DocGroup gr("params"); + DocAddPk("pk", p->m_pk); + WriteUpgradeAdminsMask(p->m_ApproveMask); + } + break; + + case Oracle2::Method::ProviderDel::s_iMethod: + if (nArg >= sizeof(Oracle2::Method::ProviderDel)) + { + auto* p = (const Oracle2::Method::ProviderDel*) pArg; + Env::DocAddText("method", "ProviderDel"); + Env::DocGroup gr("params"); + Env::DocAddNum("iProvider", p->m_iProvider); + WriteUpgradeAdminsMask(p->m_ApproveMask); + } + break; + } +} + +static void OnState_Inner(const ContractID& cid) +{ + Oracle2::StateMax g; + uint32_t nProvs = 0; + + Env::Key_T key; + _POD_(key.m_Prefix.m_Cid) = cid; + key.m_KeyInContract = Oracle2::Tags::s_StateFull; + + { + Env::VarReader r(key, key); + uint32_t nKey = 0, nVal = sizeof(g); + if (!r.MoveNext(nullptr, nKey, &g, nVal, 0)) + return; + nProvs = (nVal - sizeof(Oracle2::State0)) / sizeof(Oracle2::State0::Entry); + if (nProvs > g.s_ProvsMax) + return; + } + + { + Env::DocGroup gr1("Settings"); + WriteOracle2Settings(g.m_Settings); + } + + Height h = Env::get_Height(); + + { + Env::DocGroup gr1("Feeds"); + DocSetType("table"); + Env::DocArray gr2("value"); + { + Env::DocArray gr3(""); + DocAddTableHeader("Index"); + DocAddTableHeader("Key"); + DocAddTableHeader("Last Value"); + DocAddTableHeader("Last Height"); + DocAddTableHeader("Comment"); + } + + Height h1 = (h > g.m_Settings.m_hValidity) ? (h - g.m_Settings.m_hValidity) : 0; + + for (uint32_t i = 0; i < nProvs; i++) + { + const auto& x = g.m_pE[i]; + if (_POD_(x.m_Pk).IsZero()) + continue; + + Env::DocArray gr3(""); + Env::DocAddNum("", i); + DocAddPk("", x.m_Pk); + DocAddFloat("", x.m_Val); + DocAddHeight1("", x.m_hUpdated); + Env::DocAddText("", (x.m_hUpdated > h1) ? "" : "outdated"); + } + } + + { + key.m_KeyInContract = Oracle2::Tags::s_Median; + Oracle2::Median med; + if (Env::VarReader::Read_T(key, med)) + { + bool bValid = (med.m_hEnd >= h); + if (bValid) + DocAddFloat("Median", med.m_Res); + else + Env::DocAddText("Median", ""); + } + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, Oracle2::s_pSID, _countof(Oracle2::s_pSID)); +} +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID& cid, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(cid, iMethod, pArg, nArg); +} +BEAM_EXPORT void Method_1(const ShaderID&, const ContractID&) { Env::DocGroup gr(""); OnKind(); } +BEAM_EXPORT void Method_2(const ShaderID&, const ContractID& cid) +{ + Env::DocGroup gr(""); OnKind(); + { Env::DocGroup grSt("State"); OnState_Inner(cid); } +} diff --git a/bvm/Shaders/oracle2/parser.wasm b/bvm/Shaders/oracle2/parser.wasm new file mode 100755 index 0000000000..6a0fa08610 Binary files /dev/null and b/bvm/Shaders/oracle2/parser.wasm differ diff --git a/bvm/Shaders/pbft/parser.cpp b/bvm/Shaders/pbft/parser.cpp new file mode 100644 index 0000000000..266e64e6a2 --- /dev/null +++ b/bvm/Shaders/pbft/parser.cpp @@ -0,0 +1,390 @@ +// Parser module for PBFT_DPOS and PBFT_STAT. +#include "../common.h" +#include "../Sort.h" +#include "../Explorer/parser_module_abi.h" +#include "pbft_dpos.h" +#include "pbft_stat.h" + +static const ShaderID s_pSid[] = { PBFT_DPOS::s_SID, PBFT_STAT::s_SID }; + +static const char* KindFor(const ShaderID& sid) +{ + if (_POD_(sid) == PBFT_DPOS::s_SID) return "PBFT_DPOS"; + if (_POD_(sid) == PBFT_STAT::s_SID) return "PBFT_STAT"; + return "PBFT_?"; +} + +static void On_PBFT_Settings(const PBFT_DPOS::Settings& stg) +{ + DocAddAid("Stake-Aid", stg.m_aidStake); + Env::DocAddNum("Unbond lock", stg.m_hUnbondLock); + DocAddAmount("Min stake", stg.m_MinValidatorStake); +} + +static void On_PBFT_ValidatorAddr(const PBFT_DPOS::Address& addr) { DocAddMonoblob("Address", addr); } +static void On_PBFT_DelegatorAddr(const PubKey& addr) { DocAddMonoblob("Delegator", addr); } + +static void On_PBFT_Status(const char* szName, I_PBFT::State::Validator::Status status) +{ + const char* szStatus = nullptr; + switch (status) + { + case I_PBFT::State::Validator::Status::Active: szStatus = "Active"; break; + case I_PBFT::State::Validator::Status::Jailed: szStatus = "Jailed"; break; + case I_PBFT::State::Validator::Status::Suspended: szStatus = "Suspended"; break; + case I_PBFT::State::Validator::Status::Tombed: szStatus = "Tombed"; break; + case I_PBFT::State::Validator::Status::Slash: szStatus = "Slash"; break; + default: + Env::DocAddNum(szName, static_cast(status)); + return; + } + Env::DocAddText(szName, szStatus); +} + +static void On_PBFT_Commission(uint16_t commission_cpc, bool bIsTbl = false) +{ + DocAddFixedPoint(bIsTbl ? "" : "Commission", commission_cpc, 100, 2); +} + +// ---------- PBFT_DPOS ---------- + +static void OnMethod_DPOS(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case PBFT_DPOS::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(PBFT_DPOS::Method::Create)) + { + auto* p = (const PBFT_DPOS::Method::Create*) pArg; + Env::DocGroup gr("params"); + On_PBFT_Settings(p->m_Settings); + } + break; + case 1: Env::DocAddText("method", "Destroy"); break; + + case PBFT_DPOS::Method::ValidatorStatusUpdate::s_iMethod: + Env::DocAddText("method", "ValidatorStatusUpdate"); + if (nArg >= sizeof(PBFT_DPOS::Method::ValidatorStatusUpdate)) + { + auto* p = (const PBFT_DPOS::Method::ValidatorStatusUpdate*) pArg; + Env::DocGroup gr("params"); + On_PBFT_ValidatorAddr(p->m_Address); + On_PBFT_Status("Status", p->m_Status); + } + break; + + case PBFT_DPOS::Method::AddReward::s_iMethod: + Env::DocAddText("method", "AddReward"); + break; + + case PBFT_DPOS::Method::DelegatorUpdate::s_iMethod: + Env::DocAddText("method", "DelegatorUpdate"); + if (nArg >= sizeof(PBFT_DPOS::Method::DelegatorUpdate)) + { + auto* p = (const PBFT_DPOS::Method::DelegatorUpdate*) pArg; + Env::DocGroup gr("params"); + DocAddMonoblob("Delegator", p->m_Delegator); + if (p->m_RewardClaim || p->m_StakeBond) + { + DocAddMonoblob("Validator", p->m_Validator); + DocAddAmountSigned("Bond_change", p->m_StakeBond); + } + } + break; + + case PBFT_DPOS::Method::ValidatorRegister::s_iMethod: + Env::DocAddText("method", "ValidatorRegister"); + if (nArg >= sizeof(PBFT_DPOS::Method::ValidatorRegister)) + { + auto* p = (const PBFT_DPOS::Method::ValidatorRegister*) pArg; + Env::DocGroup gr("params"); + On_PBFT_ValidatorAddr(p->m_Validator); + On_PBFT_DelegatorAddr(p->m_Delegator); + DocAddAmountSigned("Stake", p->m_Stake, true); + On_PBFT_Commission(p->m_Commission_cpc); + } + break; + + case PBFT_DPOS::Method::ValidatorUpdate::s_iMethod: + Env::DocAddText("method", "ValidatorUpdate"); + if (nArg >= sizeof(PBFT_DPOS::Method::ValidatorUpdate)) + { + auto* p = (const PBFT_DPOS::Method::ValidatorUpdate*) pArg; + Env::DocGroup gr("params"); + On_PBFT_ValidatorAddr(p->m_Validator); + if (PBFT_DPOS::State::ValidatorPlus::s_CommissionTagTomb == p->m_Commission_cpc) + Env::DocAddText("Action", "Tomb"); + else + On_PBFT_Commission(p->m_Commission_cpc); + } + break; + } +} + +static void OnState_DPOS(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = PBFT_DPOS::State::Tag::s_Global; + + PBFT_DPOS::State::Global g; + if (!Env::VarReader::Read_T(k, g)) + return; + + g.FlushRewardPending(); + + const Amount nProbeOnePercent = 100000000; + + PBFT_DPOS::State::Global g2; + _POD_(g2) = g; + g2.m_RewardPending = nProbeOnePercent * 100; + g2.FlushRewardPending(); + + struct ValidatorPlus + { + PBFT_DPOS::State::ValidatorPlus m_Validador; + PBFT_DPOS::Address m_Address; + + bool HasVotingPower() const { + return m_Validador.m_Status < I_PBFT::State::Validator::Status::Suspended; + } + + void operator = (const ValidatorPlus& x) { _POD_(*this) = x; } + + bool operator < (const ValidatorPlus& x) const { + if (m_Validador.m_Weight > x.m_Validador.m_Weight) return true; + if (m_Validador.m_Weight < x.m_Validador.m_Weight) return false; + if (m_Validador.m_Status < x.m_Validador.m_Status) return true; + if (m_Validador.m_Status > x.m_Validador.m_Status) return false; + return _POD_(m_Address).Cmp(x.m_Address) < 0; + } + }; + + Utils::Vector vVals; + Amount totalStake = 0; + uint64_t totalPower = 0; + + { + Env::Key_T vk0, vk1; + _POD_(vk0.m_Prefix.m_Cid) = cid; + _POD_(vk1.m_Prefix.m_Cid) = cid; + _POD_(vk0.m_KeyInContract.m_Address).SetZero(); + _POD_(vk1.m_KeyInContract.m_Address).SetObject(0xff); + + for (Env::VarReader r(vk0, vk1); ; ) + { + auto& x = vVals.emplace_back(); + if (!r.MoveNext_T(vk0, x.m_Validador)) + { + vVals.m_Count--; + break; + } + _POD_(x.m_Address) = vk0.m_KeyInContract.m_Address; + totalStake += x.m_Validador.m_Weight; + if (x.HasVotingPower()) + totalPower += x.m_Validador.m_Weight; + } + } + + { + Env::DocGroup gr("Settings"); + On_PBFT_Settings(g.m_Settings); + } + + DocAddAmount("Total stake", totalStake); + + vVals.Prepare(vVals.m_Count * 2); + auto* pVals = MergeSort::Do(vVals.m_p, vVals.m_p + vVals.m_Count, vVals.m_Count); + + { + Env::DocGroup gr2("Validators/Delegators"); + + DocSetType("table"); + Env::DocArray gr3("value"); + + { + Env::DocArray gr4(""); + DocAddTableHeader("Validator"); + DocAddTableHeader("Delegator"); + DocAddTableHeader("Status"); + DocAddTableHeader("Commission"); + DocAddTableHeader("Voting Power %"); + DocAddTableHeader("Stake"); + DocAddTableHeader("Reward Pending"); + DocAddTableHeader("Reward %"); + } + + Env::Key_T dk0, dk1; + _POD_(dk0.m_Prefix.m_Cid) = cid; + _POD_(dk1.m_Prefix.m_Cid) = cid; + + for (uint32_t iV = 0; iV < vVals.m_Count; iV++) + { + auto& x = pVals[iV]; + auto& vp = x.m_Validador; + + PBFT_DPOS::State::ValidatorPlus vp2; + _POD_(vp2) = vp; + vp2.FlushRewardPending(g2); + vp.FlushRewardPending(g); + + _POD_(dk0.m_KeyInContract.m_Validator) = x.m_Address; + _POD_(dk0.m_KeyInContract.m_Delegator) = vp.m_Self.m_Delegator; + + auto weight = x.HasVotingPower() ? vp.m_Weight : 0; + + PBFT_DPOS::State::Delegator dp, dp2; + Amount dpStake = 0; + + bool bFoundSelf = Env::VarReader::Read_T(dk0, dp); + if (bFoundSelf) + { + _POD_(dp2) = dp; + dp2.Pop(vp2, g2); + dp2.m_RewardRemaining += vp2.m_Self.m_Commission; + + dpStake = dp.Pop(vp, g); + dp.m_RewardRemaining += vp.m_Self.m_Commission; + } + else + { + _POD_(dp).SetZero(); + _POD_(dp2).SetZero(); + } + + { + Env::DocArray gr4(""); + DocAddMonoblob("", x.m_Address); + DocAddMonoblob("", vp.m_Self.m_Delegator); + On_PBFT_Status("", vp.m_Status); + On_PBFT_Commission(vp.m_Commission_cpc, true); + DocAddFixedPoint("", weight * 100, totalPower, 4); + DocAddAmount("", dpStake); + DocAddAmount("", dp.m_RewardRemaining); + DocAddFixedPoint("", dp2.m_RewardRemaining - dp.m_RewardRemaining, nProbeOnePercent, 4); + } + + _POD_(dk1.m_KeyInContract.m_Validator) = x.m_Address; + _POD_(dk0.m_KeyInContract.m_Delegator).SetZero(); + _POD_(dk1.m_KeyInContract.m_Delegator).SetObject(0xff); + + for (Env::VarReader r2(dk0, dk1); ; ) + { + if (!r2.MoveNext_T(dk0, dp)) + break; + if (_POD_(vp.m_Self.m_Delegator) == dk0.m_KeyInContract.m_Delegator) + continue; + + _POD_(dp2) = dp; + dp2.Pop(vp2, g2); + dpStake = dp.Pop(vp, g); + + Env::DocArray gr4(""); + Env::DocAddText("", ""); + DocAddMonoblob("", dk0.m_KeyInContract.m_Delegator); + Env::DocAddText("", ""); + Env::DocAddText("", ""); + Env::DocAddText("", ""); + DocAddAmount("", dpStake); + DocAddAmount("", dp.m_RewardRemaining); + DocAddFixedPoint("", dp2.m_RewardRemaining - dp.m_RewardRemaining, nProbeOnePercent, 4); + } + } + } +} + +// ---------- PBFT_STAT ---------- + +static void OnMethod_STAT(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 0: Env::DocAddText("method", "Create"); break; + case 1: Env::DocAddText("method", "Destroy"); break; + + case I_PBFT::Method::ValidatorStatusUpdate::s_iMethod: + Env::DocAddText("method", "ValidatorStatusUpdate"); + if (nArg >= sizeof(I_PBFT::Method::ValidatorStatusUpdate)) + { + auto* p = (const I_PBFT::Method::ValidatorStatusUpdate*) pArg; + Env::DocGroup gr("params"); + On_PBFT_ValidatorAddr(p->m_Address); + On_PBFT_Status("Status", p->m_Status); + } + break; + + case PBFT_DPOS::Method::AddReward::s_iMethod: + Env::DocAddText("method", "AddReward"); + break; + } +} + +static void OnState_STAT(const ContractID& cid) +{ + Env::DocGroup gr2("Validators"); + + DocSetType("table"); + Env::DocArray gr3("value"); + + { + Env::DocArray gr4(""); + DocAddTableHeader("Validator"); + DocAddTableHeader("Status"); + DocAddTableHeader("Weight"); + } + + Env::Key_T vk0, vk1; + _POD_(vk0.m_Prefix.m_Cid) = cid; + _POD_(vk1.m_Prefix.m_Cid) = cid; + _POD_(vk0.m_KeyInContract.m_Address).SetZero(); + _POD_(vk1.m_KeyInContract.m_Address).SetObject(0xff); + + for (Env::VarReader r(vk0, vk1); ; ) + { + I_PBFT::State::Validator vp; + if (!r.MoveNext_T(vk0, vp)) + break; + + Env::DocArray gr4(""); + DocAddMonoblob("", vk0.m_KeyInContract.m_Address); + On_PBFT_Status("", vp.m_Status); + DocAddAmount("", vp.m_Weight); + } +} + +// ---------- ABI ---------- + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + return ParserModule_FillSids(out_buf, out_cap, s_pSid, _countof(s_pSid)); +} + +BEAM_EXPORT void Method_0(const ShaderID& sid, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); + Env::DocAddText("kind", KindFor(sid)); + if (_POD_(sid) == PBFT_DPOS::s_SID) + OnMethod_DPOS(iMethod, pArg, nArg); + else + OnMethod_STAT(iMethod, pArg, nArg); +} + +BEAM_EXPORT void Method_1(const ShaderID& sid, const ContractID&) +{ + Env::DocGroup gr(""); + Env::DocAddText("kind", KindFor(sid)); +} + +BEAM_EXPORT void Method_2(const ShaderID& sid, const ContractID& cid) +{ + Env::DocGroup gr(""); + Env::DocAddText("kind", KindFor(sid)); + { + Env::DocGroup grSt("State"); + if (_POD_(sid) == PBFT_DPOS::s_SID) + OnState_DPOS(cid); + else + OnState_STAT(cid); + } +} diff --git a/bvm/Shaders/pbft/parser.wasm b/bvm/Shaders/pbft/parser.wasm new file mode 100755 index 0000000000..e4a7929d16 Binary files /dev/null and b/bvm/Shaders/pbft/parser.wasm differ diff --git a/bvm/Shaders/perpetual/app.wasm b/bvm/Shaders/perpetual/app.wasm old mode 100644 new mode 100755 index fdf2d41b9b..d00debace7 Binary files a/bvm/Shaders/perpetual/app.wasm and b/bvm/Shaders/perpetual/app.wasm differ diff --git a/bvm/Shaders/perpetual/contract.wasm b/bvm/Shaders/perpetual/contract.wasm old mode 100644 new mode 100755 index 315c439852..1a76d6b6c7 Binary files a/bvm/Shaders/perpetual/contract.wasm and b/bvm/Shaders/perpetual/contract.wasm differ diff --git a/bvm/Shaders/pipe/contract.wasm b/bvm/Shaders/pipe/contract.wasm old mode 100644 new mode 100755 index 45d5440f94..21dbe22e7c Binary files a/bvm/Shaders/pipe/contract.wasm and b/bvm/Shaders/pipe/contract.wasm differ diff --git a/bvm/Shaders/playground/app.wasm b/bvm/Shaders/playground/app.wasm old mode 100644 new mode 100755 index c74fffa2cb..568400ce75 Binary files a/bvm/Shaders/playground/app.wasm and b/bvm/Shaders/playground/app.wasm differ diff --git a/bvm/Shaders/playground/contract.wasm b/bvm/Shaders/playground/contract.wasm old mode 100644 new mode 100755 index 1d68333f71..af2b2dc602 Binary files a/bvm/Shaders/playground/contract.wasm and b/bvm/Shaders/playground/contract.wasm differ diff --git a/bvm/Shaders/profit_pool/app.wasm b/bvm/Shaders/profit_pool/app.wasm old mode 100644 new mode 100755 index d4d44e7763..954442fb58 Binary files a/bvm/Shaders/profit_pool/app.wasm and b/bvm/Shaders/profit_pool/app.wasm differ diff --git a/bvm/Shaders/profit_pool/contract.wasm b/bvm/Shaders/profit_pool/contract.wasm old mode 100644 new mode 100755 index 06c1d9994b..e33b770bcc Binary files a/bvm/Shaders/profit_pool/contract.wasm and b/bvm/Shaders/profit_pool/contract.wasm differ diff --git a/bvm/Shaders/roulette/app.wasm b/bvm/Shaders/roulette/app.wasm old mode 100644 new mode 100755 index 57b4da1a98..e904b4d67c Binary files a/bvm/Shaders/roulette/app.wasm and b/bvm/Shaders/roulette/app.wasm differ diff --git a/bvm/Shaders/roulette/contract.wasm b/bvm/Shaders/roulette/contract.wasm old mode 100644 new mode 100755 index 3c18eeaa89..673ca4e6f9 Binary files a/bvm/Shaders/roulette/contract.wasm and b/bvm/Shaders/roulette/contract.wasm differ diff --git a/bvm/Shaders/sidechain/contract.wasm b/bvm/Shaders/sidechain/contract.wasm old mode 100644 new mode 100755 index 406d0da6f3..f454066020 Binary files a/bvm/Shaders/sidechain/contract.wasm and b/bvm/Shaders/sidechain/contract.wasm differ diff --git a/bvm/Shaders/sidechain_pos/parser.cpp b/bvm/Shaders/sidechain_pos/parser.cpp new file mode 100644 index 0000000000..417d1f0ceb --- /dev/null +++ b/bvm/Shaders/sidechain_pos/parser.cpp @@ -0,0 +1,205 @@ +// Parser module for SidechainPos L1 and L2 bridges. +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract_l1.h" +#include "contract_l2.h" + +static ShaderID g_Sids[1 + _countof(SidechainPos::L1::s_pSID)]; + +static uint32_t init_sids() +{ + uint32_t n = 0; + _POD_(g_Sids[n++]) = SidechainPos::L2::s_SID; + for (uint32_t i = 0; i < _countof(SidechainPos::L1::s_pSID); i++) + _POD_(g_Sids[n++]) = SidechainPos::L1::s_pSID[i]; + return n; +} + +static const char* KindFor(const ShaderID& sid) +{ + if (_POD_(sid) == SidechainPos::L2::s_SID) return "Bridge_L2"; + for (uint32_t i = 0; i < _countof(SidechainPos::L1::s_pSID); i++) + if (_POD_(sid) == SidechainPos::L1::s_pSID[i]) + return "Bridge_L1"; + return "Bridge_?"; +} + +static void WriteSposSettings(const SidechainPos::L1::Settings& stg) +{ + DocAddAid("Staking Token", stg.m_aidStaking); + DocAddAid("Liquidity Token", stg.m_aidLiquidity); + DocAddHeight("Per-phase End", stg.m_hPreEnd); +} + +static void WriteSposValidators(const SidechainPos::L1::Validator* pV, uint32_t nV) +{ + Env::DocGroup gr1("Validators"); + DocSetType("table"); + Env::DocArray gr2("value"); + + { + Env::DocArray gr3(""); + DocAddTableHeader("Index"); + DocAddTableHeader("Key"); + } + + for (uint32_t i = 0; i < nV; i++) + { + Env::DocArray gr3(""); + Env::DocAddNum("", i); + DocAddPk("", pV[i].m_pk); + } +} + +static void OnSposBridgeOp(const SidechainPos::L1::Method::BridgeOp& op) +{ + DocAddAidAmount("Value", op.m_Aid, op.m_Amount); + DocAddMonoblob("cookie", op.m_Cookie); + DocAddPk("pk", op.m_pk); +} + +static void OnMethod_L1(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 1: Env::DocAddText("method", "Destroy"); break; + + case SidechainPos::L1::Method::Create::s_iMethod: + Env::DocAddText("method", "Create"); + if (nArg >= sizeof(SidechainPos::L1::Method::Create)) + { + auto* p = (const SidechainPos::L1::Method::Create*) pArg; + Env::DocGroup gr("params"); + WriteSposSettings(p->m_Settings); + WriteUpgradeSettings(p->m_Upgradable); + if (nArg >= sizeof(*p) + sizeof(SidechainPos::L1::Validator) * p->m_Validators) + WriteSposValidators((const SidechainPos::L1::Validator*) (p + 1), p->m_Validators); + } + break; + + case Upgradable3::Method::Control::s_iMethod: + // Control method handling intentionally minimal — host emits wrapper info. + Env::DocAddText("method", "Upgradable3 Control"); + break; + + case SidechainPos::L1::Method::UserStake::s_iMethod: + if (nArg >= sizeof(SidechainPos::L1::Method::UserStake)) + { + auto* p = (const SidechainPos::L1::Method::UserStake*) pArg; + Env::DocAddText("method", "User stake"); + Env::DocGroup gr("params"); + DocAddAmount("Amount", p->m_Amount); + DocAddPk("Pk", p->m_pkUser); + } + break; + + case SidechainPos::L1::Method::BridgeExport::s_iMethod: + if (nArg >= sizeof(SidechainPos::L1::Method::BridgeExport)) + { + auto* p = (const SidechainPos::L1::Method::BridgeExport*) pArg; + Env::DocAddText("method", "Bridge Export"); + Env::DocGroup gr("params"); + OnSposBridgeOp(*p); + } + break; + + case SidechainPos::L1::Method::BridgeImport::s_iMethod: + if (nArg >= sizeof(SidechainPos::L1::Method::BridgeImport)) + { + auto* p = (const SidechainPos::L1::Method::BridgeImport*) pArg; + Env::DocAddText("method", "Bridge Import"); + Env::DocGroup gr("params"); + OnSposBridgeOp(*p); + WriteUpgradeAdminsMask(p->m_ApproveMask); + } + break; + } +} + +static void OnState_L1(const ContractID& cid) +{ + Env::Key_T k; + _POD_(k.m_Prefix.m_Cid) = cid; + k.m_KeyInContract = SidechainPos::L1::Tags::s_State; + + SidechainPos::L1::State s; + if (!Env::VarReader::Read_T(k, s)) + return; + + { + Env::DocGroup gr2("Settings"); + WriteSposSettings(s.m_Settings); + } + + { + k.m_KeyInContract = SidechainPos::L1::Tags::s_Validators; + Env::VarReader r(k, k); + + SidechainPos::L1::Validator pV[SidechainPos::L1::Validator::s_Max]; + uint32_t nKey = 0, nVal = sizeof(pV); + + if (r.MoveNext(nullptr, nKey, pV, nVal, 0) && (nVal >= sizeof(SidechainPos::L1::Validator)) && (nVal <= sizeof(pV))) + WriteSposValidators(pV, nVal / sizeof(SidechainPos::L1::Validator)); + } +} + +static void OnMethod_L2(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 0: Env::DocAddText("method", "Create"); break; + case 1: Env::DocAddText("method", "Destroy"); break; + + case SidechainPos::L2::Method::BridgeEmit::s_iMethod: + if (nArg >= sizeof(SidechainPos::L2::Method::BridgeEmit)) + { + auto* p = (const SidechainPos::L2::Method::BridgeEmit*) pArg; + Env::DocAddText("method", "Mint"); + Env::DocGroup gr("params"); + OnSposBridgeOp(*p); + } + break; + + case SidechainPos::L2::Method::BridgeBurn::s_iMethod: + if (nArg >= sizeof(SidechainPos::L2::Method::BridgeBurn)) + { + auto* p = (const SidechainPos::L2::Method::BridgeBurn*) pArg; + Env::DocAddText("method", "Burn"); + Env::DocGroup gr("params"); + OnSposBridgeOp(*p); + } + break; + } +} + +BEAM_EXPORT uint32_t Method_3(ShaderID* out_buf, uint32_t out_cap) +{ + uint32_t n = init_sids(); + return ParserModule_FillSids(out_buf, out_cap, g_Sids, n); +} + +BEAM_EXPORT void Method_0(const ShaderID& sid, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); + Env::DocAddText("kind", KindFor(sid)); + if (_POD_(sid) == SidechainPos::L2::s_SID) + OnMethod_L2(iMethod, pArg, nArg); + else + OnMethod_L1(iMethod, pArg, nArg); +} + +BEAM_EXPORT void Method_1(const ShaderID& sid, const ContractID&) +{ + Env::DocGroup gr(""); + Env::DocAddText("kind", KindFor(sid)); +} + +BEAM_EXPORT void Method_2(const ShaderID& sid, const ContractID& cid) +{ + Env::DocGroup gr(""); + Env::DocAddText("kind", KindFor(sid)); + if (_POD_(sid) == SidechainPos::L2::s_SID) + return; // L2 has no state + Env::DocGroup grSt("State"); + OnState_L1(cid); +} diff --git a/bvm/Shaders/sidechain_pos/parser.wasm b/bvm/Shaders/sidechain_pos/parser.wasm new file mode 100755 index 0000000000..a05ba4173d Binary files /dev/null and b/bvm/Shaders/sidechain_pos/parser.wasm differ diff --git a/bvm/Shaders/upgradable/contract.wasm b/bvm/Shaders/upgradable/contract.wasm old mode 100644 new mode 100755 index 2de673e67c..0dcd29bd75 Binary files a/bvm/Shaders/upgradable/contract.wasm and b/bvm/Shaders/upgradable/contract.wasm differ diff --git a/bvm/Shaders/upgradable2/Test/test_app.wasm b/bvm/Shaders/upgradable2/Test/test_app.wasm old mode 100644 new mode 100755 index 674f868ad1..148a8cc4c4 Binary files a/bvm/Shaders/upgradable2/Test/test_app.wasm and b/bvm/Shaders/upgradable2/Test/test_app.wasm differ diff --git a/bvm/Shaders/upgradable2/Test/test_v0.wasm b/bvm/Shaders/upgradable2/Test/test_v0.wasm old mode 100644 new mode 100755 index 70e3d417e7..6e35aa60cb Binary files a/bvm/Shaders/upgradable2/Test/test_v0.wasm and b/bvm/Shaders/upgradable2/Test/test_v0.wasm differ diff --git a/bvm/Shaders/upgradable2/Test/test_v1.wasm b/bvm/Shaders/upgradable2/Test/test_v1.wasm old mode 100644 new mode 100755 index eca53adf4b..ed928e96b3 Binary files a/bvm/Shaders/upgradable2/Test/test_v1.wasm and b/bvm/Shaders/upgradable2/Test/test_v1.wasm differ diff --git a/bvm/Shaders/upgradable2/contract.wasm b/bvm/Shaders/upgradable2/contract.wasm old mode 100644 new mode 100755 index aecf786413..259de3246f Binary files a/bvm/Shaders/upgradable2/contract.wasm and b/bvm/Shaders/upgradable2/contract.wasm differ diff --git a/bvm/Shaders/upgradable3/Test/test_app.wasm b/bvm/Shaders/upgradable3/Test/test_app.wasm old mode 100644 new mode 100755 index ccc772cb4c..87e1f4c7ac Binary files a/bvm/Shaders/upgradable3/Test/test_app.wasm and b/bvm/Shaders/upgradable3/Test/test_app.wasm differ diff --git a/bvm/Shaders/upgradable3/Test/test_v0.wasm b/bvm/Shaders/upgradable3/Test/test_v0.wasm old mode 100644 new mode 100755 index 958ebdd314..fd3be2f7b7 Binary files a/bvm/Shaders/upgradable3/Test/test_v0.wasm and b/bvm/Shaders/upgradable3/Test/test_v0.wasm differ diff --git a/bvm/Shaders/upgradable3/Test/test_v0_migrate.wasm b/bvm/Shaders/upgradable3/Test/test_v0_migrate.wasm old mode 100644 new mode 100755 index 04e0b95927..64346bc5dd Binary files a/bvm/Shaders/upgradable3/Test/test_v0_migrate.wasm and b/bvm/Shaders/upgradable3/Test/test_v0_migrate.wasm differ diff --git a/bvm/Shaders/upgradable3/Test/test_v1.wasm b/bvm/Shaders/upgradable3/Test/test_v1.wasm old mode 100644 new mode 100755 index a490799a28..440f1d5792 Binary files a/bvm/Shaders/upgradable3/Test/test_v1.wasm and b/bvm/Shaders/upgradable3/Test/test_v1.wasm differ diff --git a/bvm/Shaders/vault/app.wasm b/bvm/Shaders/vault/app.wasm old mode 100644 new mode 100755 index 6ef54c4227..c7e24e950f Binary files a/bvm/Shaders/vault/app.wasm and b/bvm/Shaders/vault/app.wasm differ diff --git a/bvm/Shaders/vault/contract.wasm b/bvm/Shaders/vault/contract.wasm old mode 100644 new mode 100755 index 93083e9a2a..50ce461d17 Binary files a/bvm/Shaders/vault/contract.wasm and b/bvm/Shaders/vault/contract.wasm differ diff --git a/bvm/Shaders/vault/parser.cpp b/bvm/Shaders/vault/parser.cpp new file mode 100644 index 0000000000..ff6a7cb601 --- /dev/null +++ b/bvm/Shaders/vault/parser.cpp @@ -0,0 +1,39 @@ +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static const ShaderID s_pSid[] = { Vault::s_SID }; + +static void OnKind() { Env::DocAddText("kind", "Vault"); } + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 0: Env::DocAddText("method", "Create"); break; + case 1: Env::DocAddText("method", "Destroy"); break; + + case Vault::Deposit::s_iMethod: + if (nArg >= sizeof(Vault::Deposit)) + { + auto* p = (const Vault::Deposit*) pArg; + Env::DocAddText("method", "Deposit"); + Env::DocGroup gr("params"); + DocAddPk("User", p->m_Account); + } + break; + + case Vault::Withdraw::s_iMethod: + Env::DocAddText("method", "Withdraw"); + break; + } +} + +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} + +PARSER_MODULE_EXPORT_SIDS(s_pSid) +PARSER_MODULE_EXPORT_KIND_ONLY(OnKind) diff --git a/bvm/Shaders/vault/parser.wasm b/bvm/Shaders/vault/parser.wasm new file mode 100755 index 0000000000..0fd20d83b5 Binary files /dev/null and b/bvm/Shaders/vault/parser.wasm differ diff --git a/bvm/Shaders/vault_anon/app.wasm b/bvm/Shaders/vault_anon/app.wasm old mode 100644 new mode 100755 index 3befada96f..72e51eba8d Binary files a/bvm/Shaders/vault_anon/app.wasm and b/bvm/Shaders/vault_anon/app.wasm differ diff --git a/bvm/Shaders/vault_anon/contract.wasm b/bvm/Shaders/vault_anon/contract.wasm old mode 100644 new mode 100755 index 9a4ae79f9c..43287e5f77 Binary files a/bvm/Shaders/vault_anon/contract.wasm and b/bvm/Shaders/vault_anon/contract.wasm differ diff --git a/bvm/Shaders/vault_anon/parser.cpp b/bvm/Shaders/vault_anon/parser.cpp new file mode 100644 index 0000000000..dd880b44bc --- /dev/null +++ b/bvm/Shaders/vault_anon/parser.cpp @@ -0,0 +1,39 @@ +#include "../common.h" +#include "../Explorer/parser_module_abi.h" +#include "contract.h" + +static const ShaderID s_pSid[] = { VaultAnon::s_SID }; + +static void OnKind() { Env::DocAddText("kind", "VaultAnon"); } + +static void OnMethod_Inner(uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + switch (iMethod) + { + case 0: Env::DocAddText("method", "Create"); break; + case 1: Env::DocAddText("method", "Destroy"); break; + + case VaultAnon::Method::Deposit::s_iMethod: + if (nArg >= sizeof(VaultAnon::Method::Deposit)) + { + auto* p = (const VaultAnon::Method::Deposit*) pArg; + Env::DocAddText("method", "Deposit"); + Env::DocGroup gr("params"); + DocAddPk("User", p->m_Key.m_pkOwner); + } + break; + + case VaultAnon::Method::Withdraw::s_iMethod: + Env::DocAddText("method", "Withdraw"); + break; + } +} + +BEAM_EXPORT void Method_0(const ShaderID&, const ContractID&, uint32_t iMethod, const void* pArg, uint32_t nArg) +{ + Env::DocGroup gr(""); OnKind(); + OnMethod_Inner(iMethod, pArg, nArg); +} + +PARSER_MODULE_EXPORT_SIDS(s_pSid) +PARSER_MODULE_EXPORT_KIND_ONLY(OnKind) diff --git a/bvm/Shaders/vault_anon/parser.wasm b/bvm/Shaders/vault_anon/parser.wasm new file mode 100755 index 0000000000..57e41f7818 Binary files /dev/null and b/bvm/Shaders/vault_anon/parser.wasm differ diff --git a/bvm/Shaders/voting/app.wasm b/bvm/Shaders/voting/app.wasm old mode 100644 new mode 100755 index edb90b1a10..7ee7bd373c Binary files a/bvm/Shaders/voting/app.wasm and b/bvm/Shaders/voting/app.wasm differ diff --git a/bvm/Shaders/voting/contract.wasm b/bvm/Shaders/voting/contract.wasm old mode 100644 new mode 100755 index 487ce60e2a..24ec9bfae8 Binary files a/bvm/Shaders/voting/contract.wasm and b/bvm/Shaders/voting/contract.wasm differ diff --git a/explorer/explorer_node.cpp b/explorer/explorer_node.cpp index 877f0947c4..b25d70ea6a 100644 --- a/explorer/explorer_node.cpp +++ b/explorer/explorer_node.cpp @@ -35,14 +35,18 @@ struct Options { static const unsigned logRotationPeriod = 3*60*60*1000; // 3 hours std::vector whitelist; uint32_t logCleanupPeriod; - ByteBuffer m_RichParser; - bool m_RichParserChanged = false; + std::string m_RichParserFolder; + bool m_RichParserFolderDryRun = false; bool m_LogTrafic = false; bool m_PeersPersistent; }; +using StagedParserModules = std::vector>; + static bool parse_cmdline(int argc, char* argv[], Options& o, Rules&); static void setup_node(Node& node, const Options& o); +static bool load_parser_modules(const Options& o, StagedParserModules& staged); +static bool apply_parser_modules(Node& node, const StagedParserModules& staged, bool dryRun); thread_local const beam::Rules* beam::Rules::s_pInstance = nullptr; @@ -56,6 +60,10 @@ int main(int argc, char* argv[]) { return 1; } + StagedParserModules stagedModules; + if (!load_parser_modules(options, stagedModules)) + return 1; + r.UpdateChecksum(); const auto path = boost::filesystem::system_complete(LOG_FILES_DIR); @@ -76,6 +84,8 @@ int main(int argc, char* argv[]) { setup_node(node, options); explorer::IAdapter::Ptr adapter = explorer::create_adapter(node); node.Initialize(); + if (!apply_parser_modules(node, stagedModules, options.m_RichParserFolderDryRun)) + return 1; adapter->Initialize(); explorer::Server server(*adapter, *reactor, options.explorerListenTo, options.accessControlFile, options.whitelist); BEAM_LOG_INFO() << "Node listens to " << options.nodeListenTo << ", explorer listens to " << options.explorerListenTo; @@ -110,7 +120,8 @@ bool parse_cmdline(int argc, char* argv[], Options& o, Rules& r) { (cli::IP_WHITELIST, po::value()->default_value(""), "IP whitelist") (cli::LOG_CLEANUP_DAYS, po::value()->default_value(5), "old logfiles cleanup period(days)") (cli::CONFIG_FILE_PATH, po::value()->default_value("explorer-node.cfg"), "path to the config file") - (cli::CONTRACT_RICH_PARSER, po::value(), "Optional shader to parse contract invocation info") + (cli::CONTRACT_RICH_PARSER_FOLDER, po::value(), "Optional folder of per-contract parser modules (*.wasm)") + (cli::CONTRACT_RICH_PARSER_FOLDER_DRYRUN, po::bool_switch(&o.m_RichParserFolderDryRun)->default_value(false), "Scan parser folder, print SID->module map and exit") (cli::LOG_LEVEL, po::value(), "set log level [error|warning|info(default)|debug|verbose]") (cli::NODE_PEERS_PERSISTENT, po::value()->default_value(false), "Keep persistent connection to the specified peers, regardless to ratings") (g_szTraficLog, po::value()->default_value(false), "Log trafic") @@ -177,25 +188,9 @@ bool parse_cmdline(int argc, char* argv[], Options& o, Rules& r) { } } - auto& vArg = vm[cli::CONTRACT_RICH_PARSER]; - if (!vArg.empty()) - { - o.m_RichParserChanged = true; - - auto sPath = vArg.as(); - if (!sPath.empty()) - { - std::FStream fs; - fs.Open(sPath.c_str(), true, true); - - o.m_RichParser.resize(static_cast(fs.get_Remaining())); - if (!o.m_RichParser.empty()) - fs.read(&o.m_RichParser.front(), o.m_RichParser.size()); - - bvm2::Processor::Compile(o.m_RichParser, o.m_RichParser, bvm2::Processor::Kind::Manager); - } - - } + auto& vFolder = vm[cli::CONTRACT_RICH_PARSER_FOLDER]; + if (!vFolder.empty()) + o.m_RichParserFolder = vFolder.as(); o.m_LogTrafic = vm[g_szTraficLog].as(); @@ -238,6 +233,116 @@ bool parse_cmdline(int argc, char* argv[], Options& o, Rules& r) { return false; } +// Step 1 of folder load (runs at CLI-parse time): read+compile every *.wasm +// in the folder. SID discovery is deferred to apply_parser_modules() because +// querying Method_3 needs a NodeProcessor instance. +bool load_parser_modules(const Options& o, StagedParserModules& staged) +{ + if (o.m_RichParserFolder.empty()) + return true; + + namespace fs = boost::filesystem; + fs::path dir(o.m_RichParserFolder); + if (!fs::is_directory(dir)) + { + BEAM_LOG_ERROR() << "Parser folder not a directory: " << o.m_RichParserFolder; + return false; + } + + std::vector wasms; + for (const auto& entry : fs::directory_iterator(dir)) + { + if (!fs::is_regular_file(entry.status())) + continue; + if (entry.path().extension() != ".wasm") + continue; + wasms.push_back(entry.path()); + } + std::sort(wasms.begin(), wasms.end()); // deterministic for stable error output + + for (const auto& p : wasms) + { + std::FStream fs1; + fs1.Open(p.string().c_str(), true, true); + + ByteBuffer raw; + raw.resize(static_cast(fs1.get_Remaining())); + if (!raw.empty()) + fs1.read(&raw.front(), raw.size()); + + ByteBuffer compiled; + try + { + bvm2::Processor::Compile(compiled, raw, bvm2::Processor::Kind::Manager); + } + catch (const std::exception& e) + { + BEAM_LOG_ERROR() << "Failed to compile parser module " << p.filename().string() << ": " << e.what(); + return false; + } + staged.emplace_back(p.filename().string(), std::move(compiled)); + } + return true; +} + +// Step 2 of folder load (runs after node.Initialize()): for each staged +// module, ask it for its supported SIDs via Method_3, populate +// node.get_Processor().m_RichParserModules keyed by SID, and refuse to start +// if two modules claim the same SID. Returns false on conflict. +bool apply_parser_modules(Node& node, const StagedParserModules& staged, bool dryRun) +{ + if (staged.empty() && !dryRun) + return true; + + auto& proc = node.get_Processor(); + std::map sidToName; // for conflict reporting + + bool conflict = false; + for (const auto& m : staged) + { + const std::string& name = m.first; + const ByteBuffer& compiled = m.second; + Blob bb(compiled.data(), static_cast(compiled.size())); + + std::vector sids; + if (!proc.ParserModule_GetSupportedSids(bb, sids) || sids.empty()) + { + BEAM_LOG_WARNING() << "Parser module " << name << " reported no SIDs; skipping"; + continue; + } + + for (const auto& sid : sids) + { + auto it = sidToName.find(sid); + if (it != sidToName.end()) + { + BEAM_LOG_ERROR() << "SID " << sid << " claimed by multiple parser modules: " << it->second << " and " << name; + conflict = true; + } + else + { + sidToName[sid] = name; + proc.m_RichParserModules[sid] = compiled; + } + } + } + + if (conflict) + { + BEAM_LOG_ERROR() << "Refusing to start: duplicate parser module SIDs."; + return false; + } + + if (dryRun) + { + std::cout << "Parser module SID -> module map:\n"; + for (const auto& kv : sidToName) + std::cout << " " << kv.first << " " << kv.second << "\n"; + std::exit(0); + } + return true; +} + void setup_node(Node& node, const Options& o) { BEAM_LOG_INFO() << "Beam Node Explorer " << PROJECT_VERSION << " (" << BRANCH_NAME << ")"; BEAM_LOG_INFO() << "Rules signature: " << Rules::get().get_SignatureStr(); @@ -256,9 +361,4 @@ void setup_node(Node& node, const Options& o) { address.resolve(o.nodeConnectTo.c_str()); node.m_Cfg.m_ProcessorParams.m_RichInfoFlags = NodeProcessor::StartParams::RichInfo::On; - if (o.m_RichParserChanged) - { - node.m_Cfg.m_ProcessorParams.m_RichInfoFlags |= NodeProcessor::StartParams::RichInfo::UpdShader; - node.m_Cfg.m_ProcessorParams.m_RichParser = o.m_RichParser; - } } diff --git a/node/processor.cpp b/node/processor.cpp index 538f5a40c3..2e5dc7a6a4 100644 --- a/node/processor.cpp +++ b/node/processor.cpp @@ -185,14 +185,6 @@ void NodeProcessor::Initialize(const char* szPath, const StartParams& sp, ILongA } } - if (StartParams::RichInfo::UpdShader & sp.m_RichInfoFlags) - { - m_DB.ParamSet(NodeDB::ParamID::RichContractParser, nullptr, &sp.m_RichParser); - - if (!bRebuildNonStd && m_DB.ParamIntGetDef(NodeDB::ParamID::RichContractInfo)) - bRebuildNonStd = true; - } - uint64_t nFlags1 = m_DB.ParamIntGetDef(NodeDB::ParamID::Flags1); if (bRebuildNonStd || (NodeDB::Flags1::PendingRebuildNonStd & nFlags1)) { @@ -5733,7 +5725,6 @@ struct NodeProcessor::ProcessorInfoParser NodeProcessor& m_Proc; Height m_Height; - ByteBuffer m_bufParser; std::ostringstream m_os; void SelectContext(bool /* bDependent */, uint32_t /* nChargeNeeded */) override { @@ -5844,15 +5835,18 @@ struct NodeProcessor::ProcessorInfoParser m_Height = p.m_Cursor.m_hh.m_Height; } - bool Init(uint32_t nStackBytesExtra) + bool Init(uint32_t nStackBytesExtra, const ECC::uintBig* pSid) { - m_Proc.m_DB.ParamGet(NodeDB::ParamID::RichContractParser, nullptr, nullptr, &m_bufParser); - if (m_bufParser.empty()) + if (!pSid) return false; - InitMem(nStackBytesExtra); - m_Code = m_bufParser; + auto it = m_Proc.m_RichParserModules.find(*pSid); + if (it == m_Proc.m_RichParserModules.end()) + return false; + const ByteBuffer& module = it->second; + InitMem(nStackBytesExtra); + m_Code = Blob(module.data(), static_cast(module.size())); m_pOut = &m_os; return true; } @@ -5892,7 +5886,7 @@ void NodeProcessor::BlockInterpretCtx::BvmProcessor::ParseExtraInfo(ContractInvo ProcessorInfoParser proc(m_Bic.m_Proc); proc.m_Height = m_Bic.m_Height - 1; - if (!proc.Init(m_Stack.AlignUp(args.n))) + if (!proc.Init(m_Stack.AlignUp(args.n), &sid)) return; proc.m_Stack.PushAlias(args); @@ -5919,7 +5913,7 @@ void NodeProcessor::get_ContractDescr(const ECC::uintBig& sid, const ECC::uintBi try { ProcessorInfoParser proc(*this); - if (!proc.Init(0)) + if (!proc.Init(0, &sid)) return; proc.PushArgBoth(sid); @@ -5935,6 +5929,56 @@ void NodeProcessor::get_ContractDescr(const ECC::uintBig& sid, const ECC::uintBi } } +bool NodeProcessor::ParserModule_GetSupportedSids(const Blob& moduleBytes, std::vector& outSids) +{ + try + { + ProcessorInfoParser proc(*this); + proc.InitMem(0); + + // moduleBytes is already-compiled BVM bytecode (compiled by stage_parser_modules). + proc.m_Code = moduleBytes; + proc.m_pOut = &proc.m_os; + + // First call: get count. + proc.m_Stack.Push((Wasm::Word) 0); // out_buf = nullptr + proc.m_Stack.Push((Wasm::Word) 0); // out_cap = 0 + proc.CallMethod(3); + while (!proc.IsDone()) + proc.RunOnce(); + + uint32_t nCount = proc.m_Stack.Pop(); + if (!nCount) + return true; + + // Second call: allocate aux buffer, write SIDs there, copy out. + const uint32_t nBytes = nCount * (uint32_t) sizeof(ECC::uintBig); + proc.m_Stack.AliasAlloc(nBytes); + Wasm::Word pBuf = proc.m_Stack.get_AlasSp(); + + proc.m_Stack.Push(pBuf); + proc.m_Stack.Push((Wasm::Word) nCount); + proc.CallMethod(3); + while (!proc.IsDone()) + proc.RunOnce(); + + uint32_t nWritten = proc.m_Stack.Pop(); + if (nWritten > nCount) + nWritten = nCount; + + const auto* pSids = (const ECC::uintBig*) proc.m_Stack.get_AliasPtr(); + for (uint32_t i = 0; i < nWritten; i++) + outSids.push_back(pSids[i]); + + return true; + } + catch (const std::exception& e) + { + BEAM_LOG_WARNING() << "parser module Method_3 error: " << e.what(); + return false; + } +} + BlobMap::Entry& NodeProcessor::BlockInterpretCtx::Storage::get_Var(const Blob& key) { auto* pE = m_Vars.Find(key); diff --git a/node/processor.h b/node/processor.h index 22ef8d255a..d210f718b2 100644 --- a/node/processor.h +++ b/node/processor.h @@ -267,10 +267,8 @@ class NodeProcessor struct RichInfo { static const uint8_t Off = 1; static const uint8_t On = 2; - static const uint8_t UpdShader = 4; }; uint8_t m_RichInfoFlags = 0; - Blob m_RichParser = Blob(nullptr, 0); }; void Initialize(const char* szPath); @@ -455,6 +453,17 @@ class NodeProcessor void ExtractTreasurykWithExtra(std::vector& vOuts); void get_ContractDescr(const ECC::uintBig& sid, const ECC::uintBig& cid, std::string&, bool bFullState); + // Per-SID parser modules. Loaded from --contract_rich_parser_folder before + // Initialize() is called. When a SID is not in this map, parsing is skipped. + std::map m_RichParserModules; + + // Ask a parser module for the list of SIDs it handles via Method_3 + // (two-call protocol). moduleBytes MUST be already-compiled BVM bytecode + // (the form produced by bvm2::Processor::Compile), not raw wasm. On success + // appends every reported SID to outSids and returns true. On any wasm error + // returns false. + bool ParserModule_GetSupportedSids(const Blob& moduleBytes, std::vector& outSids); + int get_AssetAt(Asset::Full&, Height, bool bFindAid); // Must set ID. Returns -1 if asset is destroyed, 0 if never existed. // if never existed and bFindAid - try to find next that ever existed diff --git a/node/unittests/CMakeLists.txt b/node/unittests/CMakeLists.txt index ffda386e8b..27bc1ce4dc 100644 --- a/node/unittests/CMakeLists.txt +++ b/node/unittests/CMakeLists.txt @@ -5,4 +5,3 @@ configure_file("../../bvm/Shaders/vault/app.wasm" "${CMAKE_CURRENT_BINARY_DIR}/v configure_file("../../bvm/Shaders/sidechain_pos/contract_l2.wasm" "${CMAKE_CURRENT_BINARY_DIR}/sidechain_pos/contract_l2.wasm" COPYONLY) configure_file("../../bvm/Shaders/pbft/pbft_dpos.wasm" "${CMAKE_CURRENT_BINARY_DIR}/pbft/pbft_dpos.wasm" COPYONLY) configure_file("../../bvm/Shaders/pbft/pbft_stat.wasm" "${CMAKE_CURRENT_BINARY_DIR}/pbft/pbft_stat.wasm" COPYONLY) -configure_file("../../bvm/Shaders/Explorer/Parser.wasm" "${CMAKE_CURRENT_BINARY_DIR}/Explorer/Parser.wasm" COPYONLY) diff --git a/node/unittests/node_test.cpp b/node/unittests/node_test.cpp index ad7399d793..73e77df42c 100644 --- a/node/unittests/node_test.cpp +++ b/node/unittests/node_test.cpp @@ -19,12 +19,12 @@ #include "../processor.h" #include "../bridge.h" #include "../../core/fly_client.h" -#include "../../core/serialization_adapters.h" +#include "../../core/serialization_adapters.h" #include "../../core/treasury.h" #include "../../core/block_rw.h" #include "../../utility/test_helpers.h" -#include "../../utility/serialize.h" -#include "../../utility/blobmap.h" +#include "../../utility/serialize.h" +#include "../../utility/blobmap.h" #include "../../core/unittest/mini_blockchain.h" #include "../../bvm/bvm2.h" #include "../../bvm/ManagerStd.h" @@ -35,13 +35,13 @@ #endif #include "utility/logger.h" -namespace Shaders { -# define HOST_BUILD -# include "../bvm/Shaders/common.h" -# include "../bvm/Shaders/sidechain_pos/contract_l2.h" -# include "../bvm/Shaders/pbft/pbft_dpos.h" -# include "../bvm/Shaders/pbft/pbft_stat.h" -} // namespace Shaders +namespace Shaders { +# define HOST_BUILD +# include "../bvm/Shaders/common.h" +# include "../bvm/Shaders/sidechain_pos/contract_l2.h" +# include "../bvm/Shaders/pbft/pbft_dpos.h" +# include "../bvm/Shaders/pbft/pbft_stat.h" +} // namespace Shaders namespace ECC { @@ -175,35 +175,35 @@ namespace beam Treasury::Data BuildTreasuryData() { - PeerID pid; - ECC::Scalar::Native sk; - Treasury::get_ID(*g_pTreasuryKdf, pid, sk); - - Treasury tres; - Treasury::Parameters pars; - pars.m_Bursts = 1; - pars.m_MaturityStep = 4; - Treasury::Entry* pE = tres.CreatePlan(pid, Rules::get().Emission.Value0 / 5, pars); - - pE->m_pResponse.reset(new Treasury::Response); - uint64_t nIndex = 1; - verify_test(pE->m_pResponse->Create(pE->m_Request, *g_pTreasuryKdf, nIndex)); - - Treasury::Data data; - data.m_sCustomMsg = "test treasury"; - tres.Build(data); - - return data; + PeerID pid; + ECC::Scalar::Native sk; + Treasury::get_ID(*g_pTreasuryKdf, pid, sk); + + Treasury tres; + Treasury::Parameters pars; + pars.m_Bursts = 1; + pars.m_MaturityStep = 4; + Treasury::Entry* pE = tres.CreatePlan(pid, Rules::get().Emission.Value0 / 5, pars); + + pE->m_pResponse.reset(new Treasury::Response); + uint64_t nIndex = 1; + verify_test(pE->m_pResponse->Create(pE->m_Request, *g_pTreasuryKdf, nIndex)); + + Treasury::Data data; + data.m_sCustomMsg = "test treasury"; + tres.Build(data); + + return data; } void FinalizeTreasuryData(Rules& r, const Treasury::Data& td) { - beam::Serializer ser; - ser & td; - - ser.swap_buf(g_Treasury); - - ECC::Hash::Processor() << Blob(g_Treasury) >> r.TreasuryChecksum; + beam::Serializer ser; + ser & td; + + ser.swap_buf(g_Treasury); + + ECC::Hash::Processor() << Blob(g_Treasury) >> r.TreasuryChecksum; } uint32_t CountTips(NodeDB& db, bool bFunctional, NodeDB::StateID* pLast = NULL) @@ -228,27 +228,27 @@ namespace beam struct StoragePts { - ECC::Point::Storage m_pArr[18]; - - void Init() - { - for (size_t i = 0; i < _countof(m_pArr); i++) - { - m_pArr[i].m_X = i; - } - } - - bool IsValid(size_t i0, size_t i1, uint32_t n0) const - { - for (; i0 < i1; i0++) - { - if (m_pArr[i0].m_X != ECC::uintBig(n0++)) - return false; - } - - return true; - } - }; + ECC::Point::Storage m_pArr[18]; + + void Init() + { + for (size_t i = 0; i < _countof(m_pArr); i++) + { + m_pArr[i].m_X = i; + } + } + + bool IsValid(size_t i0, size_t i1, uint32_t n0) const + { + for (; i0 < i1; i0++) + { + if (m_pArr[i0].m_X != ECC::uintBig(n0++)) + return false; + } + + return true; + } + }; void TestNodeDB(const char* sz) { @@ -409,16 +409,16 @@ namespace beam sid.m_Row = pRows[sid.m_Number.v - 1]; db.MoveFwd(sid); - Merkle::Hash hv; - if (sid.m_Number.v < 1 + 50) // skip it for big heights, coz it's quadratic - { + Merkle::Hash hv; + if (sid.m_Number.v < 1 + 50) // skip it for big heights, coz it's quadratic + { for (Height h = 1; h < sid.m_Number.v; h++) { Merkle::ProofBuilderStd bld; smmr.get_Proof(bld, smmr.N2I(Block::Number(h))); - vStates[h - 1].get_Hash(hv); - Merkle::Interpret(hv, bld.m_Proof); + vStates[h - 1].get_Hash(hv); + Merkle::Interpret(hv, bld.m_Proof); verify_test(hvRoot == hv); } } @@ -426,7 +426,7 @@ namespace beam const Block::SystemState::Full& sTop = vStates[sid.m_Number.v - 1]; hv = hvRoot; - Merkle::Interpret(hv, hvZero, true); + Merkle::Interpret(hv, hvZero, true); verify_test(hv == sTop.m_Definition); sTop.get_Hash(hv); @@ -536,196 +536,196 @@ namespace beam verify_test(db.GetDummyHeight(kid) == MaxHeight); - db.InsertDummy(176, kid); - - kid.m_Idx = 346; - db.InsertDummy(568, kid); + db.InsertDummy(176, kid); + + kid.m_Idx = 346; + db.InsertDummy(568, kid); - kid.m_Idx = 345; + kid.m_Idx = 345; verify_test(db.GetDummyHeight(kid) == 176); - - Height h1 = db.GetLowestDummy(kid); - verify_test(h1 == 176); - verify_test(kid.m_Idx == 345U); - - db.SetDummyHeight(kid, 1055); - - h1 = db.GetLowestDummy(kid); - verify_test(h1 == 568); - verify_test(kid.m_Idx == 346U); - - db.DeleteDummy(kid); - - h1 = db.GetLowestDummy(kid); - verify_test(h1 == 1055); - verify_test(kid.m_Idx == 345U); - - db.DeleteDummy(kid); - - verify_test(MaxHeight == db.GetLowestDummy(kid)); - - // Kernels - db.InsertKernel(bBodyP, 5); - db.InsertKernel(bBodyP, 5); // duplicate - db.InsertKernel(bBodyP, 7); - db.InsertKernel(bBodyP, 2); - - verify_test(db.FindKernel(bBodyP) == 7); - verify_test(db.FindKernel(bBodyE) == 0); - - db.DeleteKernel(bBodyP, 7); - verify_test(db.FindKernel(bBodyP) == 5); - db.DeleteKernel(bBodyP, 5); - verify_test(db.FindKernel(bBodyP) == 5); - db.DeleteKernel(bBodyP, 2); - verify_test(db.FindKernel(bBodyP) == 5); - db.DeleteKernel(bBodyP, 5); - verify_test(db.FindKernel(bBodyP) == 0); - - // Shielded - TxoID nShielded = 16 * 1024 * 3 + 5; - db.ShieldedResize(nShielded, 0); - - StoragePts pts; - pts.Init(); - - db.ShieldedWrite(16 * 1024 * 2 - 2, pts.m_pArr, _countof(pts.m_pArr)); - - ZeroObject(pts.m_pArr); - - db.ShieldedRead(16 * 1024 * 3 + 5 - _countof(pts.m_pArr), pts.m_pArr, _countof(pts.m_pArr)); - verify_test(memis0(pts.m_pArr, sizeof(pts.m_pArr))); - - db.ShieldedRead(16 * 1024 * 2 -2, pts.m_pArr, _countof(pts.m_pArr)); - verify_test(pts.IsValid(0, _countof(pts.m_pArr), 0)); - - db.ShieldedResize(1, nShielded); - db.ShieldedResize(0, 1); - - ECC::uintBig k1 = 223U; - Blob val(nullptr, 0); - - verify_test(db.UniqueInsertSafe(k1, &val)); - db.UniqueDeleteStrict(k1); - verify_test(db.UniqueInsertSafe(k1, nullptr)); - verify_test(!db.UniqueInsertSafe(k1, nullptr)); - - - // Assets - Asset::Full ai1, ai2; - ZeroObject(ai1); - - for (uint32_t i = 1; i <= 5; i++) - { - ai1.m_ID = 0; - db.AssetAdd(ai1); - verify_test(ai1.m_ID == i); - } - - verify_test(db.AssetDelete(5) == 4); // should shrink - verify_test(db.AssetDelete(3) == 4); // should retain the same size - - ai2.m_ID = 3; - verify_test(!db.AssetGetSafe(ai2)); - ai2.m_ID = 2; - verify_test(db.AssetGetSafe(ai2)); - verify_test(ai2.m_Owner == ai1.m_Owner); - - ai1.m_Owner.Inc(); - ai1.m_Owner.Negate(); - ai1.m_ID = 0; - db.AssetAdd(ai1); - verify_test(ai1.m_ID == 3); - - AmountBig::Type assetVal1, assetVal2 = 1U; - ai2.m_ID = 3; - verify_test(db.AssetGetSafe(ai2)); - verify_test(ai2.m_Value == Zero); - - assetVal2 = 334U; - db.AssetSetValue(3, assetVal2, 18); - - verify_test(db.AssetGetSafe(ai2)); - verify_test(ai2.m_Value == assetVal2); - verify_test(ai2.m_LockHeight == 18); - - ai1.m_ID = db.AssetFindByOwner(ai1.m_Owner); - verify_test(ai1.m_ID == 3); - ai1.m_Value = Zero; - verify_test(db.AssetGetSafe(ai1)); - verify_test(ai1.m_Value == assetVal2); - - verify_test(db.AssetDelete(2) == 4); - verify_test(db.AssetDelete(3) == 4); - verify_test(db.AssetDelete(4) == 1); - verify_test(db.AssetDelete(1) == 0); - - // StreamMmr, test cache - struct MyMmr - :public NodeDB::StreamMmr - { - using StreamMmr::StreamMmr; - uint32_t m_Total = 0; - uint32_t m_Miss = 0; - - void LoadElement(Merkle::Hash& hv, const Merkle::Position& pos) const override - { - Cast::NotConst(this)->m_Total++; - if (!CacheFind(hv, pos)) - { - Cast::NotConst(this)->m_Miss++; - StreamMmr::LoadElement(hv, pos); - } - } - }; - - MyMmr myMmr(db, NodeDB::StreamType::ShieldedMmr, true); - - for (uint32_t i = 0; i < 40; i++) - { - Merkle::Hash hv = i; - myMmr.Append(hv); - myMmr.get_Hash(hv); - } - - // in a 'friendly' scenario, where we only add and calculate root - cache must be 100% effective - verify_test(!myMmr.m_Miss); - + + Height h1 = db.GetLowestDummy(kid); + verify_test(h1 == 176); + verify_test(kid.m_Idx == 345U); + + db.SetDummyHeight(kid, 1055); + + h1 = db.GetLowestDummy(kid); + verify_test(h1 == 568); + verify_test(kid.m_Idx == 346U); + + db.DeleteDummy(kid); + + h1 = db.GetLowestDummy(kid); + verify_test(h1 == 1055); + verify_test(kid.m_Idx == 345U); + + db.DeleteDummy(kid); + + verify_test(MaxHeight == db.GetLowestDummy(kid)); + + // Kernels + db.InsertKernel(bBodyP, 5); + db.InsertKernel(bBodyP, 5); // duplicate + db.InsertKernel(bBodyP, 7); + db.InsertKernel(bBodyP, 2); + + verify_test(db.FindKernel(bBodyP) == 7); + verify_test(db.FindKernel(bBodyE) == 0); + + db.DeleteKernel(bBodyP, 7); + verify_test(db.FindKernel(bBodyP) == 5); + db.DeleteKernel(bBodyP, 5); + verify_test(db.FindKernel(bBodyP) == 5); + db.DeleteKernel(bBodyP, 2); + verify_test(db.FindKernel(bBodyP) == 5); + db.DeleteKernel(bBodyP, 5); + verify_test(db.FindKernel(bBodyP) == 0); + + // Shielded + TxoID nShielded = 16 * 1024 * 3 + 5; + db.ShieldedResize(nShielded, 0); + + StoragePts pts; + pts.Init(); + + db.ShieldedWrite(16 * 1024 * 2 - 2, pts.m_pArr, _countof(pts.m_pArr)); + + ZeroObject(pts.m_pArr); + + db.ShieldedRead(16 * 1024 * 3 + 5 - _countof(pts.m_pArr), pts.m_pArr, _countof(pts.m_pArr)); + verify_test(memis0(pts.m_pArr, sizeof(pts.m_pArr))); + + db.ShieldedRead(16 * 1024 * 2 -2, pts.m_pArr, _countof(pts.m_pArr)); + verify_test(pts.IsValid(0, _countof(pts.m_pArr), 0)); + + db.ShieldedResize(1, nShielded); + db.ShieldedResize(0, 1); + + ECC::uintBig k1 = 223U; + Blob val(nullptr, 0); + + verify_test(db.UniqueInsertSafe(k1, &val)); + db.UniqueDeleteStrict(k1); + verify_test(db.UniqueInsertSafe(k1, nullptr)); + verify_test(!db.UniqueInsertSafe(k1, nullptr)); + + + // Assets + Asset::Full ai1, ai2; + ZeroObject(ai1); + + for (uint32_t i = 1; i <= 5; i++) + { + ai1.m_ID = 0; + db.AssetAdd(ai1); + verify_test(ai1.m_ID == i); + } + + verify_test(db.AssetDelete(5) == 4); // should shrink + verify_test(db.AssetDelete(3) == 4); // should retain the same size + + ai2.m_ID = 3; + verify_test(!db.AssetGetSafe(ai2)); + ai2.m_ID = 2; + verify_test(db.AssetGetSafe(ai2)); + verify_test(ai2.m_Owner == ai1.m_Owner); + + ai1.m_Owner.Inc(); + ai1.m_Owner.Negate(); + ai1.m_ID = 0; + db.AssetAdd(ai1); + verify_test(ai1.m_ID == 3); + + AmountBig::Type assetVal1, assetVal2 = 1U; + ai2.m_ID = 3; + verify_test(db.AssetGetSafe(ai2)); + verify_test(ai2.m_Value == Zero); + + assetVal2 = 334U; + db.AssetSetValue(3, assetVal2, 18); + + verify_test(db.AssetGetSafe(ai2)); + verify_test(ai2.m_Value == assetVal2); + verify_test(ai2.m_LockHeight == 18); + + ai1.m_ID = db.AssetFindByOwner(ai1.m_Owner); + verify_test(ai1.m_ID == 3); + ai1.m_Value = Zero; + verify_test(db.AssetGetSafe(ai1)); + verify_test(ai1.m_Value == assetVal2); + + verify_test(db.AssetDelete(2) == 4); + verify_test(db.AssetDelete(3) == 4); + verify_test(db.AssetDelete(4) == 1); + verify_test(db.AssetDelete(1) == 0); + + // StreamMmr, test cache + struct MyMmr + :public NodeDB::StreamMmr + { + using StreamMmr::StreamMmr; + uint32_t m_Total = 0; + uint32_t m_Miss = 0; + + void LoadElement(Merkle::Hash& hv, const Merkle::Position& pos) const override + { + Cast::NotConst(this)->m_Total++; + if (!CacheFind(hv, pos)) + { + Cast::NotConst(this)->m_Miss++; + StreamMmr::LoadElement(hv, pos); + } + } + }; + + MyMmr myMmr(db, NodeDB::StreamType::ShieldedMmr, true); + + for (uint32_t i = 0; i < 40; i++) + { + Merkle::Hash hv = i; + myMmr.Append(hv); + myMmr.get_Hash(hv); + } + + // in a 'friendly' scenario, where we only add and calculate root - cache must be 100% effective + verify_test(!myMmr.m_Miss); + tr.Commit(); - // Contract data - NodeDB::Recordset rs, rs2; - Blob blob1; - ECC::Hash::Value hvKey = 234U, hvVal = 1232U, hvKey2; - verify_test(!db.ContractDataFind(hvKey, blob1, rs)); - - blob1 = hvKey; - verify_test(!db.ContractDataFindNext(blob1, rs)); - - db.ContractDataInsert(hvKey, hvVal); - verify_test(!db.ContractDataFindNext(blob1, rs)); - - hvVal.Inc(); - db.ContractDataUpdate(hvKey, hvVal); - - verify_test(db.ContractDataFind(hvKey, blob1, rs)); - verify_test(Blob(hvVal) == blob1); - - verify_test(db.ContractDataFind(hvKey, blob1, rs2)); // test the same query simultaneously - - blob1 = hvKey2; - hvKey2 = hvKey; - hvKey2.Inc(); - verify_test(!db.ContractDataFindNext(blob1, rs)); - - hvKey2 = hvKey; - hvKey2.Negate(); - hvKey2 += ECC::Hash::Value(2U); - hvKey2.Negate(); - verify_test(db.ContractDataFindNext(blob1, rs)); - verify_test(Blob(hvKey) == blob1); - - db.ContractDataDel(hvKey); + // Contract data + NodeDB::Recordset rs, rs2; + Blob blob1; + ECC::Hash::Value hvKey = 234U, hvVal = 1232U, hvKey2; + verify_test(!db.ContractDataFind(hvKey, blob1, rs)); + + blob1 = hvKey; + verify_test(!db.ContractDataFindNext(blob1, rs)); + + db.ContractDataInsert(hvKey, hvVal); + verify_test(!db.ContractDataFindNext(blob1, rs)); + + hvVal.Inc(); + db.ContractDataUpdate(hvKey, hvVal); + + verify_test(db.ContractDataFind(hvKey, blob1, rs)); + verify_test(Blob(hvVal) == blob1); + + verify_test(db.ContractDataFind(hvKey, blob1, rs2)); // test the same query simultaneously + + blob1 = hvKey2; + hvKey2 = hvKey; + hvKey2.Inc(); + verify_test(!db.ContractDataFindNext(blob1, rs)); + + hvKey2 = hvKey; + hvKey2.Negate(); + hvKey2 += ECC::Hash::Value(2U); + hvKey2.Negate(); + verify_test(db.ContractDataFindNext(blob1, rs)); + verify_test(Blob(hvKey) == blob1); + + db.ContractDataDel(hvKey); verify_test(!db.ContractDataFind(hvKey, blob1, rs)); // contract logs @@ -1352,27 +1352,27 @@ namespace beam if (!bTampered) { - Deserializer der; - der.reset(bbP); - - Block::BodyBase bbb; - TxVectors::Perishable txvp; - der & bbb; - der & txvp; - - verify_test(txvp.m_vInputs.empty()); // may contain only treasury, but we don't spend it in the test - - if (!txvp.m_vOutputs.empty()) - { - txvp.m_vOutputs.pop_back(); - - Serializer ser; - ser & bbb; - ser & txvp; - ser.swap_buf(bbP); - - bTampered = true; - } + Deserializer der; + der.reset(bbP); + + Block::BodyBase bbb; + TxVectors::Perishable txvp; + der & bbb; + der & txvp; + + verify_test(txvp.m_vInputs.empty()); // may contain only treasury, but we don't spend it in the test + + if (!txvp.m_vOutputs.empty()) + { + txvp.m_vOutputs.pop_back(); + + Serializer ser; + ser & bbb; + ser & txvp; + ser.swap_buf(bbP); + + bTampered = true; + } } Block::SystemState::ID id; @@ -1399,22 +1399,22 @@ namespace beam if (!bTampered) { - Deserializer der; - der.reset(bbP); - - Block::BodyBase bbb; - TxVectors::Perishable txvp; - der & bbb; - der & txvp; - - bbb.m_Offset.m_Value.Inc(); - - Serializer ser; - ser & bbb; - ser & txvp; - ser.swap_buf(bbP); - - bTampered = true; + Deserializer der; + der.reset(bbP); + + Block::BodyBase bbb; + TxVectors::Perishable txvp; + der & bbb; + der & txvp; + + bbb.m_Offset.m_Value.Inc(); + + Serializer ser; + ser & bbb; + ser & txvp; + ser.swap_buf(bbP); + + bTampered = true; } Block::SystemState::ID id; @@ -1440,32 +1440,32 @@ namespace beam if (!bTampered) { - Deserializer der; - der.reset(bbP); - - Block::BodyBase bbb; - TxVectors::Perishable txvp; - der & bbb; - der & txvp; - - for (size_t j = 0; j < txvp.m_vOutputs.size(); j++) - { - Output& outp = *txvp.m_vOutputs[j]; - if (outp.m_pConfidential) - { - outp.m_pConfidential->m_P_Tag.m_pCondensed[0].m_Value.Inc(); - bTampered = true; - break; - } - } - - if (bTampered) - { - Serializer ser; - ser & bbb; - ser & txvp; - ser.swap_buf(bbP); - } + Deserializer der; + der.reset(bbP); + + Block::BodyBase bbb; + TxVectors::Perishable txvp; + der & bbb; + der & txvp; + + for (size_t j = 0; j < txvp.m_vOutputs.size(); j++) + { + Output& outp = *txvp.m_vOutputs[j]; + if (outp.m_pConfidential) + { + outp.m_pConfidential->m_P_Tag.m_pCondensed[0].m_Value.Inc(); + bTampered = true; + break; + } + } + + if (bTampered) + { + Serializer ser; + ser & bbb; + ser & txvp; + ser.swap_buf(bbP); + } } Block::SystemState::ID id; @@ -1500,33 +1500,33 @@ namespace beam if (!bTampered) { - Deserializer der; - der.reset(bbP); - - Block::BodyBase bbb; - TxVectors::Perishable txvp; - der & bbb; - der & txvp; - - for (size_t j = 0; j < txvp.m_vOutputs.size(); j++) - { - Output& outp = *txvp.m_vOutputs[j]; - if (outp.m_pConfidential || outp.m_pPublic) - { - outp.m_pConfidential.reset(); - outp.m_pPublic.reset(); - bTampered = true; - break; - } - } - - if (bTampered) - { - Serializer ser; - ser & bbb; - ser & txvp; - ser.swap_buf(bbP); - } + Deserializer der; + der.reset(bbP); + + Block::BodyBase bbb; + TxVectors::Perishable txvp; + der & bbb; + der & txvp; + + for (size_t j = 0; j < txvp.m_vOutputs.size(); j++) + { + Output& outp = *txvp.m_vOutputs[j]; + if (outp.m_pConfidential || outp.m_pPublic) + { + outp.m_pConfidential.reset(); + outp.m_pPublic.reset(); + bTampered = true; + break; + } + } + + if (bTampered) + { + Serializer ser; + ser & bbb; + ser & txvp; + ser.swap_buf(bbP); + } } Block::SystemState::ID id; @@ -1562,33 +1562,33 @@ namespace beam if (!hTampered.v) { - Deserializer der; - der.reset(bbP); - - Block::BodyBase bbb; - TxVectors::Perishable txvp; - der & bbb; - der & txvp; - - for (size_t j = 0; j < txvp.m_vOutputs.size(); j++) - { - Output& outp = *txvp.m_vOutputs[j]; - if (outp.m_pConfidential || outp.m_pPublic) - { - outp.m_pConfidential.reset(); - outp.m_pPublic.reset(); - hTampered = h; - break; - } - } - - if (hTampered.v) - { - Serializer ser; - ser & bbb; - ser & txvp; - ser.swap_buf(bbP); - } + Deserializer der; + der.reset(bbP); + + Block::BodyBase bbb; + TxVectors::Perishable txvp; + der & bbb; + der & txvp; + + for (size_t j = 0; j < txvp.m_vOutputs.size(); j++) + { + Output& outp = *txvp.m_vOutputs[j]; + if (outp.m_pConfidential || outp.m_pPublic) + { + outp.m_pConfidential.reset(); + outp.m_pPublic.reset(); + hTampered = h; + break; + } + } + + if (hTampered.v) + { + Serializer ser; + ser & bbb; + ser & txvp; + ser.swap_buf(bbP); + } } Block::SystemState::ID id; @@ -1757,8 +1757,8 @@ namespace beam Key::IPKdf::Ptr m_pOwner2; uint32_t m_nUnrecognized = 0; - bool OnUtxo(Height h, const Output& outp) override - { + bool OnUtxo(Height h, const Output& outp) override + { CoinID cid; bool b1 = outp.Recover(h, *m_pOwner1, cid); bool b2 = outp.Recover(h, *m_pOwner2, cid); @@ -1768,9 +1768,9 @@ namespace beam m_nUnrecognized++; verify_test(m_nUnrecognized <= 1); } - - return true; - } + + return true; + } } parser; parser.m_pOwner1 = node.m_Keys.m_pOwner; parser.m_pOwner2 = node2.m_Keys.m_pOwner; @@ -1798,138 +1798,138 @@ namespace beam struct PbftTreasuryBuilderBase { - Treasury::Data::Group& m_Tg; - PbftTreasuryBuilderBase(Treasury::Data::Group& tg) - :m_Tg(tg) - { - } - - void FixOffset(ECC::Scalar::Native& sk, bool isOutp) - { - if (isOutp) - sk = -sk; - m_Tg.m_Data.m_Offset = ECC::Scalar::Native(m_Tg.m_Data.m_Offset) + sk; - } + Treasury::Data::Group& m_Tg; + PbftTreasuryBuilderBase(Treasury::Data::Group& tg) + :m_Tg(tg) + { + } + + void FixOffset(ECC::Scalar::Native& sk, bool isOutp) + { + if (isOutp) + sk = -sk; + m_Tg.m_Data.m_Offset = ECC::Scalar::Native(m_Tg.m_Data.m_Offset) + sk; + } }; - struct PbftTreasuryBuilder_Dpos - :public PbftTreasuryBuilderBase - { - ContractID m_Cid; - Shaders::PBFT_DPOS::Settings m_Settings; - - PbftTreasuryBuilder_Dpos(Treasury::Data::Group& tg) - :PbftTreasuryBuilderBase(tg) - { - ZeroObject(m_Settings); - } - - void Init() - { - m_Tg.m_Aid = m_Settings.m_aidStake; - - auto pKrn = std::make_unique(); - beam::bvm2::Compile(pKrn->m_Data, "pbft/pbft_dpos.wasm", beam::bvm2::Processor::Kind::Contract); - - pKrn->m_Args.resize(sizeof(Shaders::PBFT_DPOS::Method::Create)); - auto& args = *(Shaders::PBFT_DPOS::Method::Create*) &pKrn->m_Args.front(); - ZeroObject(args); - - args.m_Settings.m_aidStake = ByteOrder::to_le(m_Settings.m_aidStake); - args.m_Settings.m_hUnbondLock = ByteOrder::to_le(m_Settings.m_hUnbondLock); - args.m_Settings.m_MinValidatorStake = ByteOrder::to_le(m_Settings.m_MinValidatorStake); - - ECC::Scalar::Native sk; - sk.GenRandomNnz(); - ECC::Point::Native ptFunds(beam::Zero); - pKrn->Sign(&sk, 1, ptFunds, nullptr); - - bvm2::get_Cid(m_Cid, pKrn->m_Data, pKrn->m_Args); - - m_Tg.m_Data.m_vKernels.push_back(std::move(pKrn)); - FixOffset(sk, true); - } - - void AddValidator(const Block::Pbft::Address& addr, const ECC::Point& pkDelegator, Amount stake) - { - auto pKrn = std::make_unique(); - pKrn->m_Cid = m_Cid; - - pKrn->m_Args.resize(sizeof(Shaders::PBFT_DPOS::Method::ValidatorRegister)); - auto& args = *(Shaders::PBFT_DPOS::Method::ValidatorRegister*)&pKrn->m_Args.front(); - pKrn->m_iMethod = args.s_iMethod; - - ZeroObject(args); - args.m_Commission_cpc = 500; - args.m_Stake = ByteOrder::to_le(stake); - args.m_Validator = Cast::Down(addr); - args.m_Delegator = pkDelegator; - - ECC::Point::Native ptFunds(Zero); - CoinID::Generator(m_Settings.m_aidStake).AddValue(ptFunds, stake); - - ECC::Scalar::Native sk; - sk.GenRandomNnz(); - pKrn->Sign(&sk, 1, ptFunds, nullptr); - - m_Tg.m_Data.m_vKernels.push_back(std::move(pKrn)); - FixOffset(sk, true); - - m_Tg.m_Value += MultiWord::From(stake); - } + struct PbftTreasuryBuilder_Dpos + :public PbftTreasuryBuilderBase + { + ContractID m_Cid; + Shaders::PBFT_DPOS::Settings m_Settings; + + PbftTreasuryBuilder_Dpos(Treasury::Data::Group& tg) + :PbftTreasuryBuilderBase(tg) + { + ZeroObject(m_Settings); + } + + void Init() + { + m_Tg.m_Aid = m_Settings.m_aidStake; + + auto pKrn = std::make_unique(); + beam::bvm2::Compile(pKrn->m_Data, "pbft/pbft_dpos.wasm", beam::bvm2::Processor::Kind::Contract); + + pKrn->m_Args.resize(sizeof(Shaders::PBFT_DPOS::Method::Create)); + auto& args = *(Shaders::PBFT_DPOS::Method::Create*) &pKrn->m_Args.front(); + ZeroObject(args); + + args.m_Settings.m_aidStake = ByteOrder::to_le(m_Settings.m_aidStake); + args.m_Settings.m_hUnbondLock = ByteOrder::to_le(m_Settings.m_hUnbondLock); + args.m_Settings.m_MinValidatorStake = ByteOrder::to_le(m_Settings.m_MinValidatorStake); + + ECC::Scalar::Native sk; + sk.GenRandomNnz(); + ECC::Point::Native ptFunds(beam::Zero); + pKrn->Sign(&sk, 1, ptFunds, nullptr); + + bvm2::get_Cid(m_Cid, pKrn->m_Data, pKrn->m_Args); + + m_Tg.m_Data.m_vKernels.push_back(std::move(pKrn)); + FixOffset(sk, true); + } + + void AddValidator(const Block::Pbft::Address& addr, const ECC::Point& pkDelegator, Amount stake) + { + auto pKrn = std::make_unique(); + pKrn->m_Cid = m_Cid; + + pKrn->m_Args.resize(sizeof(Shaders::PBFT_DPOS::Method::ValidatorRegister)); + auto& args = *(Shaders::PBFT_DPOS::Method::ValidatorRegister*)&pKrn->m_Args.front(); + pKrn->m_iMethod = args.s_iMethod; + + ZeroObject(args); + args.m_Commission_cpc = 500; + args.m_Stake = ByteOrder::to_le(stake); + args.m_Validator = Cast::Down(addr); + args.m_Delegator = pkDelegator; + + ECC::Point::Native ptFunds(Zero); + CoinID::Generator(m_Settings.m_aidStake).AddValue(ptFunds, stake); + + ECC::Scalar::Native sk; + sk.GenRandomNnz(); + pKrn->Sign(&sk, 1, ptFunds, nullptr); + + m_Tg.m_Data.m_vKernels.push_back(std::move(pKrn)); + FixOffset(sk, true); + + m_Tg.m_Value += MultiWord::From(stake); + } }; - struct PbftTreasuryBuilder_Stat - :public PbftTreasuryBuilderBase - { - typedef Shaders::PBFT_STAT::Method::Create::ValidatorInit ValidatorInit; - std::vector m_vInit; - - using PbftTreasuryBuilderBase::PbftTreasuryBuilderBase; - - void AddValidator(const Block::Pbft::Address& addr, const ECC::Point& /* pkDelegator */, Amount stake) - { - AddValidator(addr, stake); - } - - void AddValidator(const Block::Pbft::Address& addr, Amount stake) - { - auto& x = m_vInit.emplace_back(); - x.m_Address = Cast::Down(addr); - x.m_Weight = stake; - } - - void Export() - { - verify_test(!m_vInit.empty()); - - auto pKrn = std::make_unique(); - beam::bvm2::Compile(pKrn->m_Data, "pbft/pbft_stat.wasm", beam::bvm2::Processor::Kind::Contract); - - pKrn->m_Args.resize(sizeof(Shaders::PBFT_STAT::Method::Create) + sizeof(ValidatorInit) * m_vInit.size()); - auto& args = *(Shaders::PBFT_STAT::Method::Create*) &pKrn->m_Args.front(); - ZeroObject(args); - args.m_Count = ByteOrder::to_le(static_cast(m_vInit.size())); - - for (uint32_t i = 0; i < m_vInit.size(); i++) - { - const auto& src = m_vInit[i]; - auto& dst = args.get_VI()[i]; - - dst.m_Address = src.m_Address; - dst.m_Weight = ByteOrder::to_le(src.m_Weight); - } - - ECC::Scalar::Native sk; - sk.GenRandomNnz(); - ECC::Point::Native ptFunds(beam::Zero); - pKrn->Sign(&sk, 1, ptFunds, nullptr); - - m_Tg.m_Data.m_vKernels.push_back(std::move(pKrn)); - FixOffset(sk, true); - } - + struct PbftTreasuryBuilder_Stat + :public PbftTreasuryBuilderBase + { + typedef Shaders::PBFT_STAT::Method::Create::ValidatorInit ValidatorInit; + std::vector m_vInit; + + using PbftTreasuryBuilderBase::PbftTreasuryBuilderBase; + + void AddValidator(const Block::Pbft::Address& addr, const ECC::Point& /* pkDelegator */, Amount stake) + { + AddValidator(addr, stake); + } + + void AddValidator(const Block::Pbft::Address& addr, Amount stake) + { + auto& x = m_vInit.emplace_back(); + x.m_Address = Cast::Down(addr); + x.m_Weight = stake; + } + + void Export() + { + verify_test(!m_vInit.empty()); + + auto pKrn = std::make_unique(); + beam::bvm2::Compile(pKrn->m_Data, "pbft/pbft_stat.wasm", beam::bvm2::Processor::Kind::Contract); + + pKrn->m_Args.resize(sizeof(Shaders::PBFT_STAT::Method::Create) + sizeof(ValidatorInit) * m_vInit.size()); + auto& args = *(Shaders::PBFT_STAT::Method::Create*) &pKrn->m_Args.front(); + ZeroObject(args); + args.m_Count = ByteOrder::to_le(static_cast(m_vInit.size())); + + for (uint32_t i = 0; i < m_vInit.size(); i++) + { + const auto& src = m_vInit[i]; + auto& dst = args.get_VI()[i]; + + dst.m_Address = src.m_Address; + dst.m_Weight = ByteOrder::to_le(src.m_Weight); + } + + ECC::Scalar::Native sk; + sk.GenRandomNnz(); + ECC::Point::Native ptFunds(beam::Zero); + pKrn->Sign(&sk, 1, ptFunds, nullptr); + + m_Tg.m_Data.m_vKernels.push_back(std::move(pKrn)); + FixOffset(sk, true); + } + }; void TestNodeClientProto(Rules& r, bool bTestPbft, bool bTestBridge) { @@ -2216,13 +2216,13 @@ namespace beam if (!sdp.m_Output.m_Value) return false; - auto& fs = Transaction::FeeSettings::get(h + 1); + auto& fs = Transaction::FeeSettings::get(h + 1); Amount fee = fs.get_DefaultStd() + fs.m_ShieldedOutputTotal; sdp.m_Output.m_Value -= fee; m_Shielded.m_Cfg = Rules::get().Shielded.m_ProofMax; - + assert(msgTx.m_Transaction); { @@ -2246,17 +2246,17 @@ namespace beam // skip the voucher signature } - ECC::Oracle oracle; - oracle << pKrn->get_Msg(); + ECC::Oracle oracle; + oracle << pKrn->get_Msg(); // substitute the voucher pKrn->m_Txo.m_Ticket = voucher.m_Ticket; - sdp.m_Ticket.m_SharedSecret = voucher.m_SharedSecret; + sdp.m_Ticket.m_SharedSecret = voucher.m_SharedSecret; ZeroObject(sdp.m_Output.m_User); - sdp.m_Output.m_User.m_Sender = 165U; - sdp.m_Output.m_User.m_pMessage[0] = 243U; - sdp.m_Output.m_User.m_pMessage[1] = 2435U; + sdp.m_Output.m_User.m_Sender = 165U; + sdp.m_Output.m_User.m_pMessage[0] = 243U; + sdp.m_Output.m_User.m_pMessage[1] = 2435U; sdp.GenerateOutp(pKrn->m_Txo, h + 1, oracle); m_Shielded.m_SerialPub = pKrn->m_Txo.m_Ticket.m_SerialPub; @@ -2299,48 +2299,48 @@ namespace beam msgTx.m_Transaction = std::make_shared(); msgTx.m_Transaction->m_Offset = Zero; - Height h = m_vStates.back().get_Height(); - - TxKernelShieldedInput::Ptr pKrn(new TxKernelShieldedInput); - pKrn->m_Height.m_Min = h + 1; - pKrn->m_WindowEnd = nWnd1; - pKrn->m_SpendProof.m_Cfg = m_Shielded.m_Cfg; + Height h = m_vStates.back().get_Height(); + + TxKernelShieldedInput::Ptr pKrn(new TxKernelShieldedInput); + pKrn->m_Height.m_Min = h + 1; + pKrn->m_WindowEnd = nWnd1; + pKrn->m_SpendProof.m_Cfg = m_Shielded.m_Cfg; Lelantus::CmListVec lst; assert(nWnd1 <= m_Shielded.m_Wnd0 + m_Shielded.m_N); if (nWnd1 == m_Shielded.m_Wnd0 + m_Shielded.m_N) - lst.m_vec.swap(msg.m_Items); - else - { - // zero-pad from left - lst.m_vec.resize(m_Shielded.m_N); - for (size_t i = 0; i < m_Shielded.m_N - msg.m_Items.size(); i++) - { - ECC::Point::Storage& v = lst.m_vec[i]; - v.m_X = Zero; - v.m_Y = Zero; - } - std::copy(msg.m_Items.begin(), msg.m_Items.end(), lst.m_vec.end() - msg.m_Items.size()); - } - - Lelantus::Prover p(lst, pKrn->m_SpendProof); + lst.m_vec.swap(msg.m_Items); + else + { + // zero-pad from left + lst.m_vec.resize(m_Shielded.m_N); + for (size_t i = 0; i < m_Shielded.m_N - msg.m_Items.size(); i++) + { + ECC::Point::Storage& v = lst.m_vec[i]; + v.m_X = Zero; + v.m_Y = Zero; + } + std::copy(msg.m_Items.begin(), msg.m_Items.end(), lst.m_vec.end() - msg.m_Items.size()); + } + + Lelantus::Prover p(lst, pKrn->m_SpendProof); p.m_Witness.m_L = static_cast(m_Shielded.m_N - m_Shielded.m_Confirmed) - 1; p.m_Witness.m_R = m_Shielded.m_Params.m_Ticket.m_pK[0] + m_Shielded.m_Params.m_Output.m_k; // total blinding factor of the shielded element p.m_Witness.m_SpendSk = m_Shielded.m_skSpendKey; p.m_Witness.m_V = m_Shielded.m_Params.m_Output.m_Value; - ECC::SetRandom(p.m_Witness.m_R_Output); + ECC::SetRandom(p.m_Witness.m_R_Output); pKrn->m_NotSerialized.m_hvShieldedState = msg.m_State1; pKrn->Sign(p, 0); verify_test(m_Shielded.m_Params.m_Ticket.m_SpendPk == pKrn->m_SpendProof.m_SpendPk); - auto& fs = Transaction::FeeSettings::get(h + 1); + auto& fs = Transaction::FeeSettings::get(h + 1); Amount fee = fs.get_DefaultStd() + fs.m_ShieldedInputTotal; - msgTx.m_Transaction->m_vKernels.push_back(std::move(pKrn)); + msgTx.m_Transaction->m_vKernels.push_back(std::move(pKrn)); m_Wallet.UpdateOffset(*msgTx.m_Transaction, p.m_Witness.m_R_Output, false); m_Wallet.MakeTxOutput(*msgTx.m_Transaction, h, 0, m_Shielded.m_Params.m_Output.m_Value, fee); @@ -2349,12 +2349,12 @@ namespace beam ctx.m_Height.m_Min = h + 1; verify_test(msgTx.m_Transaction->IsValid(ctx)); - for (size_t i = 0; i < msgTx.m_Transaction->m_vKernels.size(); i++) - { - const TxKernel& krn = *msgTx.m_Transaction->m_vKernels[i]; - if (krn.get_Subtype() == TxKernel::Subtype::Std) - m_Shielded.m_SpendKernelID = krn.get_ID(); - } + for (size_t i = 0; i < msgTx.m_Transaction->m_vKernels.size(); i++) + { + const TxKernel& krn = *msgTx.m_Transaction->m_vKernels[i]; + if (krn.get_Subtype() == TxKernel::Subtype::Std) + m_Shielded.m_SpendKernelID = krn.get_ID(); + } msgTx.m_Fluff = true; OnBeingSpent(msgTx); @@ -2817,13 +2817,13 @@ namespace beam #pragma pack (push, 1) // copied from sidechain_pos/contract_l2.h - struct BridgeOp - { - Asset::ID m_Aid; - Amount m_Amount; - uint64_t m_Cookie; - ECC::Point m_pk; - }; + struct BridgeOp + { + Asset::ID m_Aid; + Amount m_Amount; + uint64_t m_Cookie; + ECC::Point m_pk; + }; #pragma pack (pop) TxKernelContractInvoke::Ptr pKrn(new TxKernelContractInvoke); @@ -2884,64 +2884,64 @@ namespace beam { } - void OnDone(const std::exception* pExc) override - { - m_Done = true; - m_Err = !!pExc; - + void OnDone(const std::exception* pExc) override + { + m_Done = true; + m_Err = !!pExc; + m_This.m_Contract.m_Done++; - - if (m_This.m_pMan) - { - if (!m_Err) + + if (m_This.m_pMan) + { + if (!m_Err) printf("manager shader: %s\n", m_Out.str().c_str()); - - //m_This.m_pMan.reset(); - } - } - - struct DelayedStart - :public io::IdleEvt - { - void OnSchedule() override - { - cancel(); - get_ParentObj().StartRun(1); - } - - IMPLEMENT_GET_PARENT_OBJ(MyManager, m_DelayedStart) - - } m_DelayedStart; - - std::map m_Slots; - - bool SlotLoad(ECC::Hash::Value& hv, uint32_t iSlot) override - { - auto it = m_Slots.find(iSlot); - if (m_Slots.end() == it) - return false; - - hv = it->second; - return true; - } - - void SlotSave(const ECC::Hash::Value& hv, uint32_t iSlot) override - { - m_Slots[iSlot] = hv; - } - - void SlotErase(uint32_t iSlot) override - { - auto it = m_Slots.find(iSlot); - if (m_Slots.end() != it) - m_Slots.erase(it); - } - - void SelectContext(bool /* bDependent */, uint32_t /* nChargeNeeded */) override - { - m_Context.m_Height = m_This.m_vStates.empty() ? 0 : m_This.m_vStates.back().get_Height(); - } - + + //m_This.m_pMan.reset(); + } + } + + struct DelayedStart + :public io::IdleEvt + { + void OnSchedule() override + { + cancel(); + get_ParentObj().StartRun(1); + } + + IMPLEMENT_GET_PARENT_OBJ(MyManager, m_DelayedStart) + + } m_DelayedStart; + + std::map m_Slots; + + bool SlotLoad(ECC::Hash::Value& hv, uint32_t iSlot) override + { + auto it = m_Slots.find(iSlot); + if (m_Slots.end() == it) + return false; + + hv = it->second; + return true; + } + + void SlotSave(const ECC::Hash::Value& hv, uint32_t iSlot) override + { + m_Slots[iSlot] = hv; + } + + void SlotErase(uint32_t iSlot) override + { + auto it = m_Slots.find(iSlot); + if (m_Slots.end() != it) + m_Slots.erase(it); + } + + void SelectContext(bool /* bDependent */, uint32_t /* nChargeNeeded */) override + { + m_Context.m_Height = m_This.m_vStates.empty() ? 0 : m_This.m_vStates.back().get_Height(); + } + }; std::unique_ptr m_pMan; @@ -2952,68 +2952,68 @@ namespace beam MyClient& m_This; MyNetwork(MyClient& me) :m_This(me) {} - void Connect() override {} - void Disconnect() override {} - void BbsSubscribe(BbsChannel, Timestamp, proto::FlyClient::IBbsReceiver*) override {} + void Connect() override {} + void Disconnect() override {} + void BbsSubscribe(BbsChannel, Timestamp, proto::FlyClient::IBbsReceiver*) override {} proto::FlyClient::Request::Ptr m_pReq; - void PostRequestInternal(proto::FlyClient::Request& r) override - { - switch (r.get_Type()) - { - case proto::FlyClient::Request::Type::ContractVars: - m_This.Send(Cast::Up(r).m_Msg); - break; - - case proto::FlyClient::Request::Type::ContractLogs: - m_This.Send(Cast::Up(r).m_Msg); - break; - - case proto::FlyClient::Request::Type::ContractVar: - m_This.Send(Cast::Up(r).m_Msg); - break; - - default: - return; - } - - m_pReq = &r; - } - - void OnComplete2() - { - auto pReq = std::move(m_pReq); - pReq->m_pTrg->OnComplete(*pReq); - } - + void PostRequestInternal(proto::FlyClient::Request& r) override + { + switch (r.get_Type()) + { + case proto::FlyClient::Request::Type::ContractVars: + m_This.Send(Cast::Up(r).m_Msg); + break; + + case proto::FlyClient::Request::Type::ContractLogs: + m_This.Send(Cast::Up(r).m_Msg); + break; + + case proto::FlyClient::Request::Type::ContractVar: + m_This.Send(Cast::Up(r).m_Msg); + break; + + default: + return; + } + + m_pReq = &r; + } + + void OnComplete2() + { + auto pReq = std::move(m_pReq); + pReq->m_pTrg->OnComplete(*pReq); + } + void OnMsg(proto::ContractVars&& msg) { - if (m_pReq && m_pReq->m_pTrg) - { - auto& x = Cast::Up(*m_pReq); - x.m_Res = std::move(msg); - OnComplete2(); + if (m_pReq && m_pReq->m_pTrg) + { + auto& x = Cast::Up(*m_pReq); + x.m_Res = std::move(msg); + OnComplete2(); } } void OnMsg(proto::ContractLogs&& msg) { - if (m_pReq && m_pReq->m_pTrg) - { - auto& x = Cast::Up(*m_pReq); - x.m_Res = std::move(msg); - OnComplete2(); + if (m_pReq && m_pReq->m_pTrg) + { + auto& x = Cast::Up(*m_pReq); + x.m_Res = std::move(msg); + OnComplete2(); } } void OnMsg(proto::ContractVar&& msg) { - if (m_pReq && m_pReq->m_pTrg) - { - auto& x = Cast::Up(*m_pReq); - x.m_Res = std::move(msg); - OnComplete2(); + if (m_pReq && m_pReq->m_pTrg) + { + auto& x = Cast::Up(*m_pReq); + x.m_Res = std::move(msg); + OnComplete2(); } } }; @@ -3362,7 +3362,7 @@ namespace beam if (!m_queProofsStateExpected.empty()) { const Block::SystemState::Full& s = m_vStates[m_queProofsStateExpected.front()]; - Block::SystemState::ID id; + Block::SystemState::ID id; s.get_ID(id); verify_test(m_vStates.back().IsValidProofState(id, msg.m_Proof)); @@ -3447,26 +3447,26 @@ namespace beam { if (!m_queProofsKrnExpected.empty()) { - const MiniWallet::MyKernel& mk = m_Wallet.m_MyKernels[m_queProofsKrnExpected.front()]; + const MiniWallet::MyKernel& mk = m_Wallet.m_MyKernels[m_queProofsKrnExpected.front()]; m_queProofsKrnExpected.pop_front(); if (!msg.m_Proof.empty()) { - TxKernelStd krn; - mk.Export(krn); - verify_test(m_vStates.back().IsValidProofKernel(krn, msg.m_Proof)); - - if (!m_Shielded.m_SpendConfirmed && (krn.get_ID() == m_Shielded.m_SpendKernelID)) - { - m_Shielded.m_SpendConfirmed = true; - - proto::GetProofShieldedInp msgOut; - msgOut.m_SpendPk = m_Shielded.m_Params.m_Ticket.m_SpendPk; - Send(msgOut); - + TxKernelStd krn; + mk.Export(krn); + verify_test(m_vStates.back().IsValidProofKernel(krn, msg.m_Proof)); + + if (!m_Shielded.m_SpendConfirmed && (krn.get_ID() == m_Shielded.m_SpendKernelID)) + { + m_Shielded.m_SpendConfirmed = true; + + proto::GetProofShieldedInp msgOut; + msgOut.m_SpendPk = m_Shielded.m_Params.m_Ticket.m_SpendPk; + Send(msgOut); + printf("Waiting for shielded input proof...\n"); - - } + + } } } else @@ -3496,17 +3496,17 @@ namespace beam MyClient& m_This; MyParser(MyClient& x) :m_This(x) {} - void OnEventBase(proto::Event::Base& evt) override - { - // log non-UTXO events - std::ostringstream os; - os << "Evt H=" << m_Height << ", "; - evt.Dump(os); - printf("%s\n", os.str().c_str()); - } - - void OnEventType(proto::Event::Utxo& evt) override - { + void OnEventBase(proto::Event::Base& evt) override + { + // log non-UTXO events + std::ostringstream os; + os << "Evt H=" << m_Height << ", "; + evt.Dump(os); + printf("%s\n", os.str().c_str()); + } + + void OnEventType(proto::Event::Utxo& evt) override + { ECC::Scalar::Native sk; ECC::Point comm; CoinID::Worker(evt.m_Cid).Create(sk, comm, *m_This.m_Wallet.m_pKdf); @@ -3514,24 +3514,24 @@ namespace beam if (evt.m_Cid.m_AssetID) { - verify_test(evt.m_Cid.m_AssetID == m_This.m_Assets.m_ID); - if (!m_This.m_Assets.m_Recognized) - { - m_This.m_Assets.m_Recognized = true; - printf("Asset UTXO recognized\n"); - } + verify_test(evt.m_Cid.m_AssetID == m_This.m_Assets.m_ID); + if (!m_This.m_Assets.m_Recognized) + { + m_This.m_Assets.m_Recognized = true; + printf("Asset UTXO recognized\n"); + } } else { if (proto::Event::Flags::Add & evt.m_Flags) m_This.m_Wallet.AddMyUtxo(evt.m_Cid, evt.m_Maturity); } - } - - void OnEventType(proto::Event::Shielded& evt) override - { - OnEventBase(evt); - + } + + void OnEventType(proto::Event::Shielded& evt) override + { + OnEventBase(evt); + // Restore all the relevent data verify_test(evt.m_TxoID == 0); @@ -3567,29 +3567,29 @@ namespace beam m_This.m_Shielded.m_EvtAdd = true; else m_This.m_Shielded.m_EvtSpend = true; - } - - void OnEventType(proto::Event::AssetCtl& evt) override - { - OnEventBase(evt); - - if (m_This.m_Assets.m_ID) { - // creation event may come before the client got proof for its asset - verify_test(evt.m_Info.m_ID == m_This.m_Assets.m_ID); - } - verify_test(evt.m_Info.m_Metadata.m_Value == m_This.m_Assets.m_Metadata.m_Value); - verify_test(evt.m_Info.m_Owner == m_This.m_Assets.m_Owner); - - if (proto::Event::Flags::Add & evt.m_Flags) - { - verify_test(!m_This.m_Assets.m_EvtCreated); - m_This.m_Assets.m_EvtCreated = true; - } - - if (evt.m_EmissionChange) - m_This.m_Assets.m_EvtEmitted = true; - } - + } + + void OnEventType(proto::Event::AssetCtl& evt) override + { + OnEventBase(evt); + + if (m_This.m_Assets.m_ID) { + // creation event may come before the client got proof for its asset + verify_test(evt.m_Info.m_ID == m_This.m_Assets.m_ID); + } + verify_test(evt.m_Info.m_Metadata.m_Value == m_This.m_Assets.m_Metadata.m_Value); + verify_test(evt.m_Info.m_Owner == m_This.m_Assets.m_Owner); + + if (proto::Event::Flags::Add & evt.m_Flags) + { + verify_test(!m_This.m_Assets.m_EvtCreated); + m_This.m_Assets.m_EvtCreated = true; + } + + if (evt.m_EmissionChange) + m_This.m_Assets.m_EvtEmitted = true; + } + } p(*this); uint32_t nCount = p.Proceed(msg.m_Events); @@ -3632,13 +3632,7 @@ namespace beam node.m_Keys.m_Accounts.m_vAdd.push_back(cl.m_Wallet2.m_pKdf); - ByteBuffer bufParser; - bvm2::Compile(bufParser, "Explorer/Parser.wasm", bvm2::Processor::Kind::Manager); - - node.m_Cfg.m_ProcessorParams.m_RichInfoFlags = - NodeProcessor::StartParams::RichInfo::On | - NodeProcessor::StartParams::RichInfo::UpdShader; - node.m_Cfg.m_ProcessorParams.m_RichParser = bufParser; + node.m_Cfg.m_ProcessorParams.m_RichInfoFlags = NodeProcessor::StartParams::RichInfo::On; node.Initialize(); @@ -3647,9 +3641,9 @@ namespace beam struct BridgeClient :public EventsExtractorForeign { - void OnEvent(Event::Base&&) override - { - } + void OnEvent(Event::Base&&) override + { + } } bc; @@ -3681,8 +3675,8 @@ namespace beam { MyClient* m_pOtherClient; - void OnConnectedSecure() override - { + void OnConnectedSecure() override + { SendLogin(); } @@ -3739,26 +3733,26 @@ namespace beam bc.Stop(); // stop it manually (rather than wait for stop in its d'tor) // we'll test various things, including manual rollback with forbidden state. As a result, the connected FlyClient may observe a decrease in tip chainwork - struct TxoRecover - :public NodeProcessor::ITxoRecover - { - uint32_t m_Recovered = 0; - + struct TxoRecover + :public NodeProcessor::ITxoRecover + { + uint32_t m_Recovered = 0; + bool OnTxo(const NodeDB::WalkerTxo&, Height hCreate, Output&, const CoinID&, const Output::User&) override { m_Recovered++; return true; } - }; - - TxoRecover wlk; - wlk.m_pKey = node.m_Keys.m_pOwner.get(); - node2.get_Processor().EnumTxos(wlk); + }; + + TxoRecover wlk; + wlk.m_pKey = node.m_Keys.m_pOwner.get(); + node2.get_Processor().EnumTxos(wlk); verify_test(wlk.m_Recovered); wlk.m_Recovered = 0; - wlk.m_pKey = node.get_Processor().m_vAccounts[1].m_pOwner.get(); - node2.get_Processor().EnumTxos(wlk); + wlk.m_pKey = node.get_Processor().m_vAccounts[1].m_pOwner.get(); + node2.get_Processor().EnumTxos(wlk); verify_test(wlk.m_Recovered); // Test recovery info. Check if shielded in/outs and assets can re recognized @@ -3776,35 +3770,35 @@ namespace beam typedef std::set PkSet; PkSet m_SpendKeys; - bool OnUtxoRecognized(Height, const Output&, CoinID& cid, const Output::User&) override - { - m_Utxos++; - if (cid.m_AssetID) - m_UtxosCA++; - return true; - } - - bool OnShieldedOutRecognized(const ShieldedTxo::DescriptionOutp& dout, const ShieldedTxo::DataParams& pars, Key::Index) override - { - verify_test(m_SpendKeys.end() == m_SpendKeys.find(pars.m_Ticket.m_SpendPk)); - m_SpendKeys.insert(pars.m_Ticket.m_SpendPk); - m_ShieldedOuts++; - return true; - } - - bool OnShieldedIn(const ShieldedTxo::DescriptionInp& din) override - { - if (m_SpendKeys.end() != m_SpendKeys.find(din.m_SpendPk)) - m_ShieldedIns++; - return true; - } - - bool OnAssetRecognized(Asset::Full&) override - { - m_Assets++; - return true; - } - + bool OnUtxoRecognized(Height, const Output&, CoinID& cid, const Output::User&) override + { + m_Utxos++; + if (cid.m_AssetID) + m_UtxosCA++; + return true; + } + + bool OnShieldedOutRecognized(const ShieldedTxo::DescriptionOutp& dout, const ShieldedTxo::DataParams& pars, Key::Index) override + { + verify_test(m_SpendKeys.end() == m_SpendKeys.find(pars.m_Ticket.m_SpendPk)); + m_SpendKeys.insert(pars.m_Ticket.m_SpendPk); + m_ShieldedOuts++; + return true; + } + + bool OnShieldedIn(const ShieldedTxo::DescriptionInp& din) override + { + if (m_SpendKeys.end() != m_SpendKeys.find(din.m_SpendPk)) + m_ShieldedIns++; + return true; + } + + bool OnAssetRecognized(Asset::Full&) override + { + m_Assets++; + return true; + } + }; MyParser p; @@ -4167,10 +4161,10 @@ namespace beam { Waiter m_W; - void OnComplete(proto::FlyClient::Request&) override - { - m_W.StopSafe(true); - } + void OnComplete(proto::FlyClient::Request&) override + { + m_W.StopSafe(true); + } }; MyHandler h; @@ -4209,12 +4203,12 @@ namespace beam } } - void get_Kdf(Key::IKdf::Ptr& pOut) override { - pOut = m_pKdf; - } - void get_OwnerKdf(Key::IPKdf::Ptr& pOut) override { - pOut = m_pKdf; - } + void get_Kdf(Key::IKdf::Ptr& pOut) override { + pOut = m_pKdf; + } + void get_OwnerKdf(Key::IPKdf::Ptr& pOut) override { + pOut = m_pKdf; + } }; @@ -4262,73 +4256,73 @@ namespace beam std::list m_lstCoins; std::vector m_vKrnIds; - void OnDone(const std::exception* pExc) override - { - m_Done = true; - m_Err = !!pExc; - - if (m_pW) - m_pW->StopSafe(!m_Err); - } - - void RunSync0(uint32_t iMethod) - { - m_Done = false; - m_Err = false; - - StartRun(iMethod); - } - - void RunSync1() - { - if (m_Done) - return; - - { - Waiter wt; - m_pW = &wt; - wt.Wait(); - m_pW = nullptr; - } - - if (!m_Done) - // propagate it - io::Reactor::get_Current().stop(); - } - - void RunSync(uint32_t iMethod) - { - RunSync0(iMethod); - RunSync1(); - } - - Transaction::Ptr BuildTx() - { + void OnDone(const std::exception* pExc) override + { + m_Done = true; + m_Err = !!pExc; + + if (m_pW) + m_pW->StopSafe(!m_Err); + } + + void RunSync0(uint32_t iMethod) + { + m_Done = false; + m_Err = false; + + StartRun(iMethod); + } + + void RunSync1() + { + if (m_Done) + return; + + { + Waiter wt; + m_pW = &wt; + wt.Wait(); + m_pW = nullptr; + } + + if (!m_Done) + // propagate it + io::Reactor::get_Current().stop(); + } + + void RunSync(uint32_t iMethod) + { + RunSync0(iMethod); + RunSync1(); + } + + Transaction::Ptr BuildTx() + { Height hTx = m_Context.m_Height + 1; auto pTx = std::make_shared(); pTx->m_Offset = Zero; - bvm2::FundsMap fm; - - for (uint32_t i = 0; i < m_InvokeData.m_vec.size(); i++) - { - const auto& cdata = m_InvokeData.m_vec[i]; - - Amount fee; - if (cdata.IsAdvanced()) - fee = cdata.m_Adv.m_Fee; // can't change! - else - fee = cdata.get_FeeMin(hTx); - - cdata.Generate(*pTx, *m_pKdf, hTx, fee); - - auto& krn = *pTx->m_vKernels.back(); - m_vKrnIds.push_back(krn.get_ID()); - - fm += cdata.m_Spend; - fm[0] += fee; - } + bvm2::FundsMap fm; + + for (uint32_t i = 0; i < m_InvokeData.m_vec.size(); i++) + { + const auto& cdata = m_InvokeData.m_vec[i]; + + Amount fee; + if (cdata.IsAdvanced()) + fee = cdata.m_Adv.m_Fee; // can't change! + else + fee = cdata.get_FeeMin(hTx); + + cdata.Generate(*pTx, *m_pKdf, hTx, fee); + + auto& krn = *pTx->m_vKernels.back(); + m_vKrnIds.push_back(krn.get_ID()); + + fm += cdata.m_Spend; + fm[0] += fee; + } ECC::Scalar::Native kOff(pTx->m_Offset); @@ -4375,7 +4369,7 @@ namespace beam pTx->m_Offset = kOff; pTx->Normalize(); return pTx; - } + } void BuildAndSend(proto::FlyClient::INetwork& net) { @@ -4643,7 +4637,7 @@ void TestAll() beam::DeleteFile(beam::g_sz2); } -thread_local const beam::Rules* beam::Rules::s_pInstance = nullptr; +thread_local const beam::Rules* beam::Rules::s_pInstance = nullptr; int main() { diff --git a/utility/cli/options.cpp b/utility/cli/options.cpp index 1ec70ae28d..bf5169fb81 100644 --- a/utility/cli/options.cpp +++ b/utility/cli/options.cpp @@ -118,7 +118,8 @@ namespace beam const char* MANUAL_ROLLBACK = "manual_rollback"; const char* MANUAL_SELECT = "manual_select"; const char* CONTRACT_RICH_INFO = "contract_rich_info"; - const char* CONTRACT_RICH_PARSER = "contract_rich_parser"; + const char* CONTRACT_RICH_PARSER_FOLDER = "contract_rich_parser_folder"; + const char* CONTRACT_RICH_PARSER_FOLDER_DRYRUN = "contract_rich_parser_folder_dryrun"; const char* CHECKDB = "check_db"; const char* VACUUM = "vacuum"; const char* CRASH = "crash"; @@ -442,7 +443,7 @@ namespace beam (cli::RECOVERY_AUTO_PATH, po::value(), "path and file prefix for recovery auto-generation") (cli::RECOVERY_AUTO_PERIOD, po::value()->default_value(30), "period (in blocks) for recovery auto-generation") (cli::CONTRACT_RICH_INFO, po::value(), "Set to save rich contract invocation info") - (cli::CONTRACT_RICH_PARSER, po::value(), "Optional shader to parse contract invocation info") + (cli::CONTRACT_RICH_PARSER_FOLDER, po::value(), "Optional folder of per-contract parser modules (*.wasm)") (cli::BRIDGE_NETWORK_L1, po::value(), "Bridge L1 network") (cli::BRIDGE_CID, po::value(), "Bridge L1 Contract ID") diff --git a/utility/cli/options.h b/utility/cli/options.h index 963e393d0d..dac840a6bb 100644 --- a/utility/cli/options.h +++ b/utility/cli/options.h @@ -84,7 +84,8 @@ namespace beam extern const char* MANUAL_ROLLBACK; extern const char* MANUAL_SELECT; extern const char* CONTRACT_RICH_INFO; - extern const char* CONTRACT_RICH_PARSER; + extern const char* CONTRACT_RICH_PARSER_FOLDER; + extern const char* CONTRACT_RICH_PARSER_FOLDER_DRYRUN; extern const char* CHECKDB; extern const char* VACUUM; extern const char* CRASH;