// Copyright (c) 2014-2016, The Monero Project // // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other // materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its contributors may be // used to endorse or promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #pragma once #include #include #include #include // memcmp #include #include "serialization/serialization.h" #include "serialization/variant.h" #include "serialization/vector.h" #include "serialization/binary_archive.h" #include "serialization/json_archive.h" #include "serialization/debug_archive.h" #include "serialization/crypto.h" #include "serialization/keyvalue_serialization.h" // eepe named serialization #include "string_tools.h" #include "cryptonote_config.h" #include "crypto/crypto.h" #include "crypto/hash.h" #include "misc_language.h" #include "tx_extra.h" #include "ringct/rctTypes.h" namespace cryptonote { const static crypto::hash null_hash = AUTO_VAL_INIT(null_hash); const static crypto::hash8 null_hash8 = AUTO_VAL_INIT(null_hash8); const static crypto::public_key null_pkey = AUTO_VAL_INIT(null_pkey); typedef std::vector ring_signature; /* outputs */ struct txout_to_script { std::vector keys; std::vector script; BEGIN_SERIALIZE_OBJECT() FIELD(keys) FIELD(script) END_SERIALIZE() }; struct txout_to_scripthash { crypto::hash hash; }; struct txout_to_key { txout_to_key() { } txout_to_key(const crypto::public_key &_key) : key(_key) { } crypto::public_key key; }; /* inputs */ struct txin_gen { size_t height; BEGIN_SERIALIZE_OBJECT() VARINT_FIELD(height) END_SERIALIZE() }; struct txin_to_script { crypto::hash prev; size_t prevout; std::vector sigset; BEGIN_SERIALIZE_OBJECT() FIELD(prev) VARINT_FIELD(prevout) FIELD(sigset) END_SERIALIZE() }; struct txin_to_scripthash { crypto::hash prev; size_t prevout; txout_to_script script; std::vector sigset; BEGIN_SERIALIZE_OBJECT() FIELD(prev) VARINT_FIELD(prevout) FIELD(script) FIELD(sigset) END_SERIALIZE() }; struct txin_to_key { uint64_t amount; std::vector key_offsets; crypto::key_image k_image; // double spending protection BEGIN_SERIALIZE_OBJECT() VARINT_FIELD(amount) FIELD(key_offsets) FIELD(k_image) END_SERIALIZE() }; typedef boost::variant txin_v; typedef boost::variant txout_target_v; //typedef std::pair out_t; struct tx_out { uint64_t amount; txout_target_v target; BEGIN_SERIALIZE_OBJECT() VARINT_FIELD(amount) FIELD(target) END_SERIALIZE() }; class 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) if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false; VARINT_FIELD(unlock_time) FIELD(vin) FIELD(vout) FIELD(extra) END_SERIALIZE() protected: transaction_prefix(){} }; class transaction: public transaction_prefix { public: std::vector > signatures; //count signatures always the same as inputs count rct::rctSig rct_signatures; transaction(); virtual ~transaction(); void set_null(); BEGIN_SERIALIZE_OBJECT() FIELDS(*static_cast(this)) if (version == 1) { ar.tag("signatures"); ar.begin_array(); PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures); bool signatures_not_expected = signatures.empty(); if (!signatures_not_expected && vin.size() != signatures.size()) return false; for (size_t i = 0; i < vin.size(); ++i) { size_t signature_size = get_signature_size(vin[i]); if (signatures_not_expected) { if (0 == signature_size) continue; else return false; } PREPARE_CUSTOM_VECTOR_SERIALIZATION(signature_size, signatures[i]); if (signature_size != signatures[i].size()) return false; FIELDS(signatures[i]); if (vin.size() - i > 1) ar.delimit_array(); } ar.end_array(); } else { FIELD(rct_signatures) if (rct_signatures.simple) { if (rct_signatures.mixRing.size() && rct_signatures.mixRing.size() != vin.size()) return false; } else { for (size_t i = 0; i < rct_signatures.mixRing.size(); ++i) { if (rct_signatures.mixRing[i].size() != vin.size()) return false; } } } END_SERIALIZE() private: static size_t get_signature_size(const txin_v& tx_in); }; inline transaction::transaction() { set_null(); } inline transaction::~transaction() { //set_null(); } inline void transaction::set_null() { version = 1; unlock_time = 0; vin.clear(); vout.clear(); extra.clear(); signatures.clear(); } inline size_t 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); } /************************************************************************/ /* */ /************************************************************************/ struct block_header { uint8_t major_version; uint8_t minor_version; // now used as a voting mechanism, rather than how this particular block is built uint64_t timestamp; crypto::hash prev_id; uint32_t nonce; BEGIN_SERIALIZE() VARINT_FIELD(major_version) VARINT_FIELD(minor_version) VARINT_FIELD(timestamp) FIELD(prev_id) FIELD(nonce) END_SERIALIZE() }; struct block: public block_header { transaction miner_tx; std::vector tx_hashes; BEGIN_SERIALIZE_OBJECT() FIELDS(*static_cast(this)) FIELD(miner_tx) FIELD(tx_hashes) END_SERIALIZE() }; /************************************************************************/ /* */ /************************************************************************/ struct account_public_address { crypto::public_key m_spend_public_key; crypto::public_key m_view_public_key; BEGIN_SERIALIZE_OBJECT() FIELD(m_spend_public_key) FIELD(m_view_public_key) END_SERIALIZE() BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_public_key) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_public_key) END_KV_SERIALIZE_MAP() }; struct keypair { crypto::public_key pub; crypto::secret_key sec; static inline keypair generate() { keypair k; generate_keys(k.pub, k.sec); return k; } }; //--------------------------------------------------------------- } BLOB_SERIALIZER(cryptonote::txout_to_key); BLOB_SERIALIZER(cryptonote::txout_to_scripthash); VARIANT_TAG(binary_archive, cryptonote::txin_gen, 0xff); VARIANT_TAG(binary_archive, cryptonote::txin_to_script, 0x0); VARIANT_TAG(binary_archive, cryptonote::txin_to_scripthash, 0x1); 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::transaction, 0xcc); VARIANT_TAG(binary_archive, cryptonote::block, 0xbb); VARIANT_TAG(json_archive, cryptonote::txin_gen, "gen"); VARIANT_TAG(json_archive, cryptonote::txin_to_script, "script"); VARIANT_TAG(json_archive, cryptonote::txin_to_scripthash, "scripthash"); 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::transaction, "tx"); VARIANT_TAG(json_archive, cryptonote::block, "block"); VARIANT_TAG(debug_archive, cryptonote::txin_gen, "gen"); VARIANT_TAG(debug_archive, cryptonote::txin_to_script, "script"); VARIANT_TAG(debug_archive, cryptonote::txin_to_scripthash, "scripthash"); 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::transaction, "tx"); VARIANT_TAG(debug_archive, cryptonote::block, "block");