mirror of
https://github.com/xmrig/xmrig.git
synced 2024-12-23 03:59:41 +00:00
Cryptonote tools WIP
This commit is contained in:
parent
0414511de0
commit
7bfb801ce2
12 changed files with 644 additions and 73 deletions
|
@ -11,7 +11,7 @@ option(WITH_ARGON2 "Enable Argon2 algorithms family" ON)
|
||||||
option(WITH_ASTROBWT "Enable AstroBWT algorithms family" ON)
|
option(WITH_ASTROBWT "Enable AstroBWT algorithms family" ON)
|
||||||
option(WITH_KAWPOW "Enable KawPow algorithms family" ON)
|
option(WITH_KAWPOW "Enable KawPow algorithms family" ON)
|
||||||
option(WITH_HTTP "Enable HTTP protocol support (client/server)" ON)
|
option(WITH_HTTP "Enable HTTP protocol support (client/server)" ON)
|
||||||
option(WITH_DEBUG_LOG "Enable debug log output" OFF)
|
option(WITH_DEBUG_LOG "Enable debug log output" ON)
|
||||||
option(WITH_TLS "Enable OpenSSL support" ON)
|
option(WITH_TLS "Enable OpenSSL support" ON)
|
||||||
option(WITH_ASM "Enable ASM PoW implementations" ON)
|
option(WITH_ASM "Enable ASM PoW implementations" ON)
|
||||||
option(WITH_MSR "Enable MSR mod & 1st-gen Ryzen fix" ON)
|
option(WITH_MSR "Enable MSR mod & 1st-gen Ryzen fix" ON)
|
||||||
|
@ -82,6 +82,7 @@ set(HEADERS_CRYPTO
|
||||||
src/crypto/cn/hash.h
|
src/crypto/cn/hash.h
|
||||||
src/crypto/cn/skein_port.h
|
src/crypto/cn/skein_port.h
|
||||||
src/crypto/cn/soft_aes.h
|
src/crypto/cn/soft_aes.h
|
||||||
|
src/crypto/cn/umul128.h
|
||||||
src/crypto/common/HugePagesInfo.h
|
src/crypto/common/HugePagesInfo.h
|
||||||
src/crypto/common/MemoryPool.h
|
src/crypto/common/MemoryPool.h
|
||||||
src/crypto/common/Nonce.h
|
src/crypto/common/Nonce.h
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
add_definitions(/DXMRIG_64_BIT)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(XMRIG_OS_WIN ON)
|
set(XMRIG_OS_WIN ON)
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
|
|
|
@ -76,6 +76,9 @@ set(HEADERS_BASE
|
||||||
src/base/tools/Handle.h
|
src/base/tools/Handle.h
|
||||||
src/base/tools/String.h
|
src/base/tools/String.h
|
||||||
src/base/tools/Timer.h
|
src/base/tools/Timer.h
|
||||||
|
src/base/tools/cryptonote/BlobReader.h
|
||||||
|
src/base/tools/cryptonote/BlockTemplate.h
|
||||||
|
src/base/tools/cryptonote/WalletAddress.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES_BASE
|
set(SOURCES_BASE
|
||||||
|
@ -126,6 +129,8 @@ set(SOURCES_BASE
|
||||||
src/base/tools/Cvt.cpp
|
src/base/tools/Cvt.cpp
|
||||||
src/base/tools/String.cpp
|
src/base/tools/String.cpp
|
||||||
src/base/tools/Timer.cpp
|
src/base/tools/Timer.cpp
|
||||||
|
src/base/tools/cryptonote/BlockTemplate.cpp
|
||||||
|
src/base/tools/cryptonote/WalletAddress.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
101
src/base/tools/cryptonote/BlobReader.h
Normal file
101
src/base/tools/cryptonote/BlobReader.h
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2014-2021 The Monero Project
|
||||||
|
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XMRIG_BLOBREADER_H
|
||||||
|
#define XMRIG_BLOBREADER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
class CBlobReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline CBlobReader(const void* data, size_t size)
|
||||||
|
: m_data(reinterpret_cast<const uint8_t*>(data))
|
||||||
|
, m_size(size)
|
||||||
|
, m_index(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline bool operator()(uint8_t& data) { return getByte(data); }
|
||||||
|
inline bool operator()(uint64_t& data) { return getVarint(data); }
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
inline bool operator()(uint8_t(&data)[N])
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
if (!getByte(data[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void readItems(T& data, size_t count)
|
||||||
|
{
|
||||||
|
data.resize(count);
|
||||||
|
for (size_t i = 0; i < count; ++i)
|
||||||
|
operator()(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t index() const { return m_index; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool getByte(uint8_t& data)
|
||||||
|
{
|
||||||
|
if (m_index >= m_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = m_data[m_index++];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool getVarint(uint64_t& data)
|
||||||
|
{
|
||||||
|
uint64_t result = 0;
|
||||||
|
uint8_t t;
|
||||||
|
int shift = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!getByte(t)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result |= static_cast<uint64_t>(t & 0x7F) << shift;
|
||||||
|
shift += 7;
|
||||||
|
} while (t & 0x80);
|
||||||
|
|
||||||
|
data = result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* m_data;
|
||||||
|
size_t m_size;
|
||||||
|
size_t m_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_BLOBREADER_H */
|
215
src/base/tools/cryptonote/BlockTemplate.cpp
Normal file
215
src/base/tools/cryptonote/BlockTemplate.cpp
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2014-2021 The Monero Project
|
||||||
|
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/crypto/keccak.h"
|
||||||
|
#include "base/tools/Cvt.h"
|
||||||
|
#include "base/tools/cryptonote/BlobReader.h"
|
||||||
|
#include "base/tools/cryptonote/BlockTemplate.h"
|
||||||
|
|
||||||
|
|
||||||
|
#pragma optimize("", off)
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
bool CBlockTemplate::Init(const String& blockTemplate)
|
||||||
|
{
|
||||||
|
raw_blob = Cvt::fromHex(blockTemplate);
|
||||||
|
|
||||||
|
CBlobReader ar(raw_blob.data(), raw_blob.size());
|
||||||
|
|
||||||
|
// Block header
|
||||||
|
ar(major_version);
|
||||||
|
ar(minor_version);
|
||||||
|
ar(timestamp);
|
||||||
|
ar(prev_id);
|
||||||
|
ar(nonce);
|
||||||
|
|
||||||
|
// Miner transaction begin
|
||||||
|
// Prefix begin
|
||||||
|
miner_tx_prefix_begin_index = ar.index();
|
||||||
|
|
||||||
|
ar(tx_version);
|
||||||
|
ar(unlock_time);
|
||||||
|
ar(num_inputs);
|
||||||
|
|
||||||
|
// must be 1 input
|
||||||
|
if (num_inputs != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ar(input_type);
|
||||||
|
|
||||||
|
// input type must be txin_gen (0xFF)
|
||||||
|
if (input_type != 0xFF)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ar(height);
|
||||||
|
|
||||||
|
ar(num_outputs);
|
||||||
|
|
||||||
|
// must be 1 output
|
||||||
|
if (num_outputs != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ar(amount);
|
||||||
|
ar(output_type);
|
||||||
|
|
||||||
|
// output type must be txout_to_key (2)
|
||||||
|
if (output_type != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eph_public_key_index = ar.index();
|
||||||
|
|
||||||
|
ar(eph_public_key);
|
||||||
|
ar(extra_size);
|
||||||
|
|
||||||
|
tx_pubkey_index = ar.index() + 1;
|
||||||
|
|
||||||
|
ar.readItems(extra, extra_size);
|
||||||
|
|
||||||
|
// First thing in tx_extra must be TX_EXTRA_TAG_PUBKEY
|
||||||
|
if (extra[0] != 0x01)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
miner_tx_prefix_end_index = ar.index();
|
||||||
|
// Prefix end
|
||||||
|
|
||||||
|
// RCT signatures (empty in miner transaction)
|
||||||
|
ar(vin_rct_type);
|
||||||
|
|
||||||
|
// must be RCTTypeNull (0)
|
||||||
|
if (vin_rct_type != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const size_t miner_tx_end = ar.index();
|
||||||
|
// Miner transaction end
|
||||||
|
|
||||||
|
// Miner transaction must have exactly 1 byte with value 0 after the prefix
|
||||||
|
if ((miner_tx_end != miner_tx_prefix_end_index + 1) || (raw_blob[miner_tx_prefix_end_index] != 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Other transaction hashes
|
||||||
|
ar(num_hashes);
|
||||||
|
|
||||||
|
hashes.resize((num_hashes + 1) * HASH_SIZE);
|
||||||
|
CalculateMinerTxHash(hashes.data());
|
||||||
|
|
||||||
|
for (uint64_t i = 1; i <= num_hashes; ++i) {
|
||||||
|
uint8_t h[HASH_SIZE];
|
||||||
|
ar(h);
|
||||||
|
memcpy(hashes.data() + i * HASH_SIZE, h, HASH_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CalculateMerkleTreeHash(hashes.data(), num_hashes + 1, root_hash);
|
||||||
|
CalculateHashingBlob();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CBlockTemplate::CalculateMinerTxHash(uint8_t* hash)
|
||||||
|
{
|
||||||
|
uint8_t hashes[HASH_SIZE * 3];
|
||||||
|
uint8_t md[200];
|
||||||
|
|
||||||
|
// Calculate 3 partial hashes
|
||||||
|
|
||||||
|
// 1. Prefix
|
||||||
|
keccak(raw_blob.data() + miner_tx_prefix_begin_index, miner_tx_prefix_end_index - miner_tx_prefix_begin_index, md);
|
||||||
|
memcpy(hashes, md, HASH_SIZE);
|
||||||
|
|
||||||
|
// 2. Base RCT, single 0 byte in miner tx
|
||||||
|
static const uint8_t known_second_hash[HASH_SIZE] = {
|
||||||
|
188,54,120,158,122,30,40,20,54,70,66,41,130,143,129,125,102,18,247,180,119,214,101,145,255,150,169,224,100,188,201,138
|
||||||
|
};
|
||||||
|
memcpy(hashes + HASH_SIZE, known_second_hash, HASH_SIZE);
|
||||||
|
|
||||||
|
// 3. Prunable RCT, empty in miner tx
|
||||||
|
memset(hashes + HASH_SIZE * 2, 0, HASH_SIZE);
|
||||||
|
|
||||||
|
// Calculate miner transaction hash
|
||||||
|
keccak(hashes, sizeof(hashes), md);
|
||||||
|
|
||||||
|
memcpy(hash, md, HASH_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void CBlockTemplate::CalculateMerkleTreeHash(const uint8_t* hashes, size_t count, uint8_t* root_hash)
|
||||||
|
{
|
||||||
|
uint8_t md[200];
|
||||||
|
|
||||||
|
if (count == 1) {
|
||||||
|
memcpy(root_hash, hashes, HASH_SIZE);
|
||||||
|
}
|
||||||
|
else if (count == 2) {
|
||||||
|
keccak(hashes, HASH_SIZE * 2, md);
|
||||||
|
memcpy(root_hash, md, HASH_SIZE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
size_t cnt = count;
|
||||||
|
while (cnt & (cnt - 1)) cnt &= cnt - 1;
|
||||||
|
|
||||||
|
Buffer ints(HASH_SIZE);
|
||||||
|
memcpy(ints.data(), hashes, (cnt * 2 - count) * HASH_SIZE);
|
||||||
|
|
||||||
|
for (i = cnt * 2 - count, j = cnt * 2 - count; j < cnt; i += 2, ++j) {
|
||||||
|
keccak(hashes + i * HASH_SIZE, HASH_SIZE * 2, md);
|
||||||
|
memcpy(ints.data() + j * HASH_SIZE, md, HASH_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cnt > 2) {
|
||||||
|
cnt >>= 1;
|
||||||
|
for (i = 0, j = 0; j < cnt; i += 2, ++j) {
|
||||||
|
keccak(ints.data() + i * HASH_SIZE, HASH_SIZE * 2, md);
|
||||||
|
memcpy(ints.data() + j * HASH_SIZE, md, HASH_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keccak(ints.data(), HASH_SIZE * 2, md);
|
||||||
|
memcpy(root_hash, md, HASH_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CBlockTemplate::CalculateHashingBlob()
|
||||||
|
{
|
||||||
|
hashingBlob.clear();
|
||||||
|
hashingBlob.reserve(miner_tx_prefix_begin_index + HASH_SIZE + 3);
|
||||||
|
|
||||||
|
hashingBlob.assign(raw_blob.begin(), raw_blob.begin() + miner_tx_prefix_begin_index);
|
||||||
|
hashingBlob.insert(hashingBlob.end(), root_hash, root_hash + HASH_SIZE);
|
||||||
|
|
||||||
|
uint64_t k = num_hashes + 1;
|
||||||
|
while (k >= 0x80) {
|
||||||
|
hashingBlob.emplace_back((static_cast<uint8_t>(k) & 0x7F) | 0x80);
|
||||||
|
k >>= 7;
|
||||||
|
}
|
||||||
|
hashingBlob.emplace_back(static_cast<uint8_t>(k));
|
||||||
|
|
||||||
|
for (int i = 0; i < hashingBlob.size(); ++i)
|
||||||
|
printf("%02x", hashingBlob[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
86
src/base/tools/cryptonote/BlockTemplate.h
Normal file
86
src/base/tools/cryptonote/BlockTemplate.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2014-2021 The Monero Project
|
||||||
|
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XMRIG_BLOCKTEMPLATE_H
|
||||||
|
#define XMRIG_BLOCKTEMPLATE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/tools/Buffer.h"
|
||||||
|
#include "base/tools/String.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
struct CBlockTemplate
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
HASH_SIZE = 32,
|
||||||
|
KEY_SIZE = 32,
|
||||||
|
NONCE_SIZE = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
Buffer raw_blob;
|
||||||
|
size_t eph_public_key_index;
|
||||||
|
size_t tx_pubkey_index;
|
||||||
|
size_t miner_tx_prefix_begin_index;
|
||||||
|
size_t miner_tx_prefix_end_index;
|
||||||
|
|
||||||
|
// Block header
|
||||||
|
uint8_t major_version;
|
||||||
|
uint8_t minor_version;
|
||||||
|
uint64_t timestamp;
|
||||||
|
uint8_t prev_id[HASH_SIZE];
|
||||||
|
uint8_t nonce[NONCE_SIZE];
|
||||||
|
|
||||||
|
// Miner tx
|
||||||
|
uint64_t tx_version;
|
||||||
|
uint64_t unlock_time;
|
||||||
|
uint64_t num_inputs;
|
||||||
|
uint8_t input_type;
|
||||||
|
uint64_t height;
|
||||||
|
uint64_t num_outputs;
|
||||||
|
uint64_t amount;
|
||||||
|
uint8_t output_type;
|
||||||
|
uint8_t eph_public_key[KEY_SIZE];
|
||||||
|
uint64_t extra_size;
|
||||||
|
Buffer extra;
|
||||||
|
uint8_t vin_rct_type;
|
||||||
|
|
||||||
|
// Transaction hashes
|
||||||
|
uint64_t num_hashes;
|
||||||
|
Buffer hashes;
|
||||||
|
|
||||||
|
uint8_t root_hash[HASH_SIZE];
|
||||||
|
|
||||||
|
Buffer hashingBlob;
|
||||||
|
|
||||||
|
bool Init(const String& blockTemplate);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CalculateMinerTxHash(uint8_t* hash);
|
||||||
|
static void CalculateMerkleTreeHash(const uint8_t* hashes, size_t count, uint8_t* root_hash);
|
||||||
|
void CalculateHashingBlob();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_BLOCKTEMPLATE_H */
|
116
src/base/tools/cryptonote/WalletAddress.cpp
Normal file
116
src/base/tools/cryptonote/WalletAddress.cpp
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2014-2021 The Monero Project
|
||||||
|
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/crypto/keccak.h"
|
||||||
|
#include "base/tools/cryptonote/BlobReader.h"
|
||||||
|
#include "base/tools/cryptonote/WalletAddress.h"
|
||||||
|
#include "base/tools/Buffer.h"
|
||||||
|
#include "crypto/cn/umul128.h"
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
|
||||||
|
#pragma optimize("", off)
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
bool WalletAddress::Decode(const String& address)
|
||||||
|
{
|
||||||
|
static constexpr std::array<int, 9> block_sizes{ 0, 2, 3, 5, 6, 7, 9, 10, 11 };
|
||||||
|
static constexpr char alphabet[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
constexpr size_t alphabet_size = sizeof(alphabet) - 1;
|
||||||
|
|
||||||
|
int8_t reverse_alphabet[256];
|
||||||
|
memset(reverse_alphabet, -1, sizeof(reverse_alphabet));
|
||||||
|
|
||||||
|
for (int i = 0; i < alphabet_size; ++i) {
|
||||||
|
reverse_alphabet[alphabet[i]] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int len = static_cast<int>(address.size());
|
||||||
|
const int num_full_blocks = len / block_sizes.back();
|
||||||
|
const int last_block_size = len % block_sizes.back();
|
||||||
|
|
||||||
|
int last_block_size_index = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < block_sizes.size(); ++i) {
|
||||||
|
if (block_sizes[i] == last_block_size) {
|
||||||
|
last_block_size_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_block_size_index < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer data;
|
||||||
|
data.reserve(static_cast<size_t>(num_full_blocks) * sizeof(uint64_t) + last_block_size_index);
|
||||||
|
|
||||||
|
const char* address_data = address.data();
|
||||||
|
|
||||||
|
for (int i = 0; i <= num_full_blocks; ++i) {
|
||||||
|
uint64_t num = 0;
|
||||||
|
uint64_t order = 1;
|
||||||
|
|
||||||
|
for (int j = ((i < num_full_blocks) ? block_sizes.back() : last_block_size) - 1; j >= 0; --j) {
|
||||||
|
const int digit = reverse_alphabet[address_data[j]];
|
||||||
|
if (digit < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t hi;
|
||||||
|
const uint64_t tmp = num + __umul128(order, static_cast<uint64_t>(digit), &hi);
|
||||||
|
if ((tmp < num) || hi) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
num = tmp;
|
||||||
|
order *= alphabet_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
address_data += block_sizes.back();
|
||||||
|
|
||||||
|
uint8_t* p = reinterpret_cast<uint8_t*>(&num);
|
||||||
|
for (int j = ((i < num_full_blocks) ? sizeof(num) : last_block_size_index) - 1; j >= 0; --j) {
|
||||||
|
data.emplace_back(p[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CBlobReader ar(data.data(), data.size());
|
||||||
|
|
||||||
|
ar(tag);
|
||||||
|
ar(public_spend_key);
|
||||||
|
ar(public_view_key);
|
||||||
|
ar(checksum);
|
||||||
|
|
||||||
|
uint8_t md[200];
|
||||||
|
keccak(data.data(), data.size() - sizeof(checksum), md);
|
||||||
|
|
||||||
|
if (memcmp(checksum, md, sizeof(checksum)) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
44
src/base/tools/cryptonote/WalletAddress.h
Normal file
44
src/base/tools/cryptonote/WalletAddress.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* XMRig
|
||||||
|
* Copyright 2014-2021 The Monero Project
|
||||||
|
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XMRIG_WALLETADDRESS_H
|
||||||
|
#define XMRIG_WALLETADDRESS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "base/tools/String.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace xmrig {
|
||||||
|
|
||||||
|
|
||||||
|
struct WalletAddress
|
||||||
|
{
|
||||||
|
uint64_t tag;
|
||||||
|
uint8_t public_spend_key[32];
|
||||||
|
uint8_t public_view_key[32];
|
||||||
|
uint8_t checksum[4];
|
||||||
|
|
||||||
|
bool Decode(const String& address);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} /* namespace xmrig */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* XMRIG_WALLETADDRESS_H */
|
|
@ -31,6 +31,8 @@
|
||||||
#include "crypto/common/VirtualMemory.h"
|
#include "crypto/common/VirtualMemory.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "crypto/cn/umul128.h"
|
||||||
|
|
||||||
#if defined(XMRIG_ARM)
|
#if defined(XMRIG_ARM)
|
||||||
# include "crypto/cn/CryptoNight_arm.h"
|
# include "crypto/cn/CryptoNight_arm.h"
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -67,41 +67,6 @@ static inline void do_skein_hash(const uint8_t *input, size_t len, uint8_t *outp
|
||||||
void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
|
void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
|
||||||
|
|
||||||
|
|
||||||
#if defined (__arm64__) || defined (__aarch64__)
|
|
||||||
static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
|
||||||
{
|
|
||||||
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
|
|
||||||
*hi = r >> 64;
|
|
||||||
return (uint64_t) r;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
|
||||||
// multiplier = ab = a * 2^32 + b
|
|
||||||
// multiplicand = cd = c * 2^32 + d
|
|
||||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
|
||||||
uint64_t a = multiplier >> 32;
|
|
||||||
uint64_t b = multiplier & 0xFFFFFFFF;
|
|
||||||
uint64_t c = multiplicand >> 32;
|
|
||||||
uint64_t d = multiplicand & 0xFFFFFFFF;
|
|
||||||
|
|
||||||
//uint64_t ac = a * c;
|
|
||||||
uint64_t ad = a * d;
|
|
||||||
//uint64_t bc = b * c;
|
|
||||||
uint64_t bd = b * d;
|
|
||||||
|
|
||||||
uint64_t adbc = ad + (b * c);
|
|
||||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
|
||||||
|
|
||||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
|
||||||
uint64_t product_lo = bd + (adbc << 32);
|
|
||||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
|
||||||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
|
||||||
|
|
||||||
return product_lo;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// This will shift and xor tmp1 into itself as 4 32-bit vals such as
|
// This will shift and xor tmp1 into itself as 4 32-bit vals such as
|
||||||
// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
|
// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1)
|
||||||
static inline __m128i sl_xor(__m128i tmp1)
|
static inline __m128i sl_xor(__m128i tmp1)
|
||||||
|
|
|
@ -75,18 +75,7 @@ static inline void do_skein_hash(const uint8_t *input, size_t len, uint8_t *outp
|
||||||
void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
|
void (* const extra_hashes[4])(const uint8_t *, size_t, uint8_t *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
|
||||||
|
|
||||||
|
|
||||||
#if defined(__x86_64__) || defined(_M_AMD64)
|
#if defined(__i386__) || defined(_M_IX86)
|
||||||
# ifdef __GNUC__
|
|
||||||
static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
|
||||||
{
|
|
||||||
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
|
|
||||||
*hi = r >> 64;
|
|
||||||
return (uint64_t) r;
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
#define __umul128 _umul128
|
|
||||||
# endif
|
|
||||||
#elif defined(__i386__) || defined(_M_IX86)
|
|
||||||
static inline int64_t _mm_cvtsi128_si64(__m128i a)
|
static inline int64_t _mm_cvtsi128_si64(__m128i a)
|
||||||
{
|
{
|
||||||
return ((uint64_t)(uint32_t)_mm_cvtsi128_si32(a) | ((uint64_t)(uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(a, 4)) << 32));
|
return ((uint64_t)(uint32_t)_mm_cvtsi128_si32(a) | ((uint64_t)(uint32_t)_mm_cvtsi128_si32(_mm_srli_si128(a, 4)) << 32));
|
||||||
|
@ -95,31 +84,6 @@ static inline int64_t _mm_cvtsi128_si64(__m128i a)
|
||||||
static inline __m128i _mm_cvtsi64_si128(int64_t a) {
|
static inline __m128i _mm_cvtsi64_si128(int64_t a) {
|
||||||
return _mm_set_epi64x(0, a);
|
return _mm_set_epi64x(0, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
|
||||||
// multiplier = ab = a * 2^32 + b
|
|
||||||
// multiplicand = cd = c * 2^32 + d
|
|
||||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
|
||||||
uint64_t a = multiplier >> 32;
|
|
||||||
uint64_t b = multiplier & 0xFFFFFFFF;
|
|
||||||
uint64_t c = multiplicand >> 32;
|
|
||||||
uint64_t d = multiplicand & 0xFFFFFFFF;
|
|
||||||
|
|
||||||
//uint64_t ac = a * c;
|
|
||||||
uint64_t ad = a * d;
|
|
||||||
//uint64_t bc = b * c;
|
|
||||||
uint64_t bd = b * d;
|
|
||||||
|
|
||||||
uint64_t adbc = ad + (b * c);
|
|
||||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
|
||||||
|
|
||||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
|
||||||
uint64_t product_lo = bd + (adbc << 32);
|
|
||||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
|
||||||
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
|
||||||
|
|
||||||
return product_lo;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
68
src/crypto/cn/umul128.h
Normal file
68
src/crypto/cn/umul128.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Additional permission under GNU GPL version 3 section 7
|
||||||
|
*
|
||||||
|
* If you modify this Program, or any covered work, by linking or combining
|
||||||
|
* it with OpenSSL (or a modified version of that library), containing parts
|
||||||
|
* covered by the terms of OpenSSL License and SSLeay License, the licensors
|
||||||
|
* of this Program grant you additional permission to convey the resulting work.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#ifdef XMRIG_64_BIT
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# include <intrin.h>
|
||||||
|
# pragma intrinsic(_umul128)
|
||||||
|
# define __umul128 _umul128
|
||||||
|
# elif defined __GNUC__
|
||||||
|
static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi)
|
||||||
|
{
|
||||||
|
unsigned __int128 r = (unsigned __int128) a * (unsigned __int128) b;
|
||||||
|
*hi = r >> 64;
|
||||||
|
return (uint64_t) r;
|
||||||
|
}
|
||||||
|
# define __umul128 _umul128
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
|
||||||
|
// multiplier = ab = a * 2^32 + b
|
||||||
|
// multiplicand = cd = c * 2^32 + d
|
||||||
|
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||||
|
uint64_t a = multiplier >> 32;
|
||||||
|
uint64_t b = multiplier & 0xFFFFFFFF;
|
||||||
|
uint64_t c = multiplicand >> 32;
|
||||||
|
uint64_t d = multiplicand & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
//uint64_t ac = a * c;
|
||||||
|
uint64_t ad = a * d;
|
||||||
|
//uint64_t bc = b * c;
|
||||||
|
uint64_t bd = b * d;
|
||||||
|
|
||||||
|
uint64_t adbc = ad + (b * c);
|
||||||
|
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||||
|
|
||||||
|
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||||
|
uint64_t product_lo = bd + (adbc << 32);
|
||||||
|
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||||
|
*product_hi = (a * c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||||
|
|
||||||
|
return product_lo;
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in a new issue