Skip to content

Commit 8c6c331

Browse files
committed
Major update! Added support for FantomCoin blocks
1 parent 71f1a6d commit 8c6c331

13 files changed

Lines changed: 565 additions & 21 deletions

src/crypto/hash-ops.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,6 @@ void hash_extra_jh(const void *data, size_t length, char *hash);
6161
void hash_extra_skein(const void *data, size_t length, char *hash);
6262

6363
void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash);
64+
size_t tree_depth(size_t count);
65+
void tree_branch(const char (*hashes)[HASH_SIZE], size_t count, char (*branch)[HASH_SIZE]);
66+
void tree_hash_from_branch(const char (*branch)[HASH_SIZE], size_t depth, const char *leaf, const void *path, char *root_hash);

src/crypto/hash.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ namespace crypto {
4545
tree_hash(reinterpret_cast<const char (*)[HASH_SIZE]>(hashes), count, reinterpret_cast<char *>(&root_hash));
4646
}
4747

48+
inline void tree_branch(const hash* hashes, std::size_t count, hash* branch)
49+
{
50+
tree_branch(reinterpret_cast<const char (*)[HASH_SIZE]>(hashes), count, reinterpret_cast<char (*)[HASH_SIZE]>(branch));
51+
}
52+
53+
inline void tree_hash_from_branch(const hash* branch, std::size_t depth, const hash& leaf, const void* path, hash& root_hash)
54+
{
55+
tree_hash_from_branch(reinterpret_cast<const char (*)[HASH_SIZE]>(branch), depth, reinterpret_cast<const char*>(&leaf), path, reinterpret_cast<char*>(&root_hash));
56+
}
57+
4858
}
4959

5060
CRYPTO_MAKE_HASHABLE(hash)

src/crypto/tree-hash.c

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash) {
1919
size_t i, j;
2020
size_t cnt = count - 1;
2121
char (*ints)[HASH_SIZE];
22-
for (i = 1; i < sizeof(size_t); i <<= 1) {
22+
for (i = 1; i < sizeof(size_t) << 3; i <<= 1) {
2323
cnt |= cnt >> i;
2424
}
2525
cnt &= ~(cnt >> 1);
2626
ints = alloca(cnt * HASH_SIZE);
2727
memcpy(ints, hashes, (2 * cnt - count) * HASH_SIZE);
2828
for (i = 2 * cnt - count, j = 2 * cnt - count; j < cnt; i += 2, ++j) {
29-
cn_fast_hash(hashes[i], 64, ints[j]);
29+
cn_fast_hash(hashes[i], 2 * HASH_SIZE, ints[j]);
3030
}
3131
assert(i == count);
3232
while (cnt > 2) {
@@ -35,6 +35,98 @@ void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash) {
3535
cn_fast_hash(ints[i], 64, ints[j]);
3636
}
3737
}
38-
cn_fast_hash(ints[0], 64, root_hash);
38+
cn_fast_hash(ints[0], 2 * HASH_SIZE, root_hash);
3939
}
4040
}
41+
42+
size_t tree_depth(size_t count)
43+
{
44+
size_t i;
45+
size_t depth = 0;
46+
assert(count > 0);
47+
for (i = sizeof(size_t) << 2; i > 0; i >>= 1)
48+
{
49+
if (count >> i > 0)
50+
{
51+
count >>= i;
52+
depth += i;
53+
}
54+
}
55+
return depth;
56+
}
57+
58+
void tree_branch(const char (*hashes)[HASH_SIZE], size_t count, char (*branch)[HASH_SIZE])
59+
{
60+
size_t i, j;
61+
size_t cnt = 1;
62+
size_t depth = 0;
63+
char (*ints)[HASH_SIZE];
64+
assert(count > 0);
65+
for (i = sizeof(size_t) << 2; i > 0; i >>= 1)
66+
{
67+
if (cnt << i <= count)
68+
{
69+
cnt <<= i;
70+
depth += i;
71+
}
72+
}
73+
assert(cnt == 1ULL << depth);
74+
assert(depth == tree_depth(count));
75+
ints = alloca((cnt - 1) * HASH_SIZE);
76+
memcpy(ints, hashes + 1, (2 * cnt - count - 1) * HASH_SIZE);
77+
for (i = 2 * cnt - count, j = 2 * cnt - count - 1; j < cnt - 1; i += 2, ++j)
78+
{
79+
cn_fast_hash(hashes[i], 2 * HASH_SIZE, ints[j]);
80+
}
81+
assert(i == count);
82+
while (depth > 0)
83+
{
84+
assert(cnt == 1ULL << depth);
85+
cnt >>= 1;
86+
--depth;
87+
memcpy(branch[depth], ints[0], HASH_SIZE);
88+
for (i = 1, j = 0; j < cnt - 1; i += 2, ++j)
89+
{
90+
cn_fast_hash(ints[i], 2 * HASH_SIZE, ints[j]);
91+
}
92+
}
93+
}
94+
95+
void tree_hash_from_branch(const char (*branch)[HASH_SIZE], size_t depth, const char* leaf, const void* path, char* root_hash)
96+
{
97+
if (depth == 0)
98+
{
99+
memcpy(root_hash, leaf, HASH_SIZE);
100+
}
101+
else
102+
{
103+
char buffer[2][HASH_SIZE];
104+
int from_leaf = 1;
105+
char *leaf_path, *branch_path;
106+
while (depth > 0)
107+
{
108+
--depth;
109+
if (path && (((const char*) path)[depth >> 3] & (1 << (depth & 7))) != 0)
110+
{
111+
leaf_path = buffer[1];
112+
branch_path = buffer[0];
113+
}
114+
else
115+
{
116+
leaf_path = buffer[0];
117+
branch_path = buffer[1];
118+
}
119+
if (from_leaf)
120+
{
121+
memcpy(leaf_path, leaf, HASH_SIZE);
122+
from_leaf = 0;
123+
}
124+
else
125+
{
126+
cn_fast_hash(buffer, 2 * HASH_SIZE, leaf_path);
127+
}
128+
memcpy(branch_path, branch[depth], HASH_SIZE);
129+
}
130+
cn_fast_hash(buffer, 2 * HASH_SIZE, root_hash);
131+
}
132+
}

