diff --git a/binding.gyp b/binding.gyp index 908866b..612d74b 100644 --- a/binding.gyp +++ b/binding.gyp @@ -8,24 +8,24 @@ "src/crypto/tree-hash.c", "src/crypto/hash.c", "src/crypto/keccak.c", - "src/common/base58.cpp" + "src/common/base58.cpp", ], "include_dirs": [ "src", - "src/contrib/epee/include" + "src/contrib/epee/include", ], "link_settings": { "libraries": [ "-lboost_system", - "-lboost_date_time" + "-lboost_date_time", ] }, "cflags_cc!": [ "-fno-exceptions", "-fno-rtti" ], "cflags_cc": [ "-std=c++0x", "-fexceptions", - "-frtti" - ] + "-frtti", + ], } ] } diff --git a/src/cryptonote_core/cryptonote_basic.h b/src/cryptonote_core/cryptonote_basic.h index 007e62b..aee48d0 100644 --- a/src/cryptonote_core/cryptonote_basic.h +++ b/src/cryptonote_core/cryptonote_basic.h @@ -59,6 +59,16 @@ namespace cryptonote crypto::public_key key; }; + #pragma pack(push, 1) + struct bb_txout_to_key + { + bb_txout_to_key() { } + bb_txout_to_key(const crypto::public_key &_key) : key(_key) { } + crypto::public_key key; + uint8_t mix_attr; + }; + #pragma pack(pop) + /* inputs */ @@ -116,6 +126,7 @@ namespace cryptonote typedef boost::variant txin_v; typedef boost::variant txout_target_v; + typedef boost::variant bb_txout_target_v; //typedef std::pair out_t; struct tx_out @@ -127,8 +138,16 @@ namespace cryptonote VARINT_FIELD(amount) FIELD(target) END_SERIALIZE() + }; + struct bb_tx_out + { + uint64_t amount; + bb_txout_target_v target; - + BEGIN_SERIALIZE_OBJECT() + VARINT_FIELD(amount) + FIELD(target) + END_SERIALIZE() }; class transaction_prefix @@ -204,6 +223,49 @@ namespace cryptonote static size_t get_signature_size(const txin_v& tx_in); }; + class bb_transaction_prefix + { + + public: + // tx information + size_t version; + uint64_t unlock_time; //number of block (or time), used as a limitation like: spend this tx not early then block/time + + std::vector vin; + std::vector vout; + //extra + std::vector extra; + + BEGIN_SERIALIZE() + VARINT_FIELD(version) + VARINT_FIELD(unlock_time) + FIELD(vin) + FIELD(vout) + FIELD(extra) + END_SERIALIZE() + + + protected: + bb_transaction_prefix(){} + }; + + class bb_transaction: public bb_transaction_prefix + { + public: + std::vector > signatures; //count signatures always the same as inputs count + + bb_transaction(); + virtual ~bb_transaction(); + void set_null(); + + BEGIN_SERIALIZE_OBJECT() + FIELDS(*static_cast(this)) + FIELD(signatures) + END_SERIALIZE() + + static size_t get_signature_size(const txin_v& tx_in); + }; + inline transaction::transaction() @@ -242,6 +304,43 @@ namespace cryptonote return boost::apply_visitor(txin_signature_size_visitor(), tx_in); } + inline + bb_transaction::bb_transaction() + { + set_null(); + } + + inline + bb_transaction::~bb_transaction() + { + //set_null(); + } + + inline + void bb_transaction::set_null() + { + version = 0; + unlock_time = 0; + vin.clear(); + vout.clear(); + extra.clear(); + signatures.clear(); + } + + inline + size_t bb_transaction::get_signature_size(const txin_v& tx_in) + { + struct txin_signature_size_visitor : public boost::static_visitor + { + size_t operator()(const txin_gen& txin) const{return 0;} + size_t operator()(const txin_to_script& txin) const{return 0;} + size_t operator()(const txin_to_scripthash& txin) const{return 0;} + size_t operator()(const txin_to_key& txin) const {return txin.key_offsets.size();} + }; + + return boost::apply_visitor(txin_signature_size_visitor(), tx_in); + } + /************************************************************************/ @@ -257,7 +356,6 @@ namespace cryptonote BEGIN_SERIALIZE() VARINT_FIELD(major_version) - if(major_version > CURRENT_BLOCK_MAJOR_VERSION) return false; VARINT_FIELD(minor_version) VARINT_FIELD(timestamp) FIELD(prev_id) @@ -277,6 +375,37 @@ namespace cryptonote END_SERIALIZE() }; + struct bb_block_header + { + uint8_t major_version; + uint8_t minor_version; + uint64_t timestamp; + crypto::hash prev_id; + uint64_t nonce; + uint8_t flags; + + BEGIN_SERIALIZE() + FIELD(major_version) + FIELD(nonce) + FIELD(prev_id) + VARINT_FIELD(minor_version) + VARINT_FIELD(timestamp) + FIELD(flags) + END_SERIALIZE() + }; + + struct bb_block: public bb_block_header + { + bb_transaction miner_tx; + std::vector tx_hashes; + + BEGIN_SERIALIZE() + FIELDS(*static_cast(this)) + FIELD(miner_tx) + FIELD(tx_hashes) + END_SERIALIZE() + }; + /************************************************************************/ /* */ @@ -314,6 +443,7 @@ namespace cryptonote } BLOB_SERIALIZER(cryptonote::txout_to_key); +BLOB_SERIALIZER(cryptonote::bb_txout_to_key); BLOB_SERIALIZER(cryptonote::txout_to_scripthash); VARIANT_TAG(binary_archive, cryptonote::txin_gen, 0xff); @@ -323,6 +453,7 @@ VARIANT_TAG(binary_archive, cryptonote::txin_to_key, 0x2); VARIANT_TAG(binary_archive, cryptonote::txout_to_script, 0x0); VARIANT_TAG(binary_archive, cryptonote::txout_to_scripthash, 0x1); VARIANT_TAG(binary_archive, cryptonote::txout_to_key, 0x2); +VARIANT_TAG(binary_archive, cryptonote::bb_txout_to_key, 0x2); VARIANT_TAG(binary_archive, cryptonote::transaction, 0xcc); VARIANT_TAG(binary_archive, cryptonote::block, 0xbb); @@ -333,6 +464,7 @@ VARIANT_TAG(json_archive, cryptonote::txin_to_key, "key"); VARIANT_TAG(json_archive, cryptonote::txout_to_script, "script"); VARIANT_TAG(json_archive, cryptonote::txout_to_scripthash, "scripthash"); VARIANT_TAG(json_archive, cryptonote::txout_to_key, "key"); +VARIANT_TAG(json_archive, cryptonote::bb_txout_to_key, "key"); VARIANT_TAG(json_archive, cryptonote::transaction, "tx"); VARIANT_TAG(json_archive, cryptonote::block, "block"); @@ -343,5 +475,6 @@ VARIANT_TAG(debug_archive, cryptonote::txin_to_key, "key"); VARIANT_TAG(debug_archive, cryptonote::txout_to_script, "script"); VARIANT_TAG(debug_archive, cryptonote::txout_to_scripthash, "scripthash"); VARIANT_TAG(debug_archive, cryptonote::txout_to_key, "key"); +VARIANT_TAG(debug_archive, cryptonote::bb_txout_to_key, "key"); VARIANT_TAG(debug_archive, cryptonote::transaction, "tx"); VARIANT_TAG(debug_archive, cryptonote::block, "block"); diff --git a/src/cryptonote_core/cryptonote_boost_serialization.h b/src/cryptonote_core/cryptonote_boost_serialization.h index 80c4978..9dd6912 100644 --- a/src/cryptonote_core/cryptonote_boost_serialization.h +++ b/src/cryptonote_core/cryptonote_boost_serialization.h @@ -68,6 +68,14 @@ namespace boost a & x.key; } + + template + inline void serialize(Archive &a, cryptonote::bb_txout_to_key &x, const boost::serialization::version_type ver) + { + a & x.key; + a & x.mix_attr; + } + template inline void serialize(Archive &a, cryptonote::txout_to_scripthash &x, const boost::serialization::version_type ver) { @@ -124,7 +132,6 @@ namespace boost a & x.signatures; } - template inline void serialize(Archive &a, cryptonote::block &b, const boost::serialization::version_type ver) { diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index 2b38d00..693f671 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -586,6 +586,13 @@ namespace cryptonote size_t blob_size = 0; return get_object_hash(t, res, blob_size); } + + bool get_transaction_hash(const bb_transaction& t, crypto::hash& res) + { + size_t blob_size = 0; + return get_object_hash(t, res, blob_size); + } + //--------------------------------------------------------------- bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size) { @@ -600,6 +607,14 @@ namespace cryptonote blob.append(tools::get_varint_data(b.tx_hashes.size()+1)); return blob; } + blobdata get_block_hashing_blob(const bb_block& b) + { + blobdata blob = t_serializable_object_to_blob(static_cast(b)); + crypto::hash tree_root_hash = get_tx_tree_hash(b); + blob.append((const char*)&tree_root_hash, sizeof(tree_root_hash )); + blob.append(tools::get_varint_data(b.tx_hashes.size()+1)); + return blob; + } //--------------------------------------------------------------- bool get_block_hash(const block& b, crypto::hash& res) { @@ -684,6 +699,15 @@ namespace cryptonote CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob"); return true; } + bool parse_and_validate_block_from_blob(const blobdata& b_blob, bb_block& b) + { + std::stringstream ss; + ss << b_blob; + binary_archive ba(ss); + bool r = ::serialization::serialize(ba, b); + CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob"); + return true; + } //--------------------------------------------------------------- blobdata block_to_blob(const block& b) { @@ -728,5 +752,15 @@ namespace cryptonote txs_ids.push_back(th); return get_tx_tree_hash(txs_ids); } + crypto::hash get_tx_tree_hash(const bb_block& b) + { + std::vector txs_ids; + crypto::hash h = null_hash; + get_transaction_hash(b.miner_tx, h); + txs_ids.push_back(h); + BOOST_FOREACH(auto& th, b.tx_hashes) + txs_ids.push_back(th); + return get_tx_tree_hash(txs_ids); + } //--------------------------------------------------------------- } diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h index 138fb52..0552760 100644 --- a/src/cryptonote_core/cryptonote_format_utils.h +++ b/src/cryptonote_core/cryptonote_format_utils.h @@ -75,12 +75,14 @@ namespace cryptonote bool get_transaction_hash(const transaction& t, crypto::hash& res); bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size); blobdata get_block_hashing_blob(const block& b); + blobdata get_block_hashing_blob(const bb_block& b); bool get_block_hash(const block& b, crypto::hash& res); crypto::hash get_block_hash(const block& b); bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height); crypto::hash get_block_longhash(const block& b, uint64_t height); bool generate_genesis_block(block& bl); bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b); + bool parse_and_validate_block_from_blob(const blobdata& b_blob, bb_block& b); bool get_inputs_money_amount(const transaction& tx, uint64_t& money); uint64_t get_outs_money_amount(const transaction& tx); bool check_inputs_types_supported(const transaction& tx); @@ -196,6 +198,7 @@ namespace cryptonote void get_tx_tree_hash(const std::vector& tx_hashes, crypto::hash& h); crypto::hash get_tx_tree_hash(const std::vector& tx_hashes); crypto::hash get_tx_tree_hash(const block& b); + crypto::hash get_tx_tree_hash(const bb_block& b); #define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \ CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \ diff --git a/src/main.cc b/src/main.cc index 3dc7f79..0e50782 100644 --- a/src/main.cc +++ b/src/main.cc @@ -52,9 +52,31 @@ Handle convert_blob(const Arguments& args) { return except("Failed to parse block"); } output = get_block_hashing_blob(b); -// crypto::hash tree_root_hash = get_tx_tree_hash(b); -// blob.append((const char*)&tree_root_hash, sizeof(tree_root_hash )); -// blob.append(tools::get_varint_data(b.tx_hashes.size()+1)); + + Buffer* buff = Buffer::New(output.data(), output.size()); + return scope.Close(buff->handle_); +} + +Handle convert_blob_bb(const Arguments& args) { + HandleScope scope; + + if (args.Length() < 1) + return except("You must provide one argument."); + + Local target = args[0]->ToObject(); + + if (!Buffer::HasInstance(target)) + return except("Argument should be a buffer object."); + + blobdata input = std::string(Buffer::Data(target), Buffer::Length(target)); + blobdata output = ""; + + //convert + bb_block b = AUTO_VAL_INIT(b); + if (!parse_and_validate_block_from_blob(input, b)) { + return except("Failed to parse block"); + } + output = get_block_hashing_blob(b); Buffer* buff = Buffer::New(output.data(), output.size()); return scope.Close(buff->handle_); @@ -87,6 +109,7 @@ Handle address_decode(const Arguments& args) { void init(Handle exports) { exports->Set(String::NewSymbol("convert_blob"), FunctionTemplate::New(convert_blob)->GetFunction()); + exports->Set(String::NewSymbol("convert_blob_bb"), FunctionTemplate::New(convert_blob_bb)->GetFunction()); exports->Set(String::NewSymbol("address_decode"), FunctionTemplate::New(address_decode)->GetFunction()); } diff --git a/src/serialization/vector.h b/src/serialization/vector.h index 9a0c0ee..2f027b7 100644 --- a/src/serialization/vector.h +++ b/src/serialization/vector.h @@ -6,6 +6,11 @@ #include "serialization.h" +template