diff options
Diffstat (limited to 'src/cryptonote_basic/cryptonote_basic.h')
-rw-r--r-- | src/cryptonote_basic/cryptonote_basic.h | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h new file mode 100644 index 000000000..da069a21a --- /dev/null +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -0,0 +1,397 @@ +// 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 <boost/variant.hpp> +#include <boost/functional/hash/hash.hpp> +#include <vector> +#include <cstring> // memcmp +#include <sstream> +#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<crypto::signature> ring_signature; + + + /* outputs */ + + struct txout_to_script + { + std::vector<crypto::public_key> keys; + std::vector<uint8_t> 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<uint8_t> 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<uint8_t> sigset; + + BEGIN_SERIALIZE_OBJECT() + FIELD(prev) + VARINT_FIELD(prevout) + FIELD(script) + FIELD(sigset) + END_SERIALIZE() + }; + + struct txin_to_key + { + uint64_t amount; + std::vector<uint64_t> 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_gen, txin_to_script, txin_to_scripthash, txin_to_key> txin_v; + + typedef boost::variant<txout_to_script, txout_to_scripthash, txout_to_key> txout_target_v; + + //typedef std::pair<uint64_t, txout> 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<txin_v> vin; + std::vector<tx_out> vout; + //extra + std::vector<uint8_t> 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() + + public: + transaction_prefix(){} + }; + + class transaction: public transaction_prefix + { + public: + std::vector<std::vector<crypto::signature> > 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<transaction_prefix *>(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 + { + ar.tag("rct_signatures"); + if (!vin.empty()) + { + ar.begin_object(); + bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size()); + if (!r || !ar.stream().good()) return false; + ar.end_object(); + if (rct_signatures.type != rct::RCTTypeNull) + { + ar.tag("rctsig_prunable"); + ar.begin_object(); + r = rct_signatures.p.serialize_rctsig_prunable(ar, rct_signatures.type, vin.size(), vout.size(), + vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0); + if (!r || !ar.stream().good()) return false; + ar.end_object(); + } + } + } + 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(); + rct_signatures.type = rct::RCTTypeNull; + } + + inline + size_t transaction::get_signature_size(const txin_v& tx_in) + { + struct txin_signature_size_visitor : public boost::static_visitor<size_t> + { + 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<crypto::hash> tx_hashes; + + BEGIN_SERIALIZE_OBJECT() + FIELDS(*static_cast<block_header *>(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"); |