Browse Source

WIP: implemented submitblock.

cn_merge
Jianping Wu 6 years ago
parent
commit
57ab5c7255
  1. 20
      src/primitives/block.cpp
  2. 110
      src/rpc/mining.cpp

20
src/primitives/block.cpp

@ -3,7 +3,9 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <arith_uint256.h>
#include <primitives/block.h> #include <primitives/block.h>
#include <streams.h>
#include <hash.h> #include <hash.h>
#include <tinyformat.h> #include <tinyformat.h>
@ -20,9 +22,27 @@ uint256 CBlockHeader::GetHash() const
uint256 CBlockHeader::GetPoWHash() const uint256 CBlockHeader::GetPoWHash() const
{ {
uint256 thash; uint256 thash;
if (hashPrevBlock.IsNull()) {
// Genesis block
cn_slow_hash(BEGIN(nVersion), 80, BEGIN(thash), 2, 0, 0); cn_slow_hash(BEGIN(nVersion), 80, BEGIN(thash), 2, 0, 0);
return thash; return thash;
} }
arith_uint256 blockHash = UintToArith256(GetHash());
arith_uint256 expectedHash = UintToArith256(cnHeader.prev_id);
// blockHash should be the same as expectedHash. If so, after the
// following XOR operatiosn, the value of expectedHash is not changed.
blockHash ^= expectedHash;
expectedHash ^= blockHash;
CryptoNoteHeader header = cnHeader;
// Cryptonote prev_id is used to store kevacoin block hash.
header.prev_id = ArithToUint256(expectedHash);
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << header;
std::string blob = stream.str();
cn_slow_hash(blob.data(), blob.size(), BEGIN(thash), 2, 0, 0);
return thash;
}
std::string CBlock::ToString() const std::string CBlock::ToString() const
{ {

110
src/rpc/mining.cpp

@ -971,6 +971,7 @@ protected:
} }
}; };
#if 0
UniValue submitblock(const JSONRPCRequest& request) UniValue submitblock(const JSONRPCRequest& request)
{ {
// We allow 2 arguments for compliance with BIP22. Argument 2 is ignored. // We allow 2 arguments for compliance with BIP22. Argument 2 is ignored.
@ -1041,6 +1042,115 @@ UniValue submitblock(const JSONRPCRequest& request)
} }
return BIP22ValidationResult(sc.state); return BIP22ValidationResult(sc.state);
} }
#endif
static uint256 CryptoHashToUint256(const crypto::hash& hash)
{
std::vector<unsigned char> prev_id((unsigned char*)(&hash), (unsigned char*)&(hash) + sizeof(crypto::hash));
return uint256(prev_id);
}
// Cryptonote RPC call, only one parameter allowed.
UniValue submitblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
"submitblock \"hexdata\"\n"
"\nAttempts to submit new block to network.\n"
"See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
"\nArguments\n"
"1. \"hexdata\" (string, required) the hex-encoded block data to submit\n"
"2. \"dummy\" (optional) dummy value, for compatibility with BIP22. This value is ignored.\n"
"\nResult:\n"
"\nExamples:\n"
+ HelpExampleCli("submitblock", "\"mydata\"")
+ HelpExampleRpc("submitblock", "\"mydata\"")
);
}
cryptonote::blobdata blockblob;
if(!epee::string_tools::parse_hexstr_to_binbuff(request.params[0].get_str(), blockblob))
{
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Wrong block blob");
}
cryptonote::block cnblock = AUTO_VAL_INIT(cnblock);
if(!cryptonote::parse_and_validate_block_from_blob(blockblob, cnblock))
{
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Wrong block blob");
}
cryptonote::tx_extra_keva_block keva_block_blob;
if (!cryptonote::get_keva_block_from_extra(cnblock.miner_tx.extra, keva_block_blob)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Could not get Kevacoin block");
}
std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>();
CBlock& block = *blockptr;
if (!DecodeHexBlk(block, keva_block_blob.keva_block)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
}
if (block.vtx.empty() || !block.vtx[0]->IsCoinBase()) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block does not start with a coinbase");
}
block.cnHeader.major_version = cnblock.major_version;
block.cnHeader.minor_version = cnblock.minor_version;
block.cnHeader.prev_id = CryptoHashToUint256(cnblock.prev_id);
block.cnHeader.nonce = cnblock.nonce;
crypto::hash tree_root_hash = get_tx_tree_hash(cnblock);
block.cnHeader.merkle_root = CryptoHashToUint256(tree_root_hash);
uint256 hash = block.GetHash();
// Cryptonote prev_id is used to store the block hash of kevacoin.
if (hash != block.cnHeader.prev_id) {
throw JSONRPCError(RPC_VERIFY_ERROR, "Kevacoin block hash does not match cryptnote hash");
}
// TODO: fix the return message.
bool fBlockPresent = false;
{
LOCK(cs_main);
BlockMap::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end()) {
CBlockIndex *pindex = mi->second;
if (pindex->IsValid(BLOCK_VALID_SCRIPTS)) {
return "duplicate";
}
if (pindex->nStatus & BLOCK_FAILED_MASK) {
return "duplicate-invalid";
}
// Otherwise, we might only have the header - process the block before returning
fBlockPresent = true;
}
}
{
LOCK(cs_main);
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi != mapBlockIndex.end()) {
UpdateUncommittedBlockStructures(block, mi->second, Params().GetConsensus());
}
}
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
bool fAccepted = ProcessNewBlock(Params(), blockptr, true, nullptr);
UnregisterValidationInterface(&sc);
if (fBlockPresent) {
if (fAccepted && !sc.found) {
return "duplicate-inconclusive";
}
return "duplicate";
}
if (!sc.found) {
return "inconclusive";
}
return BIP22ValidationResult(sc.state);
}
UniValue estimatefee(const JSONRPCRequest& request) UniValue estimatefee(const JSONRPCRequest& request)
{ {

Loading…
Cancel
Save