mirror of
https://github.com/SChernykh/p2pool.git
synced 2024-12-22 19:39:22 +00:00
View tags support
See http://github.com/monero-project/monero/pull/8061
This commit is contained in:
parent
7522111bb7
commit
2c70bf8616
13 changed files with 233 additions and 45 deletions
|
@ -689,6 +689,8 @@ int BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<Mine
|
|||
m_poolBlockTemplate->m_outputs.clear();
|
||||
m_poolBlockTemplate->m_outputs.reserve(num_outputs);
|
||||
|
||||
const uint8_t tx_type = m_poolBlockTemplate->get_tx_type();
|
||||
|
||||
uint64_t reward_amounts_weight = 0;
|
||||
for (size_t i = 0; i < num_outputs; ++i) {
|
||||
writeVarint(m_rewards[i], [this, &reward_amounts_weight](uint8_t b)
|
||||
|
@ -696,18 +698,24 @@ int BlockTemplate::create_miner_tx(const MinerData& data, const std::vector<Mine
|
|||
m_minerTx.push_back(b);
|
||||
++reward_amounts_weight;
|
||||
});
|
||||
m_minerTx.push_back(TXOUT_TO_KEY);
|
||||
m_minerTx.push_back(tx_type);
|
||||
|
||||
uint8_t view_tag = 0;
|
||||
|
||||
if (dry_run) {
|
||||
m_minerTx.insert(m_minerTx.end(), HASH_SIZE, 0);
|
||||
}
|
||||
else {
|
||||
hash eph_public_key;
|
||||
if (!shares[i].m_wallet->get_eph_public_key(m_txkeySec, i, eph_public_key)) {
|
||||
if (!shares[i].m_wallet->get_eph_public_key(m_txkeySec, i, eph_public_key, view_tag)) {
|
||||
LOGERR(1, "get_eph_public_key failed at index " << i);
|
||||
}
|
||||
m_minerTx.insert(m_minerTx.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE);
|
||||
m_poolBlockTemplate->m_outputs.emplace_back(m_rewards[i], eph_public_key);
|
||||
m_poolBlockTemplate->m_outputs.emplace_back(m_rewards[i], eph_public_key, tx_type, view_tag);
|
||||
}
|
||||
|
||||
if (tx_type == TXOUT_TO_TAGGED_KEY) {
|
||||
m_minerTx.emplace_back(view_tag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,8 @@
|
|||
namespace p2pool {
|
||||
|
||||
constexpr size_t HASH_SIZE = 32;
|
||||
constexpr uint8_t HARDFORK_SUPPORTED_VERSION = 14;
|
||||
constexpr uint8_t HARDFORK_VIEW_TAGS_VERSION = 15;
|
||||
constexpr uint8_t HARDFORK_SUPPORTED_VERSION = 16;
|
||||
constexpr uint8_t MINER_REWARD_UNLOCK_TIME = 60;
|
||||
constexpr uint8_t NONCE_SIZE = 4;
|
||||
constexpr uint8_t EXTRA_NONCE_SIZE = 4;
|
||||
|
@ -89,6 +90,7 @@ constexpr uint8_t EXTRA_NONCE_MAX_SIZE = EXTRA_NONCE_SIZE + 10;
|
|||
constexpr uint8_t TX_VERSION = 2;
|
||||
constexpr uint8_t TXIN_GEN = 0xFF;
|
||||
constexpr uint8_t TXOUT_TO_KEY = 2;
|
||||
constexpr uint8_t TXOUT_TO_TAGGED_KEY = 3;
|
||||
constexpr uint8_t TX_EXTRA_TAG_PUBKEY = 1;
|
||||
constexpr uint8_t TX_EXTRA_NONCE = 2;
|
||||
constexpr uint8_t TX_EXTRA_MERGE_MINING_TAG = 3;
|
||||
|
|
|
@ -144,17 +144,19 @@ public:
|
|||
uv_mutex_destroy(&m);
|
||||
}
|
||||
|
||||
bool get_derivation(const hash& key1, const hash& key2, hash& derivation)
|
||||
bool get_derivation(const hash& key1, const hash& key2, size_t output_index, hash& derivation, uint8_t& view_tag)
|
||||
{
|
||||
std::array<uint8_t, HASH_SIZE * 2> index;
|
||||
std::array<uint8_t, HASH_SIZE * 2 + sizeof(size_t)> index;
|
||||
memcpy(index.data(), key1.h, HASH_SIZE);
|
||||
memcpy(index.data() + HASH_SIZE, key2.h, HASH_SIZE);
|
||||
memcpy(index.data() + HASH_SIZE * 2, &output_index, sizeof(size_t));
|
||||
|
||||
{
|
||||
MutexLock lock(m);
|
||||
auto it = derivations.find(index);
|
||||
if (it != derivations.end()) {
|
||||
derivation = it->second;
|
||||
derivation = it->second.derivation;
|
||||
view_tag = it->second.view_tag;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -172,9 +174,11 @@ public:
|
|||
ge_p1p1_to_p2(&point2, &point3);
|
||||
ge_tobytes(reinterpret_cast<uint8_t*>(&derivation), &point2);
|
||||
|
||||
derive_view_tag(derivation, output_index, view_tag);
|
||||
|
||||
{
|
||||
MutexLock lock(m);
|
||||
derivations.emplace(index, derivation);
|
||||
derivations.emplace(index, DerivationEntry{ derivation, view_tag } );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -231,16 +235,22 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
struct DerivationEntry
|
||||
{
|
||||
hash derivation;
|
||||
uint8_t view_tag;
|
||||
};
|
||||
|
||||
uv_mutex_t m;
|
||||
unordered_map<std::array<uint8_t, HASH_SIZE * 2>, hash> derivations;
|
||||
unordered_map<std::array<uint8_t, HASH_SIZE * 2 + sizeof(size_t)>, DerivationEntry> derivations;
|
||||
unordered_map<std::array<uint8_t, HASH_SIZE * 2 + sizeof(size_t)>, hash> public_keys;
|
||||
};
|
||||
|
||||
static Cache* cache = nullptr;
|
||||
|
||||
bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation)
|
||||
bool generate_key_derivation(const hash& key1, const hash& key2, size_t output_index, hash& derivation, uint8_t& view_tag)
|
||||
{
|
||||
return cache->get_derivation(key1, key2, derivation);
|
||||
return cache->get_derivation(key1, key2, output_index, derivation, view_tag);
|
||||
}
|
||||
|
||||
bool derive_public_key(const hash& derivation, size_t output_index, const hash& base, hash& derived_key)
|
||||
|
@ -248,6 +258,22 @@ bool derive_public_key(const hash& derivation, size_t output_index, const hash&
|
|||
return cache->get_public_key(derivation, output_index, base, derived_key);
|
||||
}
|
||||
|
||||
void derive_view_tag(const hash& derivation, size_t output_index, uint8_t& view_tag)
|
||||
{
|
||||
constexpr uint8_t salt[] = "view_tag";
|
||||
constexpr size_t SALT_SIZE = sizeof(salt) - 1;
|
||||
|
||||
uint8_t buf[64];
|
||||
memcpy(buf, salt, SALT_SIZE);
|
||||
memcpy(buf + SALT_SIZE, derivation.h, HASH_SIZE);
|
||||
uint8_t* p = buf + SALT_SIZE + HASH_SIZE;
|
||||
writeVarint(output_index, [&p](uint8_t b) { *(p++) = b; });
|
||||
|
||||
hash view_tag_full;
|
||||
keccak(buf, static_cast<int>(p - buf), view_tag_full.h, HASH_SIZE);
|
||||
view_tag = view_tag_full.h[0];
|
||||
}
|
||||
|
||||
void init_crypto_cache()
|
||||
{
|
||||
if (!cache) {
|
||||
|
|
|
@ -21,8 +21,9 @@ namespace p2pool {
|
|||
|
||||
void generate_keys(hash& pub, hash& sec);
|
||||
bool check_keys(const hash& pub, const hash& sec);
|
||||
bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation);
|
||||
bool generate_key_derivation(const hash& key1, const hash& key2, size_t output_index, hash& derivation, uint8_t& view_tag);
|
||||
bool derive_public_key(const hash& derivation, size_t output_index, const hash& base, hash& derived_key);
|
||||
void derive_view_tag(const hash& derivation, size_t output_index, uint8_t& view_tag);
|
||||
|
||||
void init_crypto_cache();
|
||||
void destroy_crypto_cache();
|
||||
|
|
|
@ -72,7 +72,8 @@ p2pool::p2pool(int argc, char* argv[])
|
|||
hash pub, sec, eph_public_key;
|
||||
generate_keys(pub, sec);
|
||||
|
||||
if (!m_params->m_wallet.get_eph_public_key(sec, 0, eph_public_key)) {
|
||||
uint8_t view_tag;
|
||||
if (!m_params->m_wallet.get_eph_public_key(sec, 0, eph_public_key, view_tag)) {
|
||||
LOGERR(1, "Invalid wallet address: get_eph_public_key failed");
|
||||
panic();
|
||||
}
|
||||
|
@ -603,13 +604,15 @@ void p2pool::download_block_headers(uint64_t current_height)
|
|||
});
|
||||
}
|
||||
|
||||
const uint64_t start_height = (current_height > BLOCK_HEADERS_REQUIRED) ? (current_height - BLOCK_HEADERS_REQUIRED) : 0;
|
||||
|
||||
s.m_pos = 0;
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << current_height - BLOCK_HEADERS_REQUIRED << ",\"end_height\":" << current_height - 1 << "}}\0";
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << current_height - 1 << "}}\0";
|
||||
|
||||
JSONRPCRequest::call(m_params->m_host.c_str(), m_params->m_rpcPort, buf,
|
||||
[this, current_height](const char* data, size_t size)
|
||||
[this, start_height, current_height](const char* data, size_t size)
|
||||
{
|
||||
if (parse_block_headers_range(data, size) == BLOCK_HEADERS_REQUIRED) {
|
||||
if (parse_block_headers_range(data, size) == current_height - start_height) {
|
||||
update_median_timestamp();
|
||||
if (m_serversStarted.exchange(1) == 0) {
|
||||
m_ZMQReader = new ZMQReader(m_params->m_host.c_str(), m_params->m_zmqPort, this);
|
||||
|
@ -624,14 +627,14 @@ void p2pool::download_block_headers(uint64_t current_height)
|
|||
}
|
||||
}
|
||||
else {
|
||||
LOGERR(1, "fatal error: couldn't download block headers for heights " << current_height - BLOCK_HEADERS_REQUIRED << " - " << current_height - 1);
|
||||
LOGERR(1, "fatal error: couldn't download block headers for heights " << start_height << " - " << current_height - 1);
|
||||
panic();
|
||||
}
|
||||
},
|
||||
[current_height](const char* data, size_t size)
|
||||
[start_height, current_height](const char* data, size_t size)
|
||||
{
|
||||
if (size > 0) {
|
||||
LOGERR(1, "fatal error: couldn't download block headers for heights " << current_height - BLOCK_HEADERS_REQUIRED << " - " << current_height - 1 << ", error " << log::const_buf(data, size));
|
||||
LOGERR(1, "fatal error: couldn't download block headers for heights " << start_height << " - " << current_height - 1 << ", error " << log::const_buf(data, size));
|
||||
panic();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -157,8 +157,12 @@ void PoolBlock::serialize_mainchain_data(uint32_t nonce, uint32_t extra_nonce, c
|
|||
|
||||
for (TxOutput& output : m_outputs) {
|
||||
writeVarint(output.m_reward, m_mainChainData);
|
||||
m_mainChainData.push_back(TXOUT_TO_KEY);
|
||||
m_mainChainData.push_back(output.m_txType);
|
||||
m_mainChainData.insert(m_mainChainData.end(), output.m_ephPublicKey.h, output.m_ephPublicKey.h + HASH_SIZE);
|
||||
|
||||
if (output.m_txType == TXOUT_TO_TAGGED_KEY) {
|
||||
m_mainChainData.push_back(output.m_viewTag);
|
||||
}
|
||||
}
|
||||
|
||||
m_mainChainOutputsBlobSize = static_cast<int>(m_mainChainData.size()) - m_mainChainOutputsOffset;
|
||||
|
@ -301,9 +305,19 @@ bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const
|
|||
uint64_t PoolBlock::get_payout(const Wallet& w) const
|
||||
{
|
||||
for (size_t i = 0, n = m_outputs.size(); i < n; ++i) {
|
||||
const TxOutput& out = m_outputs[i];
|
||||
hash eph_public_key;
|
||||
if ((w.get_eph_public_key(m_txkeySec, i, eph_public_key)) && (eph_public_key == m_outputs[i].m_ephPublicKey)) {
|
||||
return m_outputs[i].m_reward;
|
||||
|
||||
if (out.m_txType == TXOUT_TO_TAGGED_KEY) {
|
||||
if (w.get_eph_public_key_with_view_tag(m_txkeySec, i, eph_public_key, out.m_viewTag) && (eph_public_key == out.m_ephPublicKey)) {
|
||||
return out.m_reward;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint8_t view_tag;
|
||||
if (w.get_eph_public_key(m_txkeySec, i, eph_public_key, view_tag) && (eph_public_key == out.m_ephPublicKey)) {
|
||||
return out.m_reward;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,11 +81,13 @@ struct PoolBlock
|
|||
|
||||
struct TxOutput
|
||||
{
|
||||
FORCEINLINE TxOutput() : m_reward(0), m_ephPublicKey() {}
|
||||
FORCEINLINE TxOutput(uint64_t r, const hash& k) : m_reward(r), m_ephPublicKey(k) {}
|
||||
FORCEINLINE TxOutput() : m_reward(0), m_ephPublicKey(), m_txType(0), m_viewTag(0) {}
|
||||
FORCEINLINE TxOutput(uint64_t r, const hash& k, uint8_t tx_type, uint8_t view_tag) : m_reward(r), m_ephPublicKey(k), m_txType(tx_type), m_viewTag(view_tag) {}
|
||||
|
||||
uint64_t m_reward;
|
||||
hash m_ephPublicKey;
|
||||
uint8_t m_txType;
|
||||
uint8_t m_viewTag;
|
||||
};
|
||||
|
||||
std::vector<TxOutput> m_outputs;
|
||||
|
@ -139,6 +141,10 @@ struct PoolBlock
|
|||
bool get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const hash& seed_hash, hash& pow_hash);
|
||||
|
||||
uint64_t get_payout(const Wallet& w) const;
|
||||
|
||||
// Both tx types are allowed by Monero consensus during v15 because it needs to process pre-fork mempool transactions,
|
||||
// but P2Pool can switch to using only TXOUT_TO_TAGGED_KEY for miner payouts starting from v15
|
||||
FORCEINLINE uint8_t get_tx_type() const { return (m_majorVersion < HARDFORK_VIEW_TAGS_VERSION) ? TXOUT_TO_KEY : TXOUT_TO_TAGGED_KEY; }
|
||||
};
|
||||
|
||||
} // namespace p2pool
|
||||
|
|
|
@ -99,7 +99,7 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai
|
|||
if (num_outputs > 0) {
|
||||
// Outputs are in the buffer, just read them
|
||||
// Each output is at least 34 bytes, exit early if there's not enough data left
|
||||
// 1 byte for reward, 1 byte for TXOUT_TO_KEY, 32 bytes for eph_pub_key
|
||||
// 1 byte for reward, 1 byte for tx_type, 32 bytes for eph_pub_key
|
||||
constexpr uint64_t MIN_OUTPUT_SIZE = 34;
|
||||
|
||||
if (num_outputs > std::numeric_limits<uint64_t>::max() / MIN_OUTPUT_SIZE) return __LINE__;
|
||||
|
@ -108,15 +108,23 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai
|
|||
m_outputs.clear();
|
||||
m_outputs.reserve(num_outputs);
|
||||
|
||||
const uint8_t expected_tx_type = get_tx_type();
|
||||
|
||||
for (uint64_t i = 0; i < num_outputs; ++i) {
|
||||
TxOutput t;
|
||||
|
||||
READ_VARINT(t.m_reward);
|
||||
total_reward += t.m_reward;
|
||||
|
||||
EXPECT_BYTE(TXOUT_TO_KEY);
|
||||
EXPECT_BYTE(expected_tx_type);
|
||||
t.m_txType = expected_tx_type;
|
||||
|
||||
READ_BUF(t.m_ephPublicKey.h, HASH_SIZE);
|
||||
|
||||
if (expected_tx_type == TXOUT_TO_TAGGED_KEY) {
|
||||
READ_BYTE(t.m_viewTag);
|
||||
}
|
||||
|
||||
m_outputs.emplace_back(std::move(t));
|
||||
}
|
||||
|
||||
|
|
|
@ -613,13 +613,17 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
|
|||
PoolBlock* b = it->second;
|
||||
const size_t n = b->m_outputs.size();
|
||||
|
||||
blob.reserve(n * 38 + 64);
|
||||
blob.reserve(n * 39 + 64);
|
||||
writeVarint(n, blob);
|
||||
|
||||
for (const PoolBlock::TxOutput& output : b->m_outputs) {
|
||||
writeVarint(output.m_reward, blob);
|
||||
blob.emplace_back(TXOUT_TO_KEY);
|
||||
blob.emplace_back(output.m_txType);
|
||||
blob.insert(blob.end(), output.m_ephPublicKey.h, output.m_ephPublicKey.h + HASH_SIZE);
|
||||
|
||||
if (output.m_txType == TXOUT_TO_TAGGED_KEY) {
|
||||
blob.emplace_back(output.m_viewTag);
|
||||
}
|
||||
}
|
||||
|
||||
block->m_outputs = b->m_outputs;
|
||||
|
@ -632,25 +636,32 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
|
|||
|
||||
const size_t n = m_tmpShares.size();
|
||||
|
||||
blob.reserve(n * 38 + 64);
|
||||
blob.reserve(n * 39 + 64);
|
||||
|
||||
writeVarint(n, blob);
|
||||
|
||||
block->m_outputs.clear();
|
||||
block->m_outputs.reserve(n);
|
||||
|
||||
const uint8_t tx_type = block->get_tx_type();
|
||||
|
||||
hash eph_public_key;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
writeVarint(m_tmpRewards[i], blob);
|
||||
|
||||
blob.emplace_back(TXOUT_TO_KEY);
|
||||
blob.emplace_back(tx_type);
|
||||
|
||||
if (!m_tmpShares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key)) {
|
||||
uint8_t view_tag;
|
||||
if (!m_tmpShares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key, view_tag)) {
|
||||
LOGWARN(6, "get_eph_public_key failed at index " << i);
|
||||
}
|
||||
blob.insert(blob.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE);
|
||||
|
||||
block->m_outputs.emplace_back(m_tmpRewards[i], eph_public_key);
|
||||
if (tx_type == TXOUT_TO_TAGGED_KEY) {
|
||||
blob.emplace_back(view_tag);
|
||||
}
|
||||
|
||||
block->m_outputs.emplace_back(m_tmpRewards[i], eph_public_key, tx_type, view_tag);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -737,14 +748,24 @@ void SideChain::print_status()
|
|||
}
|
||||
|
||||
Wallet w = m_pool->params().m_wallet;
|
||||
const std::vector<PoolBlock::TxOutput>& outs = tip->m_outputs;
|
||||
|
||||
hash eph_public_key;
|
||||
for (size_t i = 0, n = outs.size(); i < n; ++i) {
|
||||
if (w.get_eph_public_key(tip->m_txkeySec, i, eph_public_key) && (outs[i].m_ephPublicKey == eph_public_key)) {
|
||||
your_reward = outs[i].m_reward;
|
||||
for (size_t i = 0, n = tip->m_outputs.size(); i < n; ++i) {
|
||||
const PoolBlock::TxOutput& out = tip->m_outputs[i];
|
||||
if (!your_reward) {
|
||||
if (out.m_txType == TXOUT_TO_TAGGED_KEY) {
|
||||
if (w.get_eph_public_key_with_view_tag(tip->m_txkeySec, i, eph_public_key, out.m_viewTag) && (out.m_ephPublicKey == eph_public_key)) {
|
||||
your_reward = out.m_reward;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint8_t view_tag;
|
||||
if (w.get_eph_public_key(tip->m_txkeySec, i, eph_public_key, view_tag) && (out.m_ephPublicKey == eph_public_key)) {
|
||||
your_reward = out.m_reward;
|
||||
}
|
||||
}
|
||||
}
|
||||
total_reward += outs[i].m_reward;
|
||||
total_reward += out.m_reward;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1320,17 +1341,20 @@ void SideChain::verify(PoolBlock* block)
|
|||
}
|
||||
|
||||
for (size_t i = 0, n = rewards.size(); i < n; ++i) {
|
||||
if (rewards[i] != block->m_outputs[i].m_reward) {
|
||||
const PoolBlock::TxOutput& out = block->m_outputs[i];
|
||||
|
||||
if (rewards[i] != out.m_reward) {
|
||||
LOGWARN(3, "block at height = " << block->m_sidechainHeight <<
|
||||
", id = " << block->m_sidechainId <<
|
||||
", mainchain height = " << block->m_txinGenHeight <<
|
||||
" has invalid reward at index " << i << ": got " << block->m_outputs[i].m_reward << ", expected " << rewards[i]);
|
||||
" has invalid reward at index " << i << ": got " << out.m_reward << ", expected " << rewards[i]);
|
||||
block->m_invalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
hash eph_public_key;
|
||||
if (!shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key)) {
|
||||
uint8_t view_tag;
|
||||
if (!shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key, view_tag)) {
|
||||
LOGWARN(3, "block at height = " << block->m_sidechainHeight <<
|
||||
", id = " << block->m_sidechainId <<
|
||||
", mainchain height = " << block->m_txinGenHeight <<
|
||||
|
@ -1339,7 +1363,16 @@ void SideChain::verify(PoolBlock* block)
|
|||
return;
|
||||
}
|
||||
|
||||
if (eph_public_key != block->m_outputs[i].m_ephPublicKey) {
|
||||
if ((out.m_txType == TXOUT_TO_TAGGED_KEY) && (out.m_viewTag != view_tag)) {
|
||||
LOGWARN(3, "block at height = " << block->m_sidechainHeight <<
|
||||
", id = " << block->m_sidechainId <<
|
||||
", mainchain height = " << block->m_txinGenHeight <<
|
||||
" has an incorrect view tag at index " << i);
|
||||
block->m_invalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (eph_public_key != out.m_ephPublicKey) {
|
||||
LOGWARN(3, "block at height = " << block->m_sidechainHeight <<
|
||||
", id = " << block->m_sidechainId <<
|
||||
", mainchain height = " << block->m_txinGenHeight <<
|
||||
|
|
|
@ -195,10 +195,25 @@ bool Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key, Network
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key) const
|
||||
bool Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key, uint8_t& view_tag) const
|
||||
{
|
||||
hash derivation;
|
||||
if (!generate_key_derivation(m_viewPublicKey, txkey_sec, derivation)) {
|
||||
if (!generate_key_derivation(m_viewPublicKey, txkey_sec, output_index, derivation, view_tag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!derive_public_key(derivation, output_index, m_spendPublicKey, eph_public_key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wallet::get_eph_public_key_with_view_tag(const hash& txkey_sec, size_t output_index, hash& eph_public_key, uint8_t expected_view_tag) const
|
||||
{
|
||||
hash derivation;
|
||||
uint8_t view_tag;
|
||||
if (!generate_key_derivation(m_viewPublicKey, txkey_sec, output_index, derivation, view_tag) || (view_tag != expected_view_tag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ public:
|
|||
FORCEINLINE const hash& spend_public_key() const { return m_spendPublicKey; }
|
||||
FORCEINLINE const hash& view_public_key() const { return m_viewPublicKey; }
|
||||
|
||||
bool get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key) const;
|
||||
bool get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key, uint8_t& view_tag) const;
|
||||
bool get_eph_public_key_with_view_tag(const hash& txkey_sec, size_t output_index, hash& eph_public_key, uint8_t expected_view_tag) const;
|
||||
|
||||
FORCEINLINE bool operator<(const Wallet& w) const { return m_spendPublicKey < w.m_spendPublicKey; }
|
||||
FORCEINLINE bool operator==(const Wallet& w) const { return m_spendPublicKey == w.m_spendPublicKey; }
|
||||
|
|
|
@ -42,7 +42,8 @@ TEST(crypto, derivation)
|
|||
if (result) {
|
||||
f >> expected_derivation;
|
||||
}
|
||||
ASSERT_EQ(p2pool::generate_key_derivation(key1, key2, derivation), result);
|
||||
uint8_t view_tag;
|
||||
ASSERT_EQ(p2pool::generate_key_derivation(key1, key2, 0, derivation, view_tag), result);
|
||||
if (result) {
|
||||
ASSERT_EQ(derivation, expected_derivation);
|
||||
}
|
||||
|
@ -61,6 +62,20 @@ TEST(crypto, derivation)
|
|||
ASSERT_EQ(derived_key, expected_derived_key);
|
||||
}
|
||||
}
|
||||
else if (name == "derive_view_tag") {
|
||||
hash derivation;
|
||||
uint64_t output_index;
|
||||
std::string result_str;
|
||||
f >> derivation >> output_index >> result_str;
|
||||
uint8_t view_tag;
|
||||
p2pool::derive_view_tag(derivation, output_index, view_tag);
|
||||
|
||||
char buf[log::Stream::BUF_SIZE + 1];
|
||||
log::Stream s(buf);
|
||||
s << log::hex_buf(&view_tag, 1) << '\0';
|
||||
|
||||
ASSERT_EQ(buf, result_str);
|
||||
}
|
||||
} while (!f.eof());
|
||||
}
|
||||
|
||||
|
|
|
@ -542,3 +542,59 @@ derive_public_key 5ea95a51ab11b80c7d09d0c8f8952b70c67e81d0fd421bbed43ab77c1b7b30
|
|||
derive_public_key 2c312ef971def53361274c37a90bfde86f959d877a636ea641a9c976ee80c7e3 121 b611ebd2bcfefc81cb772e35e3dd0204575cb0da644f68d4f9828a2683861e6c false
|
||||
derive_public_key 6fa161dd958022caf185faf873dd9adbc5578352cda505e84fff7cc99a8762a7 333934910 c2b56e207862958751d49643f23079009092c32bf82179a1295e3b85a385c1c3 false
|
||||
derive_public_key d85725562544e1984048391413a6112eb221bd217db3baaa9843bee331000e8e 21880446 f3148c3041e634d829e5df463ba3b1d64df282d620d63485e1f10024e003b939 false
|
||||
derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 0 76
|
||||
derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 1 d6
|
||||
derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 2 87
|
||||
derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 3 1b
|
||||
derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 12 d6
|
||||
derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 13 e9
|
||||
derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 14 12
|
||||
derive_view_tag 0fc47054f355ced4d67de73bfa12e4c78ff19089548fffa7d07a674741860f97 15 26
|
||||
derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 0 70
|
||||
derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 1 81
|
||||
derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 2 a0
|
||||
derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 3 ec
|
||||
derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 12 22
|
||||
derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 13 0a
|
||||
derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 14 87
|
||||
derive_view_tag a36ba7b4d31349ad278a6df8f77adb76748b59f4929348e67dd92adb9fa174dc 15 76
|
||||
derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 0 93
|
||||
derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 1 67
|
||||
derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 2 9d
|
||||
derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 3 2d
|
||||
derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 12 63
|
||||
derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 13 cf
|
||||
derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 14 ef
|
||||
derive_view_tag 7498d5bf0b69e08653f6d420a17f866dd2bd490ab43074f46065cb501fe7e2d8 15 10
|
||||
derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 0 90
|
||||
derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 1 5a
|
||||
derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 2 de
|
||||
derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 3 21
|
||||
derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 12 57
|
||||
derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 13 52
|
||||
derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 14 6f
|
||||
derive_view_tag fe7770c4b076e95ddb8026affcfab39d31c7c4a2266e0e25e343bc4badc907d0 15 eb
|
||||
derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 0 c6
|
||||
derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 1 60
|
||||
derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 2 f0
|
||||
derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 3 71
|
||||
derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 12 0e
|
||||
derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 13 42
|
||||
derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 14 b2
|
||||
derive_view_tag ea9337d0ddf480abdc4fc56a0cb223702729cb230ae7b9de50243ad25ce90e8d 15 61
|
||||
derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 0 4c
|
||||
derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 1 9b
|
||||
derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 2 64
|
||||
derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 3 ff
|
||||
derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 12 e3
|
||||
derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 13 24
|
||||
derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 14 ea
|
||||
derive_view_tag 25d538315bcb81aff9574189ea65f418aeb0392f5cbbc84cd8a33c7ade31ef0a 15 3b
|
||||
derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 0 74
|
||||
derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 1 77
|
||||
derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 2 a9
|
||||
derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 3 44
|
||||
derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 12 75
|
||||
derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 13 05
|
||||
derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 14 ca
|
||||
derive_view_tag 8edfabada2b24ef4d8d915826c9ff0245910e4b835b59c2cf8ed8fc991b2e1e8 15 00
|
||||
|
|
Loading…
Reference in a new issue