mirror of
https://github.com/kvazar-network/keva-stratum.git
synced 2025-01-26 23:04:42 +00:00
WIP: Test merged mining.
This commit is contained in:
parent
3aa6f2f8c1
commit
5b1150fd21
@ -16,7 +16,7 @@ include_directories("src/external/easylogging++")
|
|||||||
include_directories("src/external/unbound")
|
include_directories("src/external/unbound")
|
||||||
|
|
||||||
# Build library
|
# Build library
|
||||||
add_library(${CXXLIB} SHARED src/main.cc src/cryptonote_basic/cryptonote_format_utils.cpp
|
add_library(${CXXLIB} SHARED src/cnutil.cpp src/cryptonote_basic/cryptonote_format_utils.cpp
|
||||||
src/crypto/tree-hash.c src/crypto/crypto.cpp src/crypto/crypto-ops.c src/crypto/crypto-ops-data.c
|
src/crypto/tree-hash.c src/crypto/crypto.cpp src/crypto/crypto-ops.c src/crypto/crypto-ops-data.c
|
||||||
src/crypto/hash.c src/crypto/slow-hash.c
|
src/crypto/hash.c src/crypto/slow-hash.c
|
||||||
src/crypto/oaes_lib.c src/crypto/aesb.c
|
src/crypto/oaes_lib.c src/crypto/aesb.c
|
||||||
|
@ -3,6 +3,7 @@ package cnutil
|
|||||||
// #cgo CFLAGS: -std=c11 -D_GNU_SOURCE
|
// #cgo CFLAGS: -std=c11 -D_GNU_SOURCE
|
||||||
// #cgo LDFLAGS: -L${SRCDIR} -Wl,-rpath=\$ORIGIN/cnutil -lcnutil -Wl,-rpath ${SRCDIR} -lstdc++
|
// #cgo LDFLAGS: -L${SRCDIR} -Wl,-rpath=\$ORIGIN/cnutil -lcnutil -Wl,-rpath ${SRCDIR} -lstdc++
|
||||||
// #include <stdlib.h>
|
// #include <stdlib.h>
|
||||||
|
// #include <string.h>
|
||||||
// #include "src/cnutil.h"
|
// #include "src/cnutil.h"
|
||||||
import "C"
|
import "C"
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
@ -18,6 +19,18 @@ func ConvertBlob(blob []byte) []byte {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GenerateAuxBlob(blob []byte) []byte {
|
||||||
|
input := (*C.char)(unsafe.Pointer(&blob[0]))
|
||||||
|
|
||||||
|
size := (C.uint32_t)(len(blob))
|
||||||
|
var out *C.char
|
||||||
|
blobSize := C.convert_blob_to_auxpow_blob(input, size, &out)
|
||||||
|
defer C.free(unsafe.Pointer(out))
|
||||||
|
output := make([]byte, blobSize)
|
||||||
|
C.memcpy(unsafe.Pointer(&output[0]), unsafe.Pointer(out), (C.size_t)(blobSize))
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
func ValidateAddress(addr string) bool {
|
func ValidateAddress(addr string) bool {
|
||||||
input := C.CString(addr)
|
input := C.CString(addr)
|
||||||
defer C.free(unsafe.Pointer(input))
|
defer C.free(unsafe.Pointer(input))
|
||||||
|
@ -1,11 +1,193 @@
|
|||||||
|
#include <cmath>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
|
#include "cryptonote_basic/blobdatatype.h"
|
||||||
|
#include "crypto/crypto.h"
|
||||||
|
#include "crypto/hash.h"
|
||||||
#include "common/base58.h"
|
#include "common/base58.h"
|
||||||
|
#include "serialization/binary_utils.h"
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
||||||
extern "C" uint32_t convert_blob(const char *blob, size_t len, char *out) {
|
#define HASH_SIZE 32
|
||||||
|
|
||||||
|
/*******************************************************************************************/
|
||||||
|
/* Helper functions for merged mining - for merkle tree branch compuation. */
|
||||||
|
|
||||||
|
static size_t tree_depth(size_t count)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t depth = 0;
|
||||||
|
assert(count > 0);
|
||||||
|
for (i = sizeof(size_t) << 2; i > 0; i >>= 1)
|
||||||
|
{
|
||||||
|
if (count >> i > 0)
|
||||||
|
{
|
||||||
|
count >>= i;
|
||||||
|
depth += i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tree_branch(const char (*hashes)[HASH_SIZE], size_t count, char (*branch)[HASH_SIZE])
|
||||||
|
{
|
||||||
|
size_t i, j;
|
||||||
|
size_t cnt = 1;
|
||||||
|
size_t depth = 0;
|
||||||
|
char (*ints)[HASH_SIZE];
|
||||||
|
assert(count > 0);
|
||||||
|
for (i = sizeof(size_t) << 2; i > 0; i >>= 1)
|
||||||
|
{
|
||||||
|
if (cnt << i <= count)
|
||||||
|
{
|
||||||
|
cnt <<= i;
|
||||||
|
depth += i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(cnt == 1ULL << depth);
|
||||||
|
assert(depth == tree_depth(count));
|
||||||
|
ints = reinterpret_cast<char(*)[HASH_SIZE]>(alloca((cnt - 1) * HASH_SIZE));
|
||||||
|
memcpy(ints, hashes + 1, (2 * cnt - count - 1) * HASH_SIZE);
|
||||||
|
for (i = 2 * cnt - count, j = 2 * cnt - count - 1; j < cnt - 1; i += 2, ++j)
|
||||||
|
{
|
||||||
|
crypto::cn_fast_hash(hashes[i], 2 * HASH_SIZE, ints[j]);
|
||||||
|
}
|
||||||
|
assert(i == count);
|
||||||
|
while (depth > 0)
|
||||||
|
{
|
||||||
|
assert(cnt == 1ULL << depth);
|
||||||
|
cnt >>= 1;
|
||||||
|
--depth;
|
||||||
|
memcpy(branch[depth], ints[0], HASH_SIZE);
|
||||||
|
for (i = 1, j = 0; j < cnt - 1; i += 2, ++j)
|
||||||
|
{
|
||||||
|
crypto::cn_fast_hash(ints[i], 2 * HASH_SIZE, ints[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tree_hash_from_branch(const char (*branch)[HASH_SIZE], size_t depth, const char* leaf, const void* path, char* root_hash)
|
||||||
|
{
|
||||||
|
if (depth == 0)
|
||||||
|
{
|
||||||
|
memcpy(root_hash, leaf, HASH_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buffer[2][HASH_SIZE];
|
||||||
|
int from_leaf = 1;
|
||||||
|
char *leaf_path, *branch_path;
|
||||||
|
while (depth > 0)
|
||||||
|
{
|
||||||
|
--depth;
|
||||||
|
if (path && (((const char*) path)[depth >> 3] & (1 << (depth & 7))) != 0)
|
||||||
|
{
|
||||||
|
leaf_path = buffer[1];
|
||||||
|
branch_path = buffer[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
leaf_path = buffer[0];
|
||||||
|
branch_path = buffer[1];
|
||||||
|
}
|
||||||
|
if (from_leaf)
|
||||||
|
{
|
||||||
|
memcpy(leaf_path, leaf, HASH_SIZE);
|
||||||
|
from_leaf = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crypto::cn_fast_hash(buffer, 2 * HASH_SIZE, leaf_path);
|
||||||
|
}
|
||||||
|
memcpy(branch_path, branch[depth], HASH_SIZE);
|
||||||
|
}
|
||||||
|
crypto::cn_fast_hash(buffer, 2 * HASH_SIZE, root_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
class CAuxPow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Cryptnote coinbase tx, which contains the block hash of kevacoin block.
|
||||||
|
cryptonote::transaction miner_tx;
|
||||||
|
|
||||||
|
// Merkle branch is used to establish that miner_tx is part of the
|
||||||
|
// merkel tree whose root is merkle_root.
|
||||||
|
std::vector<crypto::hash> merkle_branch;
|
||||||
|
|
||||||
|
// load
|
||||||
|
template <template <bool> class Archive>
|
||||||
|
bool do_serialize(Archive<false>& ar)
|
||||||
|
{
|
||||||
|
FIELD(miner_tx)
|
||||||
|
FIELD(merkle_branch)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
template <template <bool> class Archive>
|
||||||
|
bool do_serialize(Archive<true>& ar)
|
||||||
|
{
|
||||||
|
FIELD(miner_tx)
|
||||||
|
FIELD(merkle_branch)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CAuxPow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Cryptnote coinbase tx, which contains the block hash of kevacoin block.
|
||||||
|
cryptonote::transaction miner_tx;
|
||||||
|
|
||||||
|
// Merkle branch is used to establish that miner_tx is part of the
|
||||||
|
// merkel tree whose root is merkle_root.
|
||||||
|
std::vector<crypto::hash> merkle_branch;
|
||||||
|
|
||||||
|
// load
|
||||||
|
template <template <bool> class Archive>
|
||||||
|
bool do_serialize(Archive<false>& ar)
|
||||||
|
{
|
||||||
|
FIELD(miner_tx)
|
||||||
|
FIELD(merkle_branch)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
template <template <bool> class Archive>
|
||||||
|
bool do_serialize(Archive<true>& ar)
|
||||||
|
{
|
||||||
|
FIELD(miner_tx)
|
||||||
|
FIELD(merkle_branch)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Merkle branch and the whole miner tx.
|
||||||
|
static blobdata get_block_auxpow_blob(const block& b)
|
||||||
|
{
|
||||||
|
CAuxPow auxPow;
|
||||||
|
auxPow.miner_tx = b.miner_tx;
|
||||||
|
|
||||||
|
std::vector<crypto::hash> transactionHashes;
|
||||||
|
transactionHashes.push_back(cryptonote::get_transaction_hash(b.miner_tx));
|
||||||
|
std::copy(b.tx_hashes.begin(), b.tx_hashes.end(), std::back_inserter(transactionHashes));
|
||||||
|
auxPow.merkle_branch.resize(tree_depth(b.tx_hashes.size() + 1));
|
||||||
|
tree_branch(reinterpret_cast<const char(*)[HASH_SIZE]>(transactionHashes.data()), transactionHashes.size(),
|
||||||
|
reinterpret_cast<char(*)[HASH_SIZE]>(auxPow.merkle_branch.data()));
|
||||||
|
|
||||||
|
return t_serializable_object_to_blob(auxPow);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" uint32_t convert_blob_to_auxpow_blob(const char *blob, uint32_t len, char** out) {
|
||||||
std::string input = std::string(blob, len);
|
std::string input = std::string(blob, len);
|
||||||
std::string output = "";
|
std::string output = "";
|
||||||
|
|
||||||
@ -14,7 +196,22 @@ extern "C" uint32_t convert_blob(const char *blob, size_t len, char *out) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = get_block_hashing_blob(b);
|
output = get_block_auxpow_blob(b);
|
||||||
|
*out = (char*)malloc(output.length());
|
||||||
|
output.copy(*out, output.length(), 0);
|
||||||
|
return output.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" uint32_t convert_blob(const char *blob, uint32_t len, char *out) {
|
||||||
|
std::string input = std::string(blob, len);
|
||||||
|
blobdata output = "";
|
||||||
|
|
||||||
|
block b = AUTO_VAL_INIT(b);
|
||||||
|
if (!cryptonote::parse_and_validate_block_from_blob(input, b)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = cryptonote::get_block_hashing_blob(b);
|
||||||
output.copy(out, output.length(), 0);
|
output.copy(out, output.length(), 0);
|
||||||
return output.length();
|
return output.length();
|
||||||
}
|
}
|
||||||
@ -25,3 +222,13 @@ extern "C" bool validate_address(const char *addr, size_t len) {
|
|||||||
uint64_t prefix;
|
uint64_t prefix;
|
||||||
return tools::base58::decode_addr(addr, prefix, output);
|
return tools::base58::decode_addr(addr, prefix, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void cryptonight_hash(const char* input, char* output, uint32_t len) {
|
||||||
|
const int variant = input[0] >= 7 ? input[0] - 6 : 0;
|
||||||
|
crypto::cn_slow_hash(input, len, output, variant, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void cryptonight_fast_hash(const char* input, char* output, uint32_t len) {
|
||||||
|
crypto::cn_fast_hash(input, len, output);
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t convert_blob(const char *blob, uint32_t len, char *out);
|
uint32_t convert_blob(const char *blob, uint32_t len, char *out);
|
||||||
|
uint32_t convert_blob_to_auxpow_blob(const char *blob, uint32_t len, char** out);
|
||||||
bool validate_address(const char *addr, uint32_t len);
|
bool validate_address(const char *addr, uint32_t len);
|
||||||
|
|
||||||
void cryptonight_hash(const char* input, char* output, uint32_t len);
|
void cryptonight_hash(const char* input, char* output, uint32_t len);
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
#include <cmath>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "cryptonote_basic/cryptonote_basic.h"
|
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
|
||||||
#include "cryptonote_basic/blobdatatype.h"
|
|
||||||
#include "crypto/crypto.h"
|
|
||||||
#include "crypto/hash.h"
|
|
||||||
#include "common/base58.h"
|
|
||||||
#include "serialization/binary_utils.h"
|
|
||||||
|
|
||||||
using namespace cryptonote;
|
|
||||||
|
|
||||||
extern "C" uint32_t convert_blob(const char *blob, size_t len, char *out) {
|
|
||||||
std::string input = std::string(blob, len);
|
|
||||||
blobdata output = "";
|
|
||||||
|
|
||||||
block b = AUTO_VAL_INIT(b);
|
|
||||||
if (!cryptonote::parse_and_validate_block_from_blob(input, b)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
output = cryptonote::get_block_hashing_blob(b);
|
|
||||||
output.copy(out, output.length(), 0);
|
|
||||||
return output.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" bool validate_address(const char *addr, size_t len) {
|
|
||||||
std::string input = std::string(addr, len);
|
|
||||||
std::string output = "";
|
|
||||||
uint64_t prefix;
|
|
||||||
return tools::base58::decode_addr(addr, prefix, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void cryptonight_hash(const char* input, char* output, uint32_t len) {
|
|
||||||
const int variant = input[0] >= 7 ? input[0] - 6 : 0;
|
|
||||||
crypto::cn_slow_hash(input, len, output, variant, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void cryptonight_fast_hash(const char* input, char* output, uint32_t len) {
|
|
||||||
crypto::cn_fast_hash(input, len, output);
|
|
||||||
}
|
|
@ -94,8 +94,8 @@ func (r *RPCClient) GetInfo() (*GetInfoReply, error) {
|
|||||||
return reply, err
|
return reply, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RPCClient) SubmitBlock(hash string) (*JSONRpcResp, error) {
|
func (r *RPCClient) SubmitBlock(hash string, auxBlock string) (*JSONRpcResp, error) {
|
||||||
return r.doPost(r.Url.String(), "submitblock", []string{hash})
|
return r.doPost(r.Url.String(), "submitblock", []string{hash, auxBlock})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RPCClient) doPost(url, method string, params interface{}) (*JSONRpcResp, error) {
|
func (r *RPCClient) doPost(url, method string, params interface{}) (*JSONRpcResp, error) {
|
||||||
|
@ -169,7 +169,9 @@ func (m *Miner) processShare(s *StratumServer, cs *Session, job *Job, t *BlockTe
|
|||||||
block := hashDiff.Cmp(t.difficulty) >= 0
|
block := hashDiff.Cmp(t.difficulty) >= 0
|
||||||
|
|
||||||
if block {
|
if block {
|
||||||
_, err := r.SubmitBlock(hex.EncodeToString(shareBuff))
|
// Testing, force AuxPow
|
||||||
|
auxBuf := cnutil.GenerateAuxBlob(shareBuff)
|
||||||
|
_, err := r.SubmitBlock(hex.EncodeToString(shareBuff), hex.EncodeToString(auxBuf))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
atomic.AddInt64(&m.rejects, 1)
|
atomic.AddInt64(&m.rejects, 1)
|
||||||
atomic.AddInt64(&r.Rejects, 1)
|
atomic.AddInt64(&r.Rejects, 1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user