From cfacbe40d6429d55f557100a41d61ba00b342f01 Mon Sep 17 00:00:00 2001 From: cch Date: Wed, 24 Jul 2019 11:46:56 +0800 Subject: [PATCH] fix pow theft --- common/proof.h | 13 +++++++----- script/template/rpc.json | 12 +++++++++-- src/blockmaker.cpp | 1 + src/core.cpp | 4 ++++ src/miner.cpp | 45 ++++++++++++++++++++++++++++++---------- src/mvbase.h | 2 +- src/rpcmod.cpp | 36 +++++++++++++++++++------------- src/service.cpp | 3 ++- src/service.h | 2 +- 9 files changed, 83 insertions(+), 35 deletions(-) diff --git a/common/proof.h b/common/proof.h index 440420cc..689d5545 100644 --- a/common/proof.h +++ b/common/proof.h @@ -8,6 +8,7 @@ #include "uint256.h" #include "key.h" #include +#include "destination.h" class CProofOfSecretShare { @@ -58,17 +59,18 @@ class CProofOfHashWork : public CProofOfSecretShare public: unsigned char nAlgo; unsigned char nBits; + CDestination destMint; uint256 nNonce; protected: virtual void ToStream(walleve::CWalleveODataStream& os) override { CProofOfSecretShare::ToStream(os); - os << nAlgo << nBits << nNonce; + os << nAlgo << nBits << destMint.prefix << destMint.data << nNonce; } virtual void FromStream(walleve::CWalleveIDataStream& is) override { CProofOfSecretShare::FromStream(is); - is >> nAlgo >> nBits >> nNonce; + is >> nAlgo >> nBits >> destMint.prefix >> destMint.data >> nNonce; } }; @@ -77,19 +79,20 @@ class CProofOfHashWorkCompact public: unsigned char nAlgo; unsigned char nBits; + CDestination destMint; uint256 nNonce; public: - enum { PROOFHASHWORK_SIZE = 34 }; + enum { PROOFHASHWORK_SIZE = 67 }; void Save(std::vector& vchProof) { unsigned char *p = &vchProof[vchProof.size() - PROOFHASHWORK_SIZE]; - *p++ = nAlgo; *p++ = nBits; *((uint256*)p) = nNonce; + *p++ = nAlgo; *p++ = nBits; *p++ = destMint.prefix; *((uint256*)p) = destMint.data; p += 32; *((uint256*)p) = nNonce; } void Load(const std::vector& vchProof) { const unsigned char *p = &vchProof[vchProof.size() - PROOFHASHWORK_SIZE]; - nAlgo = *p++; nBits = *p++; nNonce = *((uint256*)p); + nAlgo = *p++; nBits = *p++; destMint.prefix = *p++; destMint.data = *((uint256*)p); p += 32; nNonce = *((uint256*)p); } }; diff --git a/script/template/rpc.json b/script/template/rpc.json index 907d7d89..d9e5fd7a 100644 --- a/script/template/rpc.json +++ b/script/template/rpc.json @@ -2558,6 +2558,14 @@ "request": { "type": "object", "content": { + "spent": { + "type": "string", + "desc": "spent address" + }, + "privkey": { + "type": "string", + "desc": "private key" + }, "prev": { "type": "string", "desc": "prev block hash", @@ -2607,11 +2615,11 @@ }, "example": [ { - "request": "multiverse-cli getwork 7ee748e9a827d476d1b4ddb77dc8f9bad779f7b71593d5c5bf73b535e1cc2446", + "request": "multiverse-cli getwork 1pdr1knaaa4fzr846v89g3q2tzb8pbvbavbbft8xppkky0mqnmsq8gn5y ceae964a1119f110b0cff3614426dd692f8467a95cc2c276e523efc63c5e5031 7ee748e9a827d476d1b4ddb77dc8f9bad779f7b71593d5c5bf73b535e1cc2446", "response": "{\"work\":{\"prevblockhash\":\"f734bb6bc12ab4058532113cfe6a3412d1036eae25f60a97ee1b17effc6e74de\",\"prevblocktime\":1538142032,\"algo\":1,\"bits\":25,\"data\":\"01000100822fae5bde746efcef171bee970af625ae6e03d112346afe3c11328505b42ac16bbb34f74300000000000000000000000000000000000000000000000000000000000000000001190000000000000000000000000000000000000000000000000000000000000000\"}}" }, { - "request": "curl -d '{\"id\":1,\"method\":\"getwork\",\"jsonrpc\":\"2.0\",\"params\":{\"prev\":\"7ee748e9a827d476d1b4ddb77dc8f9bad779f7b71593d5c5bf73b535e1cc2446\"}}' http://127.0.0.1:6812", + "request": "curl -d '{\"id\":1,\"method\":\"getwork\",\"jsonrpc\":\"2.0\",\"params\":{\"spent\":\"1pdr1knaaa4fzr846v89g3q2tzb8pbvbavbbft8xppkky0mqnmsq8gn5y\",\"privkey\":\"ceae964a1119f110b0cff3614426dd692f8467a95cc2c276e523efc63c5e5031\",\"prev\":\"7ee748e9a827d476d1b4ddb77dc8f9bad779f7b71593d5c5bf73b535e1cc2446\"}}' http://127.0.0.1:6812", "response": "{\"id\":1,\"jsonrpc\":\"2.0\",\"result\":{\"work\":{\"prevblockhash\":\"f734bb6bc12ab4058532113cfe6a3412d1036eae25f60a97ee1b17effc6e74de\",\"prevblocktime\":1538142032,\"algo\":1,\"bits\":25,\"data\":\"01000100822fae5bde746efcef171bee970af625ae6e03d112346afe3c11328505b42ac16bbb34f74300000000000000000000000000000000000000000000000000000000000000000001190000000000000000000000000000000000000000000000000000000000000000\"}}}" } ], diff --git a/src/blockmaker.cpp b/src/blockmaker.cpp index 637af126..59cbe01c 100644 --- a/src/blockmaker.cpp +++ b/src/blockmaker.cpp @@ -320,6 +320,7 @@ bool CBlockMaker::CreateProofOfWorkBlock(CBlock& block) CProofOfHashWorkCompact proof; proof.nAlgo = nAlgo; proof.nBits = nBits; + proof.destMint = destSendTo; proof.nNonce = 0; proof.Save(block.vchProof); diff --git a/src/core.cpp b/src/core.cpp index e324f3f5..cf6677cb 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -288,6 +288,10 @@ MvErr CMvCoreProtocol::VerifyProofOfWork(const CBlock& block, const CBlockIndex* { return MV_ERR_BLOCK_PROOF_OF_WORK_INVALID; } + if (proof.destMint != block.txMint.sendTo) + { + return MV_ERR_BLOCK_PROOF_OF_WORK_INVALID; + } uint256 hashTarget = (~uint256(uint64(0)) >> GetProofOfWorkRunTimeBits(nBits,block.GetBlockTime(),pIndexPrev->GetBlockTime())); diff --git a/src/miner.cpp b/src/miner.cpp index f06a303d..2125725c 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -150,21 +150,41 @@ bool CMiner::HandleEvent(CWalleveEventHttpGetRsp& event) else if (spResp->IsSuccessful()) { auto spResult = CastResultPtr(spResp->spResult); - cout << spResp->spResult->Method() << endl; - if (spResult->fResult.IsValid()) + //cout << spResp->spResult->Method() << endl; + + + int nRet = 0; + if (!spResult->fResult.IsValid()) + { + nRet = -1; + cout << "get work fResult invalid." << endl; + } + else if (!spResult->work.IsValid()) + { + nRet = -2; + cout << "get work work invalid." << endl; + } + else if (!spResult->fResult) + { + nRet = -3; + cout << "get work fResult is false." << endl; + } + else + { + cout << "get work success." << endl; + } + + if (nRet != 0) { - if (!spResult->fResult) { - { - boost::unique_lock lock(mutex); + boost::unique_lock lock(mutex); - workCurrent.SetNull(); - nMinerStatus = MINER_HOLD; - } - condMiner.notify_all(); + workCurrent.SetNull(); + nMinerStatus = MINER_HOLD; } + condMiner.notify_all(); } - else if (spResult->work.IsValid()) + else { { boost::unique_lock lock(mutex); @@ -264,7 +284,10 @@ bool CMiner::GetWork() try { // nNonceGetWork += 2; - auto spParam = MakeCGetWorkParamPtr(workCurrent.hashPrev.GetHex()); + auto spParam = MakeCGetWorkParamPtr(); + spParam->strSpent = strAddrSpent; + spParam->strPrivkey = strMintKey; + spParam->strPrev = workCurrent.hashPrev.GetHex(); CRPCReqPtr spReq = MakeCRPCReqPtr(nNonceGetWork, spParam); return SendRequest(nNonceGetWork, spReq->Serialize()); } diff --git a/src/mvbase.h b/src/mvbase.h index f185f748..f56c1ff4 100644 --- a/src/mvbase.h +++ b/src/mvbase.h @@ -281,7 +281,7 @@ class IService : public walleve::IWalleveBase virtual bool SynchronizeWalletTx(const CDestination& destNew) = 0; virtual bool ResynchronizeWalletTx() = 0; /* Mint */ - virtual bool GetWork(std::vector& vchWorkData, uint256& hashPrev, uint32& nPrevTime, int& nAlgo, int& nBits) = 0; + virtual bool GetWork(std::vector& vchWorkData, uint256& hashPrev, uint32& nPrevTime, int& nAlgo, int& nBits, CTemplateMintPtr& templMint) = 0; virtual MvErr SubmitWork(const std::vector& vchWorkData, CTemplateMintPtr& templMint, crypto::CKey& keyMint, uint256& hashBlock) = 0; }; diff --git a/src/rpcmod.cpp b/src/rpcmod.cpp index 62b0917b..c0b42e70 100644 --- a/src/rpcmod.cpp +++ b/src/rpcmod.cpp @@ -2046,37 +2046,45 @@ CRPCResultPtr CRPCModWorker::RPCDecodeTransaction(CRPCParamPtr param) // /* Mint */ CRPCResultPtr CRPCModWorker::RPCGetWork(CRPCParamPtr param) { + //getwork <"spent"> <"privkey"> ("prev") auto spParam = CastParamPtr(param); - //getwork ("prev") - uint256 hashPrev; - if (!pService->GetBlockHash(pCoreProtocol->GetGenesisBlockHash(),-1,hashPrev)) + CMvAddress addrSpent(spParam->strSpent); + uint256 nPriv(spParam->strPrivkey); + if (addrSpent.IsNull() || !addrSpent.IsPubKey()) { - throw CRPCException(RPC_INTERNAL_ERROR, "The primary chain is invalid."); + throw CRPCException(RPC_INVALID_ADDRESS_OR_KEY,"Invalid spent address"); } - - uint256 inPrev; - if (inPrev.SetHex(spParam->strPrev) != spParam->strPrev.size()) + crypto::CKey key; + if (!key.SetSecret(crypto::CCryptoKeyData(nPriv.begin(),nPriv.end()))) { - throw CRPCException(RPC_INTERNAL_ERROR, "Invalid prev."); + throw CRPCException(RPC_INVALID_ADDRESS_OR_KEY,"Invalid private key"); } - - auto spResult = MakeCGetWorkResultPtr(); - if (hashPrev == uint256(spParam->strPrev)) + crypto::CPubKey pubkeySpent; + if (addrSpent.GetPubKey(pubkeySpent) && pubkeySpent == key.GetPubKey()) { - spResult->fResult = true; - return spResult; + throw CRPCException(RPC_INVALID_ADDRESS_OR_KEY,"Invalid spent address or private key"); + } + CTemplateMintPtr ptr = CTemplateMint::CreateTemplatePtr(new CTemplateProof(key.GetPubKey(),static_cast(addrSpent))); + if (ptr == NULL) + { + throw CRPCException(RPC_INVALID_ADDRESS_OR_KEY,"Invalid mint template"); } + auto spResult = MakeCGetWorkResultPtr(); + vector vchWorkData; + uint256 hashPrev; uint32 nPrevTime; int nAlgo,nBits; - if (!pService->GetWork(vchWorkData,hashPrev,nPrevTime,nAlgo,nBits)) + if (!pService->GetWork(vchWorkData,hashPrev,nPrevTime,nAlgo,nBits,ptr)) { spResult->fResult = false; return spResult; } + spResult->fResult = true; + spResult->work.strPrevblockhash = hashPrev.GetHex(); spResult->work.nPrevblocktime = nPrevTime; spResult->work.nAlgo = nAlgo; diff --git a/src/service.cpp b/src/service.cpp index f24caedf..492c617f 100644 --- a/src/service.cpp +++ b/src/service.cpp @@ -536,7 +536,7 @@ bool CService::ResynchronizeWalletTx() return pWallet->ResynchronizeWalletTx(); } -bool CService::GetWork(vector& vchWorkData,uint256& hashPrev,uint32& nPrevTime,int& nAlgo,int& nBits) +bool CService::GetWork(std::vector& vchWorkData, uint256& hashPrev, uint32& nPrevTime, int& nAlgo, int& nBits, CTemplateMintPtr& templMint) { CBlock block; block.nType = CBlock::BLOCK_PRIMARY; @@ -566,6 +566,7 @@ bool CService::GetWork(vector& vchWorkData,uint256& hashPrev,uint proof.nAgreement = 0; proof.nAlgo = nAlgo; proof.nBits = nBits; + proof.destMint = CDestination(templMint->GetTemplateId()); proof.nNonce = 0; proof.Save(block.vchProof); diff --git a/src/service.h b/src/service.h index 266eeedf..2f29c4cf 100644 --- a/src/service.h +++ b/src/service.h @@ -72,7 +72,7 @@ class CService : public IService bool SynchronizeWalletTx(const CDestination& destNew) override; bool ResynchronizeWalletTx() override; /* Mint */ - bool GetWork(std::vector& vchWorkData,uint256& hashPrev,uint32& nPrevTime,int& nAlgo,int& nBits) override; + bool GetWork(std::vector& vchWorkData, uint256& hashPrev, uint32& nPrevTime, int& nAlgo, int& nBits, CTemplateMintPtr& templMint) override; MvErr SubmitWork(const std::vector& vchWorkData,CTemplateMintPtr& templMint,crypto::CKey& keyMint,uint256& hashBlock) override; /* Util */ protected: