/* XMRig - Hush/DragonX HAC Support * Copyright (c) 2024 XMRig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. */ #ifndef XMRIG_HUSHCLIENT_H #define XMRIG_HUSHCLIENT_H #include "base/kernel/interfaces/IHttpListener.h" #include "base/kernel/interfaces/ITimerListener.h" #include "base/net/stratum/BaseClient.h" #include "base/net/stratum/SubmitResult.h" #include #include #include namespace xmrig { class Timer; /** * Client for Hush Asset Chains (HAC) that use RandomX PoW. * Handles BIP22-style getblocktemplate RPC format used by hushd/dragonxd. */ class HushClient : public BaseClient, public ITimerListener, public IHttpListener { public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(HushClient) HushClient(int id, IClientListener *listener); ~HushClient() override; protected: // BaseClient interface bool disconnect() override; bool isTLS() const override; int64_t submit(const JobResult &result) override; void connect() override; void connect(const Pool &pool) override; void setPool(const Pool &pool) override; void deleteLater() override; // IHttpListener void onHttpData(const HttpData &data) override; // ITimerListener void onTimer(const Timer *timer) override; inline bool hasExtension(Extension) const noexcept override { return false; } inline const char *mode() const override { return "hush-daemon"; } inline const char *tlsFingerprint() const override { return m_tlsFingerprint; } inline const char *tlsVersion() const override { return m_tlsVersion; } inline int64_t send(const rapidjson::Value &, Callback) override { return -1; } inline int64_t send(const rapidjson::Value &) override { return -1; } inline void tick(uint64_t) override {} private: // RPC methods int64_t getBlockTemplate(); int64_t getBlockHash(uint64_t height); int64_t submitBlock(const std::string &blockHex); int64_t rpcSend(const rapidjson::Document &doc); // Job handling bool parseBlockTemplate(const rapidjson::Value &result); bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); void retry(); void setState(SocketState state); // RandomX key management uint64_t getKeyHeight(uint64_t height) const; // Block serialization std::vector serializeBlock(uint32_t nonce, uint64_t extraNonce) const; std::vector serializeHeader(const uint8_t* nonce32, const uint8_t* solution) const; std::string serializeBlockHex(const uint8_t* nonce32, const uint8_t* solution) const; // PoW verification (SHA256D of header with solution) bool checkPow(const uint8_t* nonce32, const uint8_t* solution) const; static void sha256d(const uint8_t* data, size_t len, uint8_t* out); // Target/difficulty conversion uint64_t targetToDiff(const char *target) const; // Constants for RandomX key derivation static constexpr int RANDOMX_INTERVAL = 1024; static constexpr int RANDOMX_LAG = 64; // Block template data int32_t m_version = 4; uint64_t m_height = 0; uint64_t m_curtime = 0; String m_prevHash; String m_merkleRoot; // coinbasetxn.hash String m_saplingRoot; // finalsaplingroothash String m_bits; String m_target; std::vector m_targetBytes; // Network target as 32 bytes for comparison String m_coinbaseTx; // coinbasetxn.data std::vector m_transactions; // RandomX key tracking uint64_t m_keyHeight = 0; String m_keyBlockHash; // Job state String m_currentJobId; String m_prevJobHash; uint64_t m_jobSteadyMs = 0; // Cached block blob for submission (full block with header + txs) std::vector m_headerBlob; size_t m_nonceOffset = 0; // Offset of nNonce field in the block blob // Cached binary header fields for block serialization (avoids re-parsing hex each submit) uint8_t m_headerPrevHash[32] = {}; uint8_t m_headerMerkleRoot[32] = {}; uint8_t m_headerSaplingRoot[32] = {}; uint32_t m_headerTime = 0; uint32_t m_headerBits = 0; // Request tracking enum RequestType { REQ_NONE, REQ_TEMPLATE, REQ_KEYHASH, REQ_SUBMIT }; RequestType m_pendingRequest = REQ_NONE; uint64_t m_pendingKeyHeight = 0; Timer *m_timer; std::shared_ptr m_httpListener; std::map m_results; char m_tlsFingerprint[64] = { 0 }; char m_tlsVersion[32] = { 0 }; }; } // namespace xmrig #endif // XMRIG_HUSHCLIENT_H