src/cryptonote_config.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#define CURRENT_BLOCK_MAJOR_VERSION 1
66
#define CURRENT_BLOCK_MINOR_VERSION 0
77

8+
#define BLOCK_MAJOR_VERSION_1 1
9+
#define BLOCK_MAJOR_VERSION_2 2
10+
811
#define COIN ((uint64_t)100000000) // pow(10, 8)
912
#define DEFAULT_FEE ((uint64_t)1000000) // pow(10, 6)
1013

src/cryptonote_core/cryptonote_basic.h

Lines changed: 124 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <boost/variant.hpp>
88
#include <boost/functional/hash/hash.hpp>
9+
#include <iostream>
910
#include <vector>
1011
#include <cstring> // memcmp
1112
#include <sstream>
@@ -27,6 +28,13 @@
2728

2829
namespace cryptonote
2930
{
31+
struct block;
32+
class transaction;
33+
struct tx_extra_merge_mining_tag;
34+
35+
// Implemented in cryptonote_format_utils.cpp
36+
bool get_transaction_hash(const transaction& t, crypto::hash& res);
37+
bool get_mm_tag_from_extra(const std::vector<uint8_t>& tx, tx_extra_merge_mining_tag& mm_tag);
3038

3139
const static crypto::hash null_hash = AUTO_VAL_INIT(null_hash);
3240
const static crypto::public_key null_pkey = AUTO_VAL_INIT(null_pkey);
@@ -346,35 +354,148 @@ namespace cryptonote
346354
/************************************************************************/
347355
/* */
348356
/************************************************************************/
357+
358+
const uint8_t CURRENT_BYTECOIN_BLOCK_MAJOR_VERSION = 1;
359+
360+
struct bytecoin_block
361+
{
362+
uint8_t major_version;
363+
uint8_t minor_version;
364+
crypto::hash prev_id;
365+
uint32_t nonce;
366+
size_t number_of_transactions;
367+
std::vector<crypto::hash> miner_tx_branch;
368+
transaction miner_tx;
369+
std::vector<crypto::hash> blockchain_branch;
370+
};
371+
372+
struct serializable_bytecoin_block
373+
{
374+
bytecoin_block& b;
375+
uint64_t& timestamp;
376+
bool hashing_serialization;
377+
bool header_only;
378+
379+
serializable_bytecoin_block(bytecoin_block& b_, uint64_t& timestamp_, bool hashing_serialization_, bool header_only_) :
380+
b(b_), timestamp(timestamp_), hashing_serialization(hashing_serialization_), header_only(header_only_)
381+
{
382+
}
383+
384+
BEGIN_SERIALIZE_OBJECT()
385+
VARINT_FIELD_N("major_version", b.major_version);
386+
if(b.major_version > CURRENT_BYTECOIN_BLOCK_MAJOR_VERSION) return false;
387+
VARINT_FIELD_N("minor_version", b.minor_version);
388+
VARINT_FIELD(timestamp);
389+
FIELD_N("prev_id", b.prev_id);
390+
FIELD_N("nonce", b.nonce);
391+
392+
if (hashing_serialization)
393+
{
394+
crypto::hash miner_tx_hash;
395+
if (!get_transaction_hash(b.miner_tx, miner_tx_hash))
396+
return false;
397+
398+
crypto::hash merkle_root;
399+
crypto::tree_hash_from_branch(b.miner_tx_branch.data(), b.miner_tx_branch.size(), miner_tx_hash, 0, merkle_root);
400+
401+
FIELD(merkle_root);
402+
}
403+
404+
VARINT_FIELD_N("number_of_transactions", b.number_of_transactions);
405+
if (b.number_of_transactions < 1)
406+
return false;
407+
408+
if (!header_only)
409+
{
410+
ar.tag("miner_tx_branch");
411+
ar.begin_array();
412+
size_t branch_size = crypto::tree_depth(b.number_of_transactions);
413+
PREPARE_CUSTOM_VECTOR_SERIALIZATION(branch_size, const_cast<bytecoin_block&>(b).miner_tx_branch);
414+
if (b.miner_tx_branch.size() != branch_size)
415+
return false;
416+
for (size_t i = 0; i < branch_size; ++i)
417+
{
418+
FIELDS(b.miner_tx_branch[i]);
419+
if (i + 1 < branch_size)
420+
ar.delimit_array();
421+
}
422+
ar.end_array();
423+
424+
FIELD(b.miner_tx);
425+
426+
tx_extra_merge_mining_tag mm_tag;
427+
if (!get_mm_tag_from_extra(b.miner_tx.extra, mm_tag))
428+
return false;
429+
430+
ar.tag("blockchain_branch");
431+
ar.begin_array();
432+
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mm_tag.depth, const_cast<bytecoin_block&>(b).blockchain_branch);
433+
if (mm_tag.depth != b.blockchain_branch.size())
434+
return false;
435+
for (size_t i = 0; i < mm_tag.depth; ++i)
436+
{
437+
FIELDS(b.blockchain_branch[i]);
438+
if (i + 1 < mm_tag.depth)
439+
ar.delimit_array();
440+
}
441+
ar.end_array();
442+
}
443+
END_SERIALIZE()
444+
};
445+
446+
// Implemented below
447+
inline serializable_bytecoin_block make_serializable_bytecoin_block(const block& b, bool hashing_serialization, bool header_only);
448+
349449
struct block_header
350450
{
351451
uint8_t major_version;
352452
uint8_t minor_version;
353453
uint64_t timestamp;
354-
crypto::hash prev_id;
454+
crypto::hash prev_id;
355455
uint32_t nonce;
356456

357457
BEGIN_SERIALIZE()
358458
VARINT_FIELD(major_version)
459+
if(major_version > BLOCK_MAJOR_VERSION_2) return false;
359460
VARINT_FIELD(minor_version)
360-
VARINT_FIELD(timestamp)
461+
if (BLOCK_MAJOR_VERSION_1 == major_version)
462+
{
463+
VARINT_FIELD(timestamp)
464+
}
361465
FIELD(prev_id)
362-
FIELD(nonce)
466+
if (BLOCK_MAJOR_VERSION_1 == major_version)
467+
{
468+
FIELD(nonce)
469+
}
363470
END_SERIALIZE()
364471
};
365472

366473
struct block: public block_header
367474
{
475+
bytecoin_block parent_block;
476+
368477
transaction miner_tx;
369478
std::vector<crypto::hash> tx_hashes;
370479

371480
BEGIN_SERIALIZE_OBJECT()
372481
FIELDS(*static_cast<block_header *>(this))
482+
if (BLOCK_MAJOR_VERSION_2 <= major_version)
483+
{
484+
auto sbb = make_serializable_bytecoin_block(*this, false, false);
485+
FIELD_N("parent_block", sbb);
486+
}
373487
FIELD(miner_tx)
374488
FIELD(tx_hashes)
375489
END_SERIALIZE()
376490
};
377491

492+
inline serializable_bytecoin_block make_serializable_bytecoin_block(const block& b, bool hashing_serialization, bool header_only)
493+
{
494+
block& block_ref = const_cast<block&>(b);
495+
return serializable_bytecoin_block(block_ref.parent_block, block_ref.timestamp, hashing_serialization, header_only);
496+
}
497+
498+
378499
struct bb_block_header
379500
{
380501
uint8_t major_version;

0 commit comments

Comments
 (0)