mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-27 23:34:20 +00:00
WIP: implemented submitblock.
This commit is contained in:
parent
bbb78c76a0
commit
57ab5c7255
@ -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,7 +22,25 @@ uint256 CBlockHeader::GetHash() const
|
|||||||
uint256 CBlockHeader::GetPoWHash() const
|
uint256 CBlockHeader::GetPoWHash() const
|
||||||
{
|
{
|
||||||
uint256 thash;
|
uint256 thash;
|
||||||
cn_slow_hash(BEGIN(nVersion), 80, BEGIN(thash), 2, 0, 0);
|
if (hashPrevBlock.IsNull()) {
|
||||||
|
// Genesis block
|
||||||
|
cn_slow_hash(BEGIN(nVersion), 80, BEGIN(thash), 2, 0, 0);
|
||||||
|
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;
|
return thash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user