diff --git a/builds/msvc-140/bitcoin/bitcoin.vcxproj b/builds/msvc-140/bitcoin/bitcoin.vcxproj index ade9b8d18..30ad9c4d2 100644 --- a/builds/msvc-140/bitcoin/bitcoin.vcxproj +++ b/builds/msvc-140/bitcoin/bitcoin.vcxproj @@ -32,6 +32,7 @@ + @@ -166,6 +167,7 @@ + @@ -357,6 +359,7 @@ + diff --git a/builds/msvc-140/bitcoin/bitcoin.vcxproj.filters b/builds/msvc-140/bitcoin/bitcoin.vcxproj.filters index d790a3178..97c6102f4 100644 --- a/builds/msvc-140/bitcoin/bitcoin.vcxproj.filters +++ b/builds/msvc-140/bitcoin/bitcoin.vcxproj.filters @@ -578,6 +578,9 @@ Source Files\chain\attachment\asset + + Source Files\chain + @@ -1147,6 +1150,9 @@ Header Files\chain\attachment\asset + + Header Files + @@ -1203,5 +1209,8 @@ Header Files\impl\utility + + Header Files\impl + \ No newline at end of file diff --git a/include/metaverse/bitcoin/base_primary.hpp b/include/metaverse/bitcoin/base_primary.hpp new file mode 100644 index 000000000..91435de71 --- /dev/null +++ b/include/metaverse/bitcoin/base_primary.hpp @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2011-2015 metaverse developers (see AUTHORS) + * + * This file is part of mvs-node. + * + * metaverse is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License with + * additional permissions to the one published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. For more information see LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef MVS_BASE_PRIMARY_HPP +#define MVS_BASE_PRIMARY_HPP + +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { + +template +class base_primary +{ +public: + T& Instance(); + const T& Instance() const; + // + template + static T factory_from_data(const data_chunk &data, Args... args); + + template + static T factory_from_data(std::istream& stream, Args... args); + + template + static T factory_from_data(reader& source, Args... args); + + template + bool from_data(const data_chunk& data, Args... args); + + template + bool from_data(std::istream& stream, Args... args); + + template + bool from_data(reader& source, Args... args); + + data_chunk to_data() const; + + template::type, + typename std::enable_if< (!std::is_base_of::value + && !std::is_base_of::value )>::type* = nullptr, typename... Args> + data_chunk to_data(T1_&& t , Args... args) const; + + template + void to_data(std::ostream& stream, Args... args) const; + + template + void to_data(writer& sink, Args... args) const; + +private: + base_primary(){} + friend T; +}; + + + +} // namespace libbitcoin + +#include + +#endif + diff --git a/include/metaverse/bitcoin/chain/attachment/account/account.hpp b/include/metaverse/bitcoin/chain/attachment/account/account.hpp index 2f238499f..b68538c04 100644 --- a/include/metaverse/bitcoin/chain/attachment/account/account.hpp +++ b/include/metaverse/bitcoin/chain/attachment/account/account.hpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace libbitcoin { namespace chain { @@ -119,23 +120,17 @@ class BC_API account_multisig }; class BC_API account + : public base_primary { public: account(); account(const std::string& name, const std::string& mnemonic, const hash_digest& passwd, uint32_t hd_index, uint8_t priority, uint8_t status, uint8_t type); - static account factory_from_data(const data_chunk& data); - static account factory_from_data(std::istream& stream); - static account factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; bool is_valid() const; void reset(); diff --git a/include/metaverse/bitcoin/chain/attachment/account/account_address.hpp b/include/metaverse/bitcoin/chain/attachment/account/account_address.hpp index 3fae7c7c5..c9bf69775 100644 --- a/include/metaverse/bitcoin/chain/attachment/account/account_address.hpp +++ b/include/metaverse/bitcoin/chain/attachment/account/account_address.hpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace libbitcoin { namespace chain { @@ -50,7 +51,8 @@ enum account_address_status : uint8_t stealth_addr = 3 // stealth address }; -class BC_API account_address +class BC_API account_address + : public base_primary { public: typedef std::vector list; @@ -59,17 +61,10 @@ class BC_API account_address const std::string& pub_key, uint32_t hd_index, uint64_t balance, const std::string& alias, const std::string& address, uint8_t status); account_address(const account_address& other); - static account_address factory_from_data(const data_chunk& data); - static account_address factory_from_data(std::istream& stream); - static account_address factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; #ifdef MVS_DEBUG std::string to_string() ; #endif diff --git a/include/metaverse/bitcoin/chain/attachment/asset/asset.hpp b/include/metaverse/bitcoin/chain/attachment/asset/asset.hpp index 8033bedb7..b7873fbf0 100644 --- a/include/metaverse/bitcoin/chain/attachment/asset/asset.hpp +++ b/include/metaverse/bitcoin/chain/attachment/asset/asset.hpp @@ -31,6 +31,7 @@ #include #include #include +#include using namespace libbitcoin::chain; @@ -43,6 +44,7 @@ namespace libbitcoin { namespace chain { class BC_API asset + : public base_primary { public: enum class asset_status : uint32_t @@ -56,17 +58,10 @@ class BC_API asset asset(); asset(uint32_t status, const asset_detail& detail); asset(uint32_t status, const asset_transfer& detail); - static asset factory_from_data(const data_chunk& data); - static asset factory_from_data(std::istream& stream); - static asset factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string() const; bool is_valid_type() const; bool is_valid() const; diff --git a/include/metaverse/bitcoin/chain/attachment/asset/asset_cert.hpp b/include/metaverse/bitcoin/chain/attachment/asset/asset_cert.hpp index 863cd3493..1b9d7784d 100644 --- a/include/metaverse/bitcoin/chain/attachment/asset/asset_cert.hpp +++ b/include/metaverse/bitcoin/chain/attachment/asset/asset_cert.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #define ASSET_CERT_STATUS2UINT32(kd) (static_cast::type>(kd)) @@ -59,6 +60,7 @@ namespace asset_cert_ns { } class BC_API asset_cert + : public base_primary { public: typedef std::vector list; @@ -79,16 +81,8 @@ class BC_API asset_cert bool is_valid() const; bool operator< (const asset_cert& other) const; - static asset_cert factory_from_data(const data_chunk& data); - static asset_cert factory_from_data(std::istream& stream); - static asset_cert factory_from_data(reader& source); - - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string() const; uint64_t serialized_size() const; diff --git a/include/metaverse/bitcoin/chain/attachment/asset/asset_detail.hpp b/include/metaverse/bitcoin/chain/attachment/asset/asset_detail.hpp index 531902482..95f331f82 100644 --- a/include/metaverse/bitcoin/chain/attachment/asset/asset_detail.hpp +++ b/include/metaverse/bitcoin/chain/attachment/asset/asset_detail.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "asset_cert.hpp" namespace libbitcoin { @@ -48,6 +49,7 @@ BC_CONSTEXPR size_t ASSET_DETAIL_FIX_SIZE = ASSET_DETAIL_SYMBOL_FIX_SIZE + ASSET_DETAIL_DESCRIPTION_FIX_SIZE; class BC_API asset_detail + : public base_primary { public: typedef std::vector list; @@ -61,16 +63,9 @@ class BC_API asset_detail uint8_t decimal_number, uint8_t threshold, const std::string& issuer, const std::string& address, const std::string& description); - static asset_detail factory_from_data(const data_chunk& data); - static asset_detail factory_from_data(std::istream& stream); - static asset_detail factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; bool operator< (const asset_detail& other) const; std::string to_string() const; diff --git a/include/metaverse/bitcoin/chain/attachment/asset/asset_mit.hpp b/include/metaverse/bitcoin/chain/attachment/asset/asset_mit.hpp index 527af30c6..b473ebe93 100644 --- a/include/metaverse/bitcoin/chain/attachment/asset/asset_mit.hpp +++ b/include/metaverse/bitcoin/chain/attachment/asset/asset_mit.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #define MIT_STATUS2UINT32(kd) (static_cast::type>(kd)) @@ -54,6 +55,7 @@ BC_CONSTEXPR size_t ASSET_MIT_TRANSFER_FIX_SIZE = ( BC_CONSTEXPR size_t ASSET_MIT_INFO_FIX_SIZE = 4 + 4 + 64 + ASSET_MIT_TRANSFER_FIX_SIZE; class BC_API asset_mit + : public base_primary { public: typedef std::vector list; @@ -74,17 +76,9 @@ class BC_API asset_mit bool is_valid() const; bool operator< (const asset_mit& other) const; - static asset_mit factory_from_data(const data_chunk& data); - static asset_mit factory_from_data(std::istream& stream); - static asset_mit factory_from_data(reader& source); - - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; data_chunk to_short_data() const; - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; std::string to_string() const; uint64_t serialized_size() const; diff --git a/include/metaverse/bitcoin/chain/attachment/asset/asset_transfer.hpp b/include/metaverse/bitcoin/chain/attachment/asset/asset_transfer.hpp index c9efd8f0c..178a56582 100644 --- a/include/metaverse/bitcoin/chain/attachment/asset/asset_transfer.hpp +++ b/include/metaverse/bitcoin/chain/attachment/asset/asset_transfer.hpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include namespace libbitcoin { namespace chain { @@ -81,21 +81,15 @@ struct asset_deposited_balance { }; class BC_API asset_transfer + : public base_primary { public: asset_transfer(); asset_transfer(const std::string& symbol, uint64_t quantity); - static asset_transfer factory_from_data(const data_chunk& data); - static asset_transfer factory_from_data(std::istream& stream); - static asset_transfer factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string() const; diff --git a/include/metaverse/bitcoin/chain/attachment/asset/blockchain_asset.hpp b/include/metaverse/bitcoin/chain/attachment/asset/blockchain_asset.hpp index c49f30bdf..6eaec05bf 100644 --- a/include/metaverse/bitcoin/chain/attachment/asset/blockchain_asset.hpp +++ b/include/metaverse/bitcoin/chain/attachment/asset/blockchain_asset.hpp @@ -23,33 +23,29 @@ #include #include #include +#include #include #include #include #include #include +#include namespace libbitcoin { namespace chain { class BC_API blockchain_asset + : public base_primary { public: typedef std::vector list; blockchain_asset(); blockchain_asset(uint32_t version, const output_point& tx_point, uint64_t height, const asset_detail& asset); - static blockchain_asset factory_from_data(const data_chunk& data); - static blockchain_asset factory_from_data(std::istream& stream); - static blockchain_asset factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; #ifdef MVS_DEBUG std::string to_string() const; diff --git a/include/metaverse/bitcoin/chain/attachment/attachment.hpp b/include/metaverse/bitcoin/chain/attachment/attachment.hpp index 21f02ef39..d5dafb4b1 100644 --- a/include/metaverse/bitcoin/chain/attachment/attachment.hpp +++ b/include/metaverse/bitcoin/chain/attachment/attachment.hpp @@ -34,6 +34,7 @@ #include #include #include +#include using namespace libbitcoin::chain; #define TYPE2UINT32(kd) (static_cast::type>(kd)) @@ -53,6 +54,7 @@ namespace libbitcoin { namespace chain { class BC_API attachment + : public base_primary { public: @@ -86,17 +88,10 @@ class BC_API attachment : type(type), version(version), attach(attach_data) {} - static attachment factory_from_data(const data_chunk& data); - static attachment factory_from_data(std::istream& stream); - static attachment factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string() const; bool is_valid() const; bool is_valid_type() const; diff --git a/include/metaverse/bitcoin/chain/attachment/did/blockchain_did.hpp b/include/metaverse/bitcoin/chain/attachment/did/blockchain_did.hpp index 8d487de01..c98f47ce8 100644 --- a/include/metaverse/bitcoin/chain/attachment/did/blockchain_did.hpp +++ b/include/metaverse/bitcoin/chain/attachment/did/blockchain_did.hpp @@ -23,16 +23,19 @@ #include #include #include +#include #include #include #include #include #include +#include namespace libbitcoin { namespace chain { class BC_API blockchain_did + : public base_primary { public: enum did_address_type: uint32_t @@ -45,17 +48,10 @@ class BC_API blockchain_did blockchain_did(); blockchain_did( uint32_t version, const output_point& tx_point, uint64_t height, uint32_t status, const did_detail& did); - static blockchain_did factory_from_data(const data_chunk& data); - static blockchain_did factory_from_data(std::istream& stream); - static blockchain_did factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; #ifdef MVS_DEBUG std::string to_string() const; diff --git a/include/metaverse/bitcoin/chain/attachment/did/did.hpp b/include/metaverse/bitcoin/chain/attachment/did/did.hpp index 5b22073cd..3a7811d8f 100644 --- a/include/metaverse/bitcoin/chain/attachment/did/did.hpp +++ b/include/metaverse/bitcoin/chain/attachment/did/did.hpp @@ -30,6 +30,7 @@ #include #include #include +#include using namespace libbitcoin::chain; @@ -42,6 +43,7 @@ namespace libbitcoin { namespace chain { class BC_API did + : public base_primary { public: enum class did_status : uint32_t @@ -53,17 +55,10 @@ class BC_API did did(); did(uint32_t status, const did_detail& detail); - static did factory_from_data(const data_chunk& data); - static did factory_from_data(std::istream& stream); - static did factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string() const; bool is_valid_type() const; bool is_valid() const; diff --git a/include/metaverse/bitcoin/chain/attachment/did/did_detail.hpp b/include/metaverse/bitcoin/chain/attachment/did/did_detail.hpp index 8ec98f72d..0158b419d 100644 --- a/include/metaverse/bitcoin/chain/attachment/did/did_detail.hpp +++ b/include/metaverse/bitcoin/chain/attachment/did/did_detail.hpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace libbitcoin { namespace chain { @@ -39,6 +40,7 @@ BC_CONSTEXPR size_t DID_DETAIL_FIX_SIZE = DID_DETAIL_SYMBOL_FIX_SIZE + DID_DETAIL_ADDRESS_FIX_SIZE; class BC_API did_detail + : public base_primary { public: typedef std::vector list; @@ -53,17 +55,10 @@ class BC_API did_detail did_detail(); did_detail(const std::string& symbol, const std::string& address); - static did_detail factory_from_data(const data_chunk& data); - static did_detail factory_from_data(std::istream& stream); - static did_detail factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); static std::string get_blackhole_did_symbol(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; bool operator< (const did_detail& other) const; std::string to_string() const; diff --git a/include/metaverse/bitcoin/chain/attachment/etp/etp.hpp b/include/metaverse/bitcoin/chain/attachment/etp/etp.hpp index 7e46f0cb9..5d47fce57 100644 --- a/include/metaverse/bitcoin/chain/attachment/etp/etp.hpp +++ b/include/metaverse/bitcoin/chain/attachment/etp/etp.hpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace libbitcoin { namespace chain { @@ -34,21 +35,15 @@ namespace chain { BC_CONSTEXPR size_t ETP_FIX_SIZE = 8; class BC_API etp + : public base_primary { public: etp(); etp(uint64_t value); - static etp factory_from_data(const data_chunk& data); - static etp factory_from_data(std::istream& stream); - static etp factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string() const; bool is_valid() const; void reset(); diff --git a/include/metaverse/bitcoin/chain/attachment/etp/etp_award.hpp b/include/metaverse/bitcoin/chain/attachment/etp/etp_award.hpp index 758cfb8a4..14dc4e466 100644 --- a/include/metaverse/bitcoin/chain/attachment/etp/etp_award.hpp +++ b/include/metaverse/bitcoin/chain/attachment/etp/etp_award.hpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace libbitcoin { namespace chain { @@ -34,21 +35,15 @@ namespace chain { BC_CONSTEXPR size_t ETP_AWARD_FIX_SIZE = 8; class BC_API etp_award + : public base_primary { public: etp_award(); etp_award(uint64_t height); - static etp_award factory_from_data(const data_chunk& data); - static etp_award factory_from_data(std::istream& stream); - static etp_award factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string() const; bool is_valid() const; void reset(); diff --git a/include/metaverse/bitcoin/chain/attachment/message/message.hpp b/include/metaverse/bitcoin/chain/attachment/message/message.hpp index 1c7eee6c8..c3aae7469 100644 --- a/include/metaverse/bitcoin/chain/attachment/message/message.hpp +++ b/include/metaverse/bitcoin/chain/attachment/message/message.hpp @@ -27,29 +27,24 @@ #include #include #include +#include namespace libbitcoin { namespace chain { BC_CONSTEXPR size_t BLOCKCHAIN_MESSAGE_FIX_SIZE = 256; class BC_API blockchain_message + : public base_primary { public: //BC_CONSTEXPR static size_t blockchain_message_FIX_SIZE = 64; blockchain_message(); blockchain_message(std::string content); - static blockchain_message factory_from_data(const data_chunk& data); - static blockchain_message factory_from_data(std::istream& stream); - static blockchain_message factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string() const; bool is_valid() const; void reset(); diff --git a/include/metaverse/bitcoin/chain/block.hpp b/include/metaverse/bitcoin/chain/block.hpp index 738784aa7..0950dd9dd 100644 --- a/include/metaverse/bitcoin/chain/block.hpp +++ b/include/metaverse/bitcoin/chain/block.hpp @@ -32,11 +32,13 @@ #include #include #include +#include namespace libbitcoin { namespace chain { class BC_API block + : public base_primary { public: typedef std::vector list; @@ -44,12 +46,6 @@ class BC_API block typedef std::vector ptr_list; typedef std::vector indexes; - static block factory_from_data(const data_chunk& data, - bool with_transaction_count = true); - static block factory_from_data(std::istream& stream, - bool with_transaction_count = true); - static block factory_from_data(reader& source, - bool with_transaction_count = true); static hash_digest generate_merkle_root( const transaction::list& transactions); static block genesis_mainnet(); @@ -68,12 +64,8 @@ class BC_API block block& operator=(block&& other); void operator=(const block&) = delete; - bool from_data(const data_chunk& data, bool with_transaction_count = true); - bool from_data(std::istream& stream, bool with_transaction_count = true); - bool from_data(reader& source, bool with_transaction_count = true); - data_chunk to_data(bool with_transaction_count = true) const; - void to_data(std::ostream& stream, bool with_transaction_count = true) const; - void to_data(writer& sink, bool with_transaction_count = true) const; + bool from_data_t(reader& source, bool with_transaction_count = true); + void to_data_t(writer& sink, bool with_transaction_count = true) const; bool is_valid() const; void reset(); uint64_t serialized_size(bool with_transaction_count = true) const; diff --git a/include/metaverse/bitcoin/chain/business_data.hpp b/include/metaverse/bitcoin/chain/business_data.hpp index 4d6ad2292..6dd606668 100644 --- a/include/metaverse/bitcoin/chain/business_data.hpp +++ b/include/metaverse/bitcoin/chain/business_data.hpp @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -34,6 +37,7 @@ #include #include #include +#include #define KIND2UINT16(kd) (static_cast::type>(kd)) // 0 -- unspent 1 -- confirmed 2 -- local asset not issued @@ -68,6 +72,7 @@ enum business_status : uint8_t }; class BC_API business_data + : public base_primary { public: typedef boost::variant< @@ -80,17 +85,10 @@ class BC_API business_data blockchain_message, did_detail> business_data_type; - static business_data factory_from_data(const data_chunk& data); - static business_data factory_from_data(std::istream& stream); - static business_data factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() ; - void to_data(std::ostream& stream) ; - void to_data(writer& sink); + bool from_data_t(reader& source); + void to_data_t(writer& sink); #if MVS_DEBUG std::string to_string() ; #endif diff --git a/include/metaverse/bitcoin/chain/header.hpp b/include/metaverse/bitcoin/chain/header.hpp index 70a6b6234..308287f08 100644 --- a/include/metaverse/bitcoin/chain/header.hpp +++ b/include/metaverse/bitcoin/chain/header.hpp @@ -39,6 +39,7 @@ #include #include #include +#include namespace libbitcoin { using bigint = boost::multiprecision::number>; @@ -49,20 +50,15 @@ namespace libbitcoin { namespace chain { class BC_API header + : public base_primary
{ public: typedef std::vector
list; typedef std::shared_ptr
ptr; typedef std::vector ptr_list; - static header factory_from_data(const data_chunk& data, - bool with_transaction_count = true); - static header factory_from_data(std::istream& stream, - bool with_transaction_count = true); - static header factory_from_data(reader& source, - bool with_transaction_count = true); static uint64_t satoshi_fixed_size_without_transaction_count(); - + header(); header(const header& other); header(uint32_t version, const hash_digest& previous_block_hash, @@ -80,12 +76,8 @@ class BC_API header // TODO: eliminate blockchain transaction copies and then delete this. header& operator=(const header& other) /*= delete*/; - bool from_data(const data_chunk& data, bool with_transaction_count = true); - bool from_data(std::istream& stream, bool with_transaction_count = true); - bool from_data(reader& source, bool with_transaction_count = true); - data_chunk to_data(bool with_transaction_count = true) const; - void to_data(std::ostream& stream, bool with_transaction_count = true) const; - void to_data(writer& sink, bool with_transaction_count = true) const; + bool from_data_t(reader& source, bool with_transaction_count = true); + void to_data_t(writer& sink, bool with_transaction_count = true) const; hash_digest hash() const; bool is_valid() const; void reset(); diff --git a/include/metaverse/bitcoin/chain/history.hpp b/include/metaverse/bitcoin/chain/history.hpp index 5dc8fed45..9118755a0 100644 --- a/include/metaverse/bitcoin/chain/history.hpp +++ b/include/metaverse/bitcoin/chain/history.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace libbitcoin { namespace chain { diff --git a/include/metaverse/bitcoin/chain/input.hpp b/include/metaverse/bitcoin/chain/input.hpp index b3f440406..bbcd44ac7 100644 --- a/include/metaverse/bitcoin/chain/input.hpp +++ b/include/metaverse/bitcoin/chain/input.hpp @@ -24,36 +24,46 @@ #include #include #include +#include #include #include #include #include #include #include +#include namespace libbitcoin { namespace chain { class BC_API input + : public base_primary { public: typedef std::vector list; - static input factory_from_data(const data_chunk& data); - static input factory_from_data(std::istream& stream); - static input factory_from_data(reader& source); + + input(); + input(input&& other); + input(const input& other); + + input(output_point&& previous_output, chain::script&& script, uint32_t sequence); + input(const output_point& previous_output, const chain::script& script, const uint32_t& sequence); + + input& operator=(input&& other); + input& operator=(const input& other); + static uint64_t satoshi_fixed_size(); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string(uint32_t flags) const; bool is_valid() const; void reset(); + bool is_final() const; + bool is_locked(size_t block_height, uint32_t median_time_past) const; + uint64_t serialized_size() const; std::string get_script_address() const; diff --git a/include/metaverse/bitcoin/chain/output.hpp b/include/metaverse/bitcoin/chain/output.hpp index 410997977..b3c1f56c1 100644 --- a/include/metaverse/bitcoin/chain/output.hpp +++ b/include/metaverse/bitcoin/chain/output.hpp @@ -32,6 +32,7 @@ #include #include // added for asset issue/transfer #include +#include // forward declaration namespace libbitcoin { @@ -44,23 +45,25 @@ namespace libbitcoin { namespace chain { class BC_API output + : public base_primary { public: + output(); + output(output&& other); + output(const output& other); + + output(uint64_t&& value, chain::script&& script, attachment&& attach_data); + output(const uint64_t& value, const chain::script& script, const attachment& attach_data); + output& operator=(output&& other); + output& operator=(const output& other); typedef std::vector list; - static output factory_from_data(const data_chunk& data); - static output factory_from_data(std::istream& stream); - static output factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); static bool is_valid_symbol(const std::string& symbol, uint32_t tx_version); static bool is_valid_did_symbol(const std::string& symbol, bool check_sensitive = false); static bool is_valid_mit_symbol(const std::string& symbol, bool check_sensitive = false); - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string(uint32_t flags) const; bool is_valid() const; code check_attachment_address(bc::blockchain::block_chain_impl& chain) const; @@ -107,13 +110,6 @@ class BC_API output attachment attach_data; // added for asset issue/transfer }; -struct BC_API output_info -{ - typedef std::vector list; - - output_point point; - uint64_t value; -}; } // namespace chain } // namespace libbitcoin diff --git a/include/metaverse/bitcoin/chain/output_point.hpp b/include/metaverse/bitcoin/chain/output_point.hpp new file mode 100644 index 000000000..2ee77c595 --- /dev/null +++ b/include/metaverse/bitcoin/chain/output_point.hpp @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS) + * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS) + * + * This file is part of metaverse. + * + * metaverse is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License with + * additional permissions to the one published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. For more information see LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef MVS_CHAIN_OUTPUT_POINT_HPP +#define MVS_CHAIN_OUTPUT_POINT_HPP + +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace chain { + +class BC_API output_point + : public point +{ +public: + + // THIS IS FOR LIBRARY USE ONLY, DO NOT CREATE A DEPENDENCY ON IT. + struct validation + { + /// Must be false if confirmed is false. + /// output spender's tx->block is indexed or confirmed not above fork. + bool spent = false; + + /// The output->tx is confirmed|indexed, fork point dependent. + bool confirmed = false; + + /// The previous output is a coinbase (must verify spender maturity). + bool coinbase = false; + + /// Prevout height is used for coinbase maturity and relative lock time. + size_t height = 0; + + /// Median time past is used for relative lock time. + uint32_t median_time_past = 0; + + /// The output cache contains the output referenced by the input point. + /// If the cache.value is not_found (default) the output is not found. + output cache; + }; + + // Constructors. + //------------------------------------------------------------------------- + + output_point(); + + output_point(point&& other); + output_point(const point& value); + + output_point(output_point&& other); + output_point(const output_point& other); + + output_point(hash_digest&& hash, uint32_t index); + output_point(const hash_digest& hash, uint32_t index); + + // Operators. + //------------------------------------------------------------------------- + // This class is move assignable and copy assignable. + + output_point& operator=(point&& other); + output_point& operator=(const point&); + output_point& operator=(output_point&& other); + output_point& operator=(const output_point&); + + bool operator==(const point& other) const; + bool operator!=(const point& other) const; + bool operator==(const output_point& other) const; + bool operator!=(const output_point& other) const; + + // Deserialization. + //------------------------------------------------------------------------- + + static output_point factory(const data_chunk& data); + static output_point factory(std::istream& stream); + static output_point factory(reader& source); + + // Validation. + //------------------------------------------------------------------------- + + /// True if cached previous output is mature enough to spend from height. + bool is_mature(size_t height) const; + + // THIS IS FOR LIBRARY USE ONLY, DO NOT CREATE A DEPENDENCY ON IT. + mutable validation metadata; + +protected: + // So that input may call reset from its own. + friend class input; +}; + +struct BC_API output_info +{ + typedef std::vector list; + + output_point point; + uint64_t value; +}; + +struct BC_API points_info +{ + output_point::list points; + uint64_t change; +}; + + +} // namespace chain +} // namespace libbitcoin + +#endif diff --git a/include/metaverse/bitcoin/chain/point.hpp b/include/metaverse/bitcoin/chain/point.hpp index 6ec561acd..d2b95dcbc 100644 --- a/include/metaverse/bitcoin/chain/point.hpp +++ b/include/metaverse/bitcoin/chain/point.hpp @@ -32,30 +32,49 @@ #include #include #include +#include namespace libbitcoin { namespace chain { class BC_API point + : public base_primary { public: typedef std::vector list; typedef std::vector indexes; - static point factory_from_data(const data_chunk& data); - static point factory_from_data(std::istream& stream); - static point factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); + point(); + + point(point&& other); + point(const point& other); + + point(hash_digest&& hash, uint32_t index); + point(const hash_digest& hash, uint32_t index); + + virtual ~point(); + + + // Operators. + //------------------------------------------------------------------------- + + /// This class is move assignable and copy assignable. + point& operator=(point&& other); + point& operator=(const point& other); + + bool operator<(const point& other) const; + bool operator==(const point& other) const; + bool operator!=(const point& other) const; + uint64_t checksum() const; bool is_null() const; - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; + std::string to_string() const; bool is_valid() const; void reset(); @@ -68,19 +87,14 @@ class BC_API point uint32_t index; }; -BC_API bool operator==(const point& left, const point& right); -BC_API bool operator!=(const point& left, const point& right); +// BC_API bool operator==(const point& left, const point& right); +// BC_API bool operator!=(const point& left, const point& right); -BC_API bool operator<(const point& left, const point& right); +// BC_API bool operator<(const point& left, const point& right); typedef point input_point; -typedef point output_point; +// typedef point output_point; -struct BC_API points_info -{ - output_point::list points; - uint64_t change; -}; } // namespace chain } // namespace libbitcoin diff --git a/include/metaverse/bitcoin/chain/script/opcode.hpp b/include/metaverse/bitcoin/chain/script/opcode.hpp index eafceb142..4caa6c8c4 100644 --- a/include/metaverse/bitcoin/chain/script/opcode.hpp +++ b/include/metaverse/bitcoin/chain/script/opcode.hpp @@ -135,9 +135,12 @@ enum class opcode : uint8_t checkmultisig = 174, checkmultisigverify = 175, op_nop1 = 176, - checklocktimeverify = 177, // op_nop2 - checkattenuationverify = 178, // op_nop3 + op_nop2 = 177, + checklocktimeverify = op_nop2, + op_nop3 = 178, + checkattenuationverify = op_nop3, op_nop4 = 179, + checksequenceverify = op_nop4, op_nop5 = 180, op_nop6 = 181, op_nop7 = 182, @@ -170,6 +173,9 @@ enum script_context : uint32_t /// nop3 becomes check attenuation verify attenuation_enabled = 1 << 5, + /// nop4 becomes check sequence verify + bip112_enabled = 1 << 6, + all_enabled = 0xffffffff }; diff --git a/include/metaverse/bitcoin/chain/transaction.hpp b/include/metaverse/bitcoin/chain/transaction.hpp index 12fd39839..92b1311f9 100644 --- a/include/metaverse/bitcoin/chain/transaction.hpp +++ b/include/metaverse/bitcoin/chain/transaction.hpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace libbitcoin { namespace chain { @@ -46,6 +47,7 @@ enum transaction_version { }; class BC_API transaction + : public base_primary { public: typedef std::vector list; @@ -53,9 +55,6 @@ class BC_API transaction typedef std::vector ptr_list; typedef std::vector indexes; - static transaction factory_from_data(const data_chunk& data); - static transaction factory_from_data(std::istream& stream); - static transaction factory_from_data(reader& source); static uint64_t satoshi_fixed_size(); transaction(); @@ -73,12 +72,8 @@ class BC_API transaction // TODO: eliminate blockchain transaction copies and then delete this. transaction& operator=(const transaction& other) /*= delete*/; - bool from_data(const data_chunk& data); - bool from_data(std::istream& stream); - bool from_data(reader& source); - data_chunk to_data() const; - void to_data(std::ostream& stream) const; - void to_data(writer& sink) const; + bool from_data_t(reader& source); + void to_data_t(writer& sink) const; std::string to_string(uint32_t flags) const; bool is_valid() const; void reset(); @@ -88,6 +83,7 @@ class BC_API transaction hash_digest hash(uint32_t sighash_type) const; bool is_coinbase() const; bool is_final(uint64_t block_height, uint32_t block_time) const; + bool is_locked(size_t block_height, uint32_t median_time_past) const; bool is_locktime_conflict() const; uint64_t total_output_value() const; uint64_t serialized_size() const; diff --git a/include/metaverse/bitcoin/constants.hpp b/include/metaverse/bitcoin/constants.hpp index 19ca77991..174435077 100644 --- a/include/metaverse/bitcoin/constants.hpp +++ b/include/metaverse/bitcoin/constants.hpp @@ -64,6 +64,15 @@ BC_CONSTEXPR uint32_t min_fee_percentage_to_miner = 20; // otherwise as UNIX timestamp. [Tue Nov 5 00:53:20 1985 UTC] BC_CONSTEXPR uint32_t locktime_threshold = 500000000; +// Relative locktime constants. +//----------------------------------------------------------------------------- + +BC_CONSTEXPR size_t relative_locktime_min_version = 2; +BC_CONSTEXPR size_t relative_locktime_seconds_shift = 9; +BC_CONSTEXPR uint32_t relative_locktime_mask = 0x0000ffff; +BC_CONSTEXPR uint32_t relative_locktime_disabled = 0x80000000; +BC_CONSTEXPR uint32_t relative_locktime_time_locked = 0x00400000; + BC_CONSTFUNC uint64_t max_money_recursive(uint64_t current) { return (current > 0) ? current + max_money_recursive(current >> 1) : 0; diff --git a/include/metaverse/bitcoin/error.hpp b/include/metaverse/bitcoin/error.hpp index eed4ce919..496c40e7d 100644 --- a/include/metaverse/bitcoin/error.hpp +++ b/include/metaverse/bitcoin/error.hpp @@ -175,7 +175,9 @@ enum error_code_t mit_exist, mit_register_error, mit_symbol_invalid, - mit_not_exist, + mit_not_exist, // 90 + + sequence_locked, }; diff --git a/include/metaverse/bitcoin/impl/base_primary.ipp b/include/metaverse/bitcoin/impl/base_primary.ipp new file mode 100644 index 000000000..87e52c61a --- /dev/null +++ b/include/metaverse/bitcoin/impl/base_primary.ipp @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2011-2015 libbitcoin developers (see AUTHORS) + * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS) + * + * This file is part of metaverse. + * + * metaverse is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License with + * additional permissions to the one published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. For more information see LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#ifndef MVS_BASE_PRIMARY_IPP +#define MVS_BASE_PRIMARY_IPP + +namespace libbitcoin { + +template +T& base_primary::Instance(){ + return static_cast(*this); +} + +template +const T& base_primary::Instance() const { + return static_cast(*this); +} + +template +template +T base_primary::factory_from_data(const data_chunk &data, Args... args){ + T instance; + instance.from_data(data, std::forward(args)...); + return instance; +} + +template +template +T base_primary::factory_from_data(std::istream& stream, Args... args){ + T instance; + instance.from_data(stream, std::forward(args)...); + return instance; +} + +template +template +T base_primary::factory_from_data(reader& source, Args... args){ + T instance; + instance.from_data(source, std::forward(args)...); + return instance; +} + +template +template +bool base_primary::from_data(const data_chunk& data, Args... args){ + data_source istream(data); + return from_data(istream, std::forward(args)...); +} + +template +template +bool base_primary::from_data(std::istream& stream, Args... args){ + istream_reader source(stream); + return from_data(source, std::forward(args)...); +} + +template +template +bool base_primary::from_data(reader& source, Args... args){ + return Instance().from_data_t(source, std::forward(args)...); +} + +template +data_chunk base_primary::to_data() const{ + data_chunk data; + data_sink ostream(data); + to_data(ostream); + ostream.flush(); + return data; +} + +template +template::value +&& !std::is_base_of::value )>::type*, typename... Args> +data_chunk base_primary::to_data(T1_&& t, Args... args) const{ + data_chunk data; + data_sink ostream(data); + to_data(ostream, std::forward(t), std::forward(args)...); + ostream.flush(); + return data; +} + + +template +template +void base_primary::to_data(std::ostream& stream, Args... args) const{ + ostream_writer sink(stream); + to_data(sink, std::forward(args)...); +} + +template +template< typename... Args> +void base_primary::to_data(writer& sink, Args... args) const{ + Instance().to_data_t(sink, std::forward(args)...); +} + +} // namespace libbitcoin + +#endif + diff --git a/include/metaverse/bitcoin/math/limits.hpp b/include/metaverse/bitcoin/math/limits.hpp new file mode 100644 index 000000000..3462071e4 --- /dev/null +++ b/include/metaverse/bitcoin/math/limits.hpp @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2011-2017 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef MVS_LIMITS_HPP +#define MVS_LIMITS_HPP + +#include +#include +#include +#include +#include + +namespace libbitcoin { + +#define IF(T) std::enable_if +#define SIGN(T) std::is_signed::value +#define UNSIGN(T) std::is_unsigned::value + +#define SIGNED(A) IF(SIGN(A)) +#define UNSIGNED(A) IF(UNSIGN(A)) +#define SIGNED_SIGNED(A, B) IF(SIGN(A) && SIGN(B)) +#define SIGNED_UNSIGNED(A, B) IF(SIGN(A) && UNSIGN(B)) +#define UNSIGNED_SIGNED(A, B) IF(UNSIGN(A) && SIGN(B)) +#define UNSIGNED_UNSIGNED(A, B) IF(UNSIGN(A) && UNSIGN(B)) + +template +Space cast_add(Integer left, Integer right) +{ + return static_cast(left) + static_cast(right); +} + +template +Space cast_subtract(Integer left, Integer right) +{ + return static_cast(left) - static_cast(right); +} + +template +Integer ceiling_add(Integer left, Integer right) +{ + static const auto ceiling = std::numeric_limits::max(); + return left > ceiling - right ? ceiling : left + right; +} + +template +Integer floor_subtract(Integer left, Integer right) +{ + static const auto floor = std::numeric_limits::min(); + return right >= left ? floor : left - right; +} + +template +Integer safe_add(Integer left, Integer right) +{ + static const auto maximum = std::numeric_limits::max(); + + if (left > maximum - right) + throw std::overflow_error("addition overflow"); + + return left + right; +} + +template +Integer safe_subtract(Integer left, Integer right) +{ + static const auto minimum = std::numeric_limits::min(); + + if (left < minimum + right) + throw std::underflow_error("subtraction underflow"); + + return left - right; +} + +template +void safe_increment(Integer& value) +{ + static BC_CONSTEXPR auto one = Integer{1}; + value = safe_add(value, one); +} + +template +void safe_decrement(Integer& value) +{ + static BC_CONSTEXPR auto one = Integer{1}; + value = safe_subtract(value, one); +} + +template +To safe_signed(From signed_value) +{ + static const auto signed_minimum = std::numeric_limits::min(); + static const auto signed_maximum = std::numeric_limits::max(); + + if (signed_value < signed_minimum || signed_value > signed_maximum) + throw std::range_error("signed assignment out of range"); + + return static_cast(signed_value); +} + +template +To safe_unsigned(From unsigned_value) +{ + static const auto unsigned_minimum = std::numeric_limits::min(); + static const auto unsigned_maximum = std::numeric_limits::max(); + + if (unsigned_value < unsigned_minimum || unsigned_value > unsigned_maximum) + throw std::range_error("unsigned assignment out of range"); + + return static_cast(unsigned_value); +} + +template +To safe_to_signed(From unsigned_value) +{ + static_assert(sizeof(uint64_t) >= sizeof(To), "safe assign out of range"); + static const auto signed_maximum = std::numeric_limits::max(); + + if (unsigned_value > static_cast(signed_maximum)) + throw std::range_error("to signed assignment out of range"); + + return static_cast(unsigned_value); +} + +template +To safe_to_unsigned(From signed_value) +{ + static_assert(sizeof(uint64_t) >= sizeof(To), "safe assign out of range"); + static const auto unsigned_maximum = std::numeric_limits::max(); + + if (signed_value < 0 || + static_cast(signed_value) > unsigned_maximum) + throw std::range_error("to unsigned assignment out of range"); + + return static_cast(signed_value); +} + +/// Constrain a numeric value within a given type domain. +template +To domain_constrain(From value) +{ + static const auto minimum = std::numeric_limits::min(); + static const auto maximum = std::numeric_limits::max(); + + if (value < minimum) + return minimum; + + if (value > maximum) + return maximum; + + return static_cast(value); +} + +/// Constrain a numeric value within a given range. +template +To range_constrain(From value, To minimum, To maximum) +{ + if (value < minimum) + return minimum; + + if (value > maximum) + return maximum; + + return static_cast(value); +} + +#undef IF +#undef SIGN +#undef UNSIGN +#undef SIGNED +#undef UNSIGNED +#undef SIGNED_SIGNED +#undef SIGNED_UNSIGNED +#undef UNSIGNED_SIGNED +#undef UNSIGNED_UNSIGNED + +} // namespace libbitcoin + +#endif diff --git a/include/metaverse/bitcoin/math/script_number.hpp b/include/metaverse/bitcoin/math/script_number.hpp index 4bddb37d0..b70b1b1e2 100644 --- a/include/metaverse/bitcoin/math/script_number.hpp +++ b/include/metaverse/bitcoin/math/script_number.hpp @@ -30,6 +30,7 @@ namespace libbitcoin { BC_CONSTEXPR size_t max_script_number_size = 4; BC_CONSTEXPR size_t cltv_max_script_number_size = 5; +BC_CONSTEXPR size_t csv_max_script_number_size = 5; /** * Numeric opcodes (OP_1ADD, etc) are restricted to operating on diff --git a/include/metaverse/bitcoin/version.hpp b/include/metaverse/bitcoin/version.hpp index 3d31ea100..a7aee1381 100644 --- a/include/metaverse/bitcoin/version.hpp +++ b/include/metaverse/bitcoin/version.hpp @@ -12,9 +12,9 @@ * For interpretation of the versioning scheme see: http://semver.org */ -#define MVS_VERSION "0.8.3" +#define MVS_VERSION "0.8.4" #define MVS_MAJOR_VERSION 0 #define MVS_MINOR_VERSION 8 -#define MVS_PATCH_VERSION 3 +#define MVS_PATCH_VERSION 4 #endif diff --git a/include/metaverse/bitcoin/wallet/select_outputs.hpp b/include/metaverse/bitcoin/wallet/select_outputs.hpp index 3ddf9fde8..a64190bf7 100644 --- a/include/metaverse/bitcoin/wallet/select_outputs.hpp +++ b/include/metaverse/bitcoin/wallet/select_outputs.hpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include namespace libbitcoin { namespace wallet { diff --git a/include/metaverse/consensus/export.hpp b/include/metaverse/consensus/export.hpp index be3efb773..8fe4b0fd3 100644 --- a/include/metaverse/consensus/export.hpp +++ b/include/metaverse/consensus/export.hpp @@ -174,7 +174,12 @@ typedef enum verify_flags_type /** * Verify CHECKATTENUATIONVERIFY */ - verify_flags_checkattenuationverify = (1U << 10) + verify_flags_checkattenuationverify = (1U << 10), + + /** + * Verify CHECKSEQUENCEVERIFY + */ + verify_flags_checksequenceverify = (1U << 11) } verify_flags; /** diff --git a/include/metaverse/consensus/miner.hpp b/include/metaverse/consensus/miner.hpp index 841ee362a..a4d48c9a2 100644 --- a/include/metaverse/consensus/miner.hpp +++ b/include/metaverse/consensus/miner.hpp @@ -42,7 +42,6 @@ namespace consensus { BC_CONSTEXPR unsigned int min_tx_fee_per_kb = 1000; BC_CONSTEXPR unsigned int median_time_span = 11; -BC_CONSTEXPR uint32_t version = 1; BC_CONSTEXPR uint64_t future_blocktime_fork_height = 1030000; extern int bucket_size; diff --git a/include/metaverse/explorer/extensions/base_helper.hpp b/include/metaverse/explorer/extensions/base_helper.hpp index 241c7f07b..63bc60449 100644 --- a/include/metaverse/explorer/extensions/base_helper.hpp +++ b/include/metaverse/explorer/extensions/base_helper.hpp @@ -195,7 +195,7 @@ std::shared_ptr sync_fetch_asset_view(const std::string& s std::shared_ptr sync_fetch_asset_deposited_view( const std::string& symbol, bc::blockchain::block_chain_impl& blockchain); - + void sync_fetch_asset_cert_balance(const std::string& address, const string& symbol, bc::blockchain::block_chain_impl& blockchain, @@ -216,9 +216,11 @@ std::string get_address_from_did(const std::string& did, std::string get_fee_dividend_address(bc::blockchain::block_chain_impl& blockchain); +bool is_ETH_Address(const string& address); void check_asset_symbol(const std::string& symbol, bool check_sensitive=false); void check_mit_symbol(const std::string& symbol, bool check_sensitive=false); -void check_did_symbol(const std::string& symbol, bool check_sensitive=false); +void check_did_symbol(const std::string& symbol, bool check_sensitive=false); +void check_message(const std::string& message, bool check_sensitive=false); class BCX_API base_transfer_common { diff --git a/include/metaverse/explorer/extensions/commands/issuecert.hpp b/include/metaverse/explorer/extensions/commands/issuecert.hpp index abe0f9454..55281f1aa 100644 --- a/include/metaverse/explorer/extensions/commands/issuecert.hpp +++ b/include/metaverse/explorer/extensions/commands/issuecert.hpp @@ -94,7 +94,12 @@ class issuecert : public command_extension ( "CERT", value(&argument_.cert)->required(), - "Cert type name can be: NAMING: cert of naming right of domain. The owner of domain cert can issue this type of cert by issuecert with symbol like “domain.XYZ”(domain is the symbol of domain cert)." + "Cert type name can be: naming, marriage or KYC" + ) + ( + "memo,m", + value(&option_.memo)->default_value(""), + "Attached memo for this transaction." ) ( "fee,f", @@ -122,6 +127,7 @@ class issuecert : public command_extension struct option { + std::string memo; } option_; }; diff --git a/include/metaverse/explorer/extensions/commands/secondaryissue.hpp b/include/metaverse/explorer/extensions/commands/secondaryissue.hpp index 28002f4ed..dda6b571a 100644 --- a/include/metaverse/explorer/extensions/commands/secondaryissue.hpp +++ b/include/metaverse/explorer/extensions/commands/secondaryissue.hpp @@ -100,6 +100,11 @@ class secondaryissue: public command_extension value(&option_.attenuation_model_param), BX_MST_OFFERING_CURVE ) + ( + "memo,i", + value(&option_.memo)->default_value(""), + "Attached memo for this transaction." + ) ( "fee,f", value(&argument_.fee)->default_value(10000), @@ -127,6 +132,7 @@ class secondaryissue: public command_extension struct option { std::string attenuation_model_param; + std::string memo; } option_; }; diff --git a/include/metaverse/explorer/extensions/commands/sendmore.hpp b/include/metaverse/explorer/extensions/commands/sendmore.hpp index 6e11bf760..1fbea1fe7 100644 --- a/include/metaverse/explorer/extensions/commands/sendmore.hpp +++ b/include/metaverse/explorer/extensions/commands/sendmore.hpp @@ -86,6 +86,11 @@ class sendmore: public send_command value(&option_.change), "Change to this did/address" ) + ( + "memo,i", + value(&option_.memo)->default_value(""), + "The memo to descript transaction" + ) ( "fee,f", value(&option_.fee)->default_value(10000), @@ -109,11 +114,12 @@ class sendmore: public send_command struct option { - option():fee(10000), change("") + option():fee(10000), change(""), memo("") {}; uint64_t fee; std::string change; + std::string memo; } option_; }; diff --git a/include/metaverse/explorer/extensions/commands/swapmit.hpp b/include/metaverse/explorer/extensions/commands/swapmit.hpp new file mode 100644 index 000000000..221e42944 --- /dev/null +++ b/include/metaverse/explorer/extensions/commands/swapmit.hpp @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2016-2018 mvs developers + * + * This file is part of metaverse-explorer. + * + * metaverse-explorer is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License with + * additional permissions to the one published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. For more information see LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + + +#pragma once +#include +#include +#include +#include + +namespace libbitcoin { +namespace explorer { +namespace commands { + +#define DEFAULT_SWAP_FEE 100000000 + +/************************ burn *************************/ + +class swapmit: public command_extension +{ +public: + static const char* symbol() { return "swapmit";} + const char* name() override { return symbol();} + bool category(int bs) override { return (ex_online & bs ) == bs; } + const char* description() override { return "Swap mit for crosschain transaction."; } + + arguments_metadata& load_arguments() override + { + return get_argument_metadata() + .add("ACCOUNTNAME", 1) + .add("ACCOUNTAUTH", 1) + .add("TO_", 1) + .add("SYMBOL", 1) + .add("FOREIGN_ADDR", 1); + } + + void load_fallbacks (std::istream& input, + po::variables_map& variables) override + { + const auto raw = requires_raw_input(); + load_input(auth_.name, "ACCOUNTNAME", variables, input, raw); + load_input(auth_.auth, "ACCOUNTAUTH", variables, input, raw); + load_input(argument_.to, "TO_", variables, input, raw); + load_input(argument_.symbol, "SYMBOL", variables, input, raw); + load_input(argument_.foreign_addr, "FOREIGN_ADDR", variables, input, raw); + } + + options_metadata& load_options() override + { + using namespace po; + options_description& options = get_option_metadata(); + options.add_options() + ( + BX_HELP_VARIABLE ",h", + value()->zero_tokens(), + "Get a description and instructions for this command." + ) + ( + "ACCOUNTNAME", + value(&auth_.name)->required(), + BX_ACCOUNT_NAME + ) + ( + "ACCOUNTAUTH", + value(&auth_.auth)->required(), + BX_ACCOUNT_AUTH + ) + ( + "TO_", + value(&argument_.to)->required(), + "To this did/address the specific mit will be sent. expect to be \"droplet\"." + ) + ( + "SYMBOL", + value(&argument_.symbol)->required(), + "Asset symbol" + ) + ( + "FOREIGN_ADDR", + value(&argument_.foreign_addr)->required(), + "To this address of the destination chain to swap the mit." + ) + ( + "memo,m", + value(&option_.memo)->default_value(""), + "Attached memo for this transaction." + ) + ( + "swapfee,s", + value(&option_.swapfee)->default_value(DEFAULT_SWAP_FEE), + "Transaction fee for crosschain token swap. defaults to 1 ETP" + ) + ( + "fee,f", + value(&option_.fee)->default_value(10000), + "Transaction fee for miners. defaults to 10000 ETP bits" + ) + ; + + return options; + } + + void set_defaults_from_config (po::variables_map& variables) override + { + } + + console_result invoke (Json::Value& jv_output, + libbitcoin::server::server_node& node) override; + + struct argument + { + std::string to; + std::string symbol; + std::string foreign_addr; + } argument_; + + struct option + { + uint64_t swapfee; + uint64_t fee; + std::string memo; + } option_; + +}; + +} // namespace commands +} // namespace explorer +} // namespace libbitcoin + diff --git a/include/metaverse/explorer/extensions/commands/swaptoken.hpp b/include/metaverse/explorer/extensions/commands/swaptoken.hpp index f4035f46e..3eadf5d79 100644 --- a/include/metaverse/explorer/extensions/commands/swaptoken.hpp +++ b/include/metaverse/explorer/extensions/commands/swaptoken.hpp @@ -86,7 +86,7 @@ class swaptoken: public command_extension ( "TO_", value(&argument_.to)->required(), - "To this did/address the specific asset will be sent. expect to be \"crosschain\"." + "To this did/address the specific asset will be sent. expect to be \"droplet\"." ) ( "SYMBOL", @@ -113,6 +113,11 @@ class swaptoken: public command_extension value(&option_.from), "From this did/address" ) + ( + "memo,m", + value(&option_.memo)->default_value(""), + "Attached memo for this transaction." + ) ( "swapfee,s", value(&option_.swapfee)->default_value(DEFAULT_SWAP_FEE), @@ -149,6 +154,7 @@ class swaptoken: public command_extension uint64_t swapfee; uint64_t fee; std::string change; + std::string memo; } option_; }; diff --git a/include/metaverse/explorer/extensions/commands/transfermit.hpp b/include/metaverse/explorer/extensions/commands/transfermit.hpp index da07ece66..25d13d2a8 100644 --- a/include/metaverse/explorer/extensions/commands/transfermit.hpp +++ b/include/metaverse/explorer/extensions/commands/transfermit.hpp @@ -89,6 +89,11 @@ class transfermit : public command_extension value(&argument_.symbol)->required(), "Asset MIT symbol" ) + ( + "memo,m", + value(&option_.memo)->default_value(""), + "Attached memo for this transaction." + ) ( "fee,f", value(&argument_.fee)->default_value(10000), @@ -114,6 +119,7 @@ class transfermit : public command_extension struct option { + std::string memo; } option_; }; diff --git a/include/metaverse/explorer/version.hpp b/include/metaverse/explorer/version.hpp index 7524d4364..11ebf73c7 100644 --- a/include/metaverse/explorer/version.hpp +++ b/include/metaverse/explorer/version.hpp @@ -12,9 +12,9 @@ * For interpretation of the versioning scheme see: http://semver.org */ -#define MVS_EXPLORER_VERSION "0.8.3" +#define MVS_EXPLORER_VERSION "0.8.4" #define MVS_EXPLORER_MAJOR_VERSION 0 #define MVS_EXPLORER_MINOR_VERSION 8 -#define MVS_EXPLORER_PATCH_VERSION 3 +#define MVS_EXPLORER_PATCH_VERSION 4 #endif diff --git a/src/lib/bitcoin/chain/attachment/account/account.cpp b/src/lib/bitcoin/chain/attachment/account/account.cpp index b4eca84e6..4e23c1767 100644 --- a/src/lib/bitcoin/chain/attachment/account/account.cpp +++ b/src/lib/bitcoin/chain/attachment/account/account.cpp @@ -246,26 +246,6 @@ account::account( { } -account account::factory_from_data(const data_chunk& data) -{ - account instance; - instance.from_data(data); - return instance; -} - -account account::factory_from_data(std::istream& stream) -{ - account instance; - instance.from_data(stream); - return instance; -} - -account account::factory_from_data(reader& source) -{ - account instance; - instance.from_data(source); - return instance; -} bool account::is_valid() const { @@ -283,19 +263,7 @@ void account::reset() this->status = account_status::normal; } -bool account::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool account::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool account::from_data(reader& source) +bool account::from_data_t(reader& source) { reset(); name = source.read_string(); @@ -326,23 +294,7 @@ bool account::from_data(reader& source) return true; } -data_chunk account::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); // serialized_size is not used - return data; -} - -void account::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void account::to_data(writer& sink) const +void account::to_data_t(writer& sink) const { sink.write_string(name); sink.write_string(mnemonic); diff --git a/src/lib/bitcoin/chain/attachment/account/account_address.cpp b/src/lib/bitcoin/chain/attachment/account/account_address.cpp index 8a0e25fa0..a3b00f78b 100644 --- a/src/lib/bitcoin/chain/attachment/account/account_address.cpp +++ b/src/lib/bitcoin/chain/attachment/account/account_address.cpp @@ -61,26 +61,6 @@ account_address::account_address(const account_address& other) address = other.address; status_ = other.status_; } -account_address account_address::factory_from_data(const data_chunk& data) -{ - account_address instance; - instance.from_data(data); - return instance; -} - -account_address account_address::factory_from_data(std::istream& stream) -{ - account_address instance; - instance.from_data(stream); - return instance; -} - -account_address account_address::factory_from_data(reader& source) -{ - account_address instance; - instance.from_data(source); - return instance; -} bool account_address::is_valid() const { @@ -99,19 +79,9 @@ void account_address::reset() status_ = 0; } -bool account_address::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} -bool account_address::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} -bool account_address::from_data(reader& source) +bool account_address::from_data_t(reader& source) { reset(); name = source.read_fixed_string(ADDRESS_NAME_FIX_SIZE); @@ -133,23 +103,8 @@ bool account_address::from_data(reader& source) return true; } -data_chunk account_address::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void account_address::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} -void account_address::to_data(writer& sink) const +void account_address::to_data_t(writer& sink) const { sink.write_fixed_string(name, ADDRESS_NAME_FIX_SIZE); //sink.write_fixed_string(prv_key, ADDRESS_PRV_KEY_FIX_SIZE); diff --git a/src/lib/bitcoin/chain/attachment/asset/asset.cpp b/src/lib/bitcoin/chain/attachment/asset/asset.cpp index 048e41499..24fa24103 100644 --- a/src/lib/bitcoin/chain/attachment/asset/asset.cpp +++ b/src/lib/bitcoin/chain/attachment/asset/asset.cpp @@ -43,26 +43,6 @@ asset::asset(uint32_t status, const asset_transfer& detail): status(status), data(detail) { } -asset asset::factory_from_data(const data_chunk& data) -{ - asset instance; - instance.from_data(data); - return instance; -} - -asset asset::factory_from_data(std::istream& stream) -{ - asset instance; - instance.from_data(stream); - return instance; -} - -asset asset::factory_from_data(reader& source) -{ - asset instance; - instance.from_data(source); - return instance; -} void asset::reset() { @@ -83,19 +63,8 @@ bool asset::is_valid_type() const || (ASSET_TRANSFERABLE_TYPE == status)); } -bool asset::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} -bool asset::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool asset::from_data(reader& source) +bool asset::from_data_t(reader& source) { reset(); @@ -126,23 +95,7 @@ bool asset::from_data(reader& source) return result; } -data_chunk asset::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void asset::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void asset::to_data(writer& sink) const +void asset::to_data_t(writer& sink) const { sink.write_4_bytes_little_endian(status); diff --git a/src/lib/bitcoin/chain/attachment/asset/asset_cert.cpp b/src/lib/bitcoin/chain/attachment/asset/asset_cert.cpp index bc4917c4b..f604bb9f6 100644 --- a/src/lib/bitcoin/chain/attachment/asset/asset_cert.cpp +++ b/src/lib/bitcoin/chain/attachment/asset/asset_cert.cpp @@ -94,40 +94,7 @@ std::string asset_cert::asset_cert::get_key() const return get_key(symbol_, cert_type_); } -asset_cert asset_cert::factory_from_data(const data_chunk& data) -{ - asset_cert instance; - instance.from_data(data); - return instance; -} - -asset_cert asset_cert::factory_from_data(std::istream& stream) -{ - asset_cert instance; - instance.from_data(stream); - return instance; -} - -asset_cert asset_cert::factory_from_data(reader& source) -{ - asset_cert instance; - instance.from_data(source); - return instance; -} - -bool asset_cert::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool asset_cert::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool asset_cert::from_data(reader& source) +bool asset_cert::from_data_t(reader& source) { reset(); symbol_ = source.read_string(); @@ -143,22 +110,8 @@ bool asset_cert::from_data(reader& source) return result; } -data_chunk asset_cert::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - return data; -} - -void asset_cert::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} -void asset_cert::to_data(writer& sink) const +void asset_cert::to_data_t(writer& sink) const { sink.write_string(symbol_); sink.write_string(owner_); diff --git a/src/lib/bitcoin/chain/attachment/asset/asset_detail.cpp b/src/lib/bitcoin/chain/attachment/asset/asset_detail.cpp index 783899013..27ada96df 100644 --- a/src/lib/bitcoin/chain/attachment/asset/asset_detail.cpp +++ b/src/lib/bitcoin/chain/attachment/asset/asset_detail.cpp @@ -50,27 +50,6 @@ asset_detail::asset_detail( { } -asset_detail asset_detail::factory_from_data(const data_chunk& data) -{ - asset_detail instance; - instance.from_data(data); - return instance; -} - -asset_detail asset_detail::factory_from_data(std::istream& stream) -{ - asset_detail instance; - instance.from_data(stream); - return instance; -} - -asset_detail asset_detail::factory_from_data(reader& source) -{ - asset_detail instance; - instance.from_data(source); - return instance; -} - bool asset_detail::is_valid() const { return !(symbol.empty() @@ -91,19 +70,7 @@ void asset_detail::reset() description = ""; } -bool asset_detail::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool asset_detail::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool asset_detail::from_data(reader& source) +bool asset_detail::from_data_t(reader& source) { reset(); @@ -124,22 +91,8 @@ bool asset_detail::from_data(reader& source) return result; } -data_chunk asset_detail::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - return data; -} - -void asset_detail::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} -void asset_detail::to_data(writer& sink) const +void asset_detail::to_data_t(writer& sink) const { sink.write_string(symbol); sink.write_8_bytes_little_endian(maximum_supply); diff --git a/src/lib/bitcoin/chain/attachment/asset/asset_mit.cpp b/src/lib/bitcoin/chain/attachment/asset/asset_mit.cpp index 47dd1190e..e3fcfcd68 100644 --- a/src/lib/bitcoin/chain/attachment/asset/asset_mit.cpp +++ b/src/lib/bitcoin/chain/attachment/asset/asset_mit.cpp @@ -71,40 +71,7 @@ bool asset_mit::operator< (const asset_mit& other) const return symbol_.compare(other.symbol_) < 0; } -asset_mit asset_mit::factory_from_data(const data_chunk& data) -{ - asset_mit instance; - instance.from_data(data); - return instance; -} - -asset_mit asset_mit::factory_from_data(std::istream& stream) -{ - asset_mit instance; - instance.from_data(stream); - return instance; -} - -asset_mit asset_mit::factory_from_data(reader& source) -{ - asset_mit instance; - instance.from_data(source); - return instance; -} - -bool asset_mit::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool asset_mit::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool asset_mit::from_data(reader& source) +bool asset_mit::from_data_t(reader& source) { reset(); @@ -135,22 +102,8 @@ data_chunk asset_mit::to_short_data() const return data; } -data_chunk asset_mit::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - return data; -} - -void asset_mit::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} -void asset_mit::to_data(writer& sink) const +void asset_mit::to_data_t(writer& sink) const { sink.write_byte(status_); sink.write_string(symbol_); diff --git a/src/lib/bitcoin/chain/attachment/asset/asset_transfer.cpp b/src/lib/bitcoin/chain/attachment/asset/asset_transfer.cpp index 0f6d939dc..f7479c261 100644 --- a/src/lib/bitcoin/chain/attachment/asset/asset_transfer.cpp +++ b/src/lib/bitcoin/chain/attachment/asset/asset_transfer.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include namespace libbitcoin { @@ -46,26 +47,6 @@ asset_transfer::asset_transfer(const std::string& symbol, uint64_t quantity): { } -asset_transfer asset_transfer::factory_from_data(const data_chunk& data) -{ - asset_transfer instance; - instance.from_data(data); - return instance; -} - -asset_transfer asset_transfer::factory_from_data(std::istream& stream) -{ - asset_transfer instance; - instance.from_data(stream); - return instance; -} - -asset_transfer asset_transfer::factory_from_data(reader& source) -{ - asset_transfer instance; - instance.from_data(source); - return instance; -} bool asset_transfer::is_valid() const { @@ -80,19 +61,7 @@ void asset_transfer::reset() quantity = 0; } -bool asset_transfer::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool asset_transfer::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool asset_transfer::from_data(reader& source) +bool asset_transfer::from_data_t(reader& source) { reset(); symbol = source.read_string(); @@ -105,23 +74,8 @@ bool asset_transfer::from_data(reader& source) return result; } -data_chunk asset_transfer::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void asset_transfer::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} -void asset_transfer::to_data(writer& sink) const +void asset_transfer::to_data_t(writer& sink) const { sink.write_string(symbol); sink.write_8_bytes_little_endian(quantity); diff --git a/src/lib/bitcoin/chain/attachment/asset/blockchain_asset.cpp b/src/lib/bitcoin/chain/attachment/asset/blockchain_asset.cpp index 1d07baec7..3a6359774 100644 --- a/src/lib/bitcoin/chain/attachment/asset/blockchain_asset.cpp +++ b/src/lib/bitcoin/chain/attachment/asset/blockchain_asset.cpp @@ -39,26 +39,6 @@ blockchain_asset::blockchain_asset(uint32_t version, const output_point& tx_poin { } -blockchain_asset blockchain_asset::factory_from_data(const data_chunk& data) -{ - blockchain_asset instance; - instance.from_data(data); - return instance; -} - -blockchain_asset blockchain_asset::factory_from_data(std::istream& stream) -{ - blockchain_asset instance; - instance.from_data(stream); - return instance; -} - -blockchain_asset blockchain_asset::factory_from_data(reader& source) -{ - blockchain_asset instance; - instance.from_data(source); - return instance; -} bool blockchain_asset::is_valid() const { return true; @@ -72,19 +52,8 @@ void blockchain_asset::reset() asset_ = asset_detail(); } -bool blockchain_asset::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool blockchain_asset::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} -bool blockchain_asset::from_data(reader& source) +bool blockchain_asset::from_data_t(reader& source) { reset(); @@ -96,23 +65,8 @@ bool blockchain_asset::from_data(reader& source) return true; } -data_chunk blockchain_asset::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void blockchain_asset::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} -void blockchain_asset::to_data(writer& sink) const +void blockchain_asset::to_data_t(writer& sink) const { sink.write_4_bytes_little_endian(version_); tx_point_.to_data(sink); diff --git a/src/lib/bitcoin/chain/attachment/attachment.cpp b/src/lib/bitcoin/chain/attachment/attachment.cpp index 93d75858d..2a6c68f1b 100644 --- a/src/lib/bitcoin/chain/attachment/attachment.cpp +++ b/src/lib/bitcoin/chain/attachment/attachment.cpp @@ -44,27 +44,6 @@ attachment::attachment(const std::string& from_did, const std::string& to_did) boost::apply_visitor(visitor, attach); } -attachment attachment::factory_from_data(const data_chunk& data) -{ - attachment instance; - instance.from_data(data); - return instance; -} - -attachment attachment::factory_from_data(std::istream& stream) -{ - attachment instance; - instance.from_data(stream); - return instance; -} - -attachment attachment::factory_from_data(reader& source) -{ - attachment instance; - instance.from_data(source); - return instance; -} - void attachment::reset() { version = 0; @@ -95,20 +74,7 @@ bool attachment::is_valid_type() const || (DID_TYPE == type)); } - -bool attachment::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool attachment::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool attachment::from_data(reader& source) +bool attachment::from_data_t(reader& source) { reset(); @@ -174,23 +140,7 @@ bool attachment::from_data(reader& source) return result; } -data_chunk attachment::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void attachment::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void attachment::to_data(writer& sink) const +void attachment::to_data_t(writer& sink) const { sink.write_4_bytes_little_endian(version); sink.write_4_bytes_little_endian(type); diff --git a/src/lib/bitcoin/chain/attachment/did/blockchain_did.cpp b/src/lib/bitcoin/chain/attachment/did/blockchain_did.cpp index a1c565c92..3404a7ce7 100644 --- a/src/lib/bitcoin/chain/attachment/did/blockchain_did.cpp +++ b/src/lib/bitcoin/chain/attachment/did/blockchain_did.cpp @@ -39,26 +39,6 @@ blockchain_did::blockchain_did(uint32_t version, const output_point& tx_point, { } -blockchain_did blockchain_did::factory_from_data(const data_chunk& data) -{ - blockchain_did instance; - instance.from_data(data); - return instance; -} - -blockchain_did blockchain_did::factory_from_data(std::istream& stream) -{ - blockchain_did instance; - instance.from_data(stream); - return instance; -} - -blockchain_did blockchain_did::factory_from_data(reader& source) -{ - blockchain_did instance; - instance.from_data(source); - return instance; -} bool blockchain_did::is_valid() const { return true; @@ -73,19 +53,8 @@ void blockchain_did::reset() did_ = did_detail(); } -bool blockchain_did::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool blockchain_did::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} -bool blockchain_did::from_data(reader& source) +bool blockchain_did::from_data_t(reader& source) { reset(); @@ -98,23 +67,8 @@ bool blockchain_did::from_data(reader& source) return true; } -data_chunk blockchain_did::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void blockchain_did::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} -void blockchain_did::to_data(writer& sink) const +void blockchain_did::to_data_t(writer& sink) const { sink.write_4_bytes_little_endian(version_); tx_point_.to_data(sink); diff --git a/src/lib/bitcoin/chain/attachment/did/did.cpp b/src/lib/bitcoin/chain/attachment/did/did.cpp index a4a0d38a7..3323ac134 100644 --- a/src/lib/bitcoin/chain/attachment/did/did.cpp +++ b/src/lib/bitcoin/chain/attachment/did/did.cpp @@ -39,27 +39,6 @@ did::did(uint32_t status, const did_detail& detail): { } -did did::factory_from_data(const data_chunk& data) -{ - did instance; - instance.from_data(data); - return instance; -} - -did did::factory_from_data(std::istream& stream) -{ - did instance; - instance.from_data(stream); - return instance; -} - -did did::factory_from_data(reader& source) -{ - did instance; - instance.from_data(source); - return instance; -} - void did::reset() { status = 0; //did_status::did_none; @@ -77,19 +56,7 @@ bool did::is_valid_type() const || (DID_TRANSFERABLE_TYPE == status)); } -bool did::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool did::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool did::from_data(reader& source) +bool did::from_data_t(reader& source) { reset(); @@ -107,23 +74,7 @@ bool did::from_data(reader& source) return result; } -data_chunk did::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void did::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void did::to_data(writer& sink) const +void did::to_data_t(writer& sink) const { sink.write_4_bytes_little_endian(status); data.to_data(sink); diff --git a/src/lib/bitcoin/chain/attachment/did/did_detail.cpp b/src/lib/bitcoin/chain/attachment/did/did_detail.cpp index 63ff5d249..9d1d67801 100644 --- a/src/lib/bitcoin/chain/attachment/did/did_detail.cpp +++ b/src/lib/bitcoin/chain/attachment/did/did_detail.cpp @@ -41,26 +41,6 @@ did_detail::did_detail( { } -did_detail did_detail::factory_from_data(const data_chunk& data) -{ - did_detail instance; - instance.from_data(data); - return instance; -} - -did_detail did_detail::factory_from_data(std::istream& stream) -{ - did_detail instance; - instance.from_data(stream); - return instance; -} - -did_detail did_detail::factory_from_data(reader& source) -{ - did_detail instance; - instance.from_data(source); - return instance; -} bool did_detail::is_valid() const { return !(symbol.empty() @@ -73,19 +53,7 @@ void did_detail::reset() address = ""; } -bool did_detail::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool did_detail::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool did_detail::from_data(reader& source) +bool did_detail::from_data_t(reader& source) { reset(); @@ -99,23 +67,7 @@ bool did_detail::from_data(reader& source) return result; } -data_chunk did_detail::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void did_detail::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void did_detail::to_data(writer& sink) const +void did_detail::to_data_t(writer& sink) const { sink.write_string(symbol); sink.write_string(address); diff --git a/src/lib/bitcoin/chain/attachment/etp/etp.cpp b/src/lib/bitcoin/chain/attachment/etp/etp.cpp index 11fccc4d3..9af133d89 100644 --- a/src/lib/bitcoin/chain/attachment/etp/etp.cpp +++ b/src/lib/bitcoin/chain/attachment/etp/etp.cpp @@ -38,27 +38,6 @@ etp::etp(uint64_t value): } -etp etp::factory_from_data(const data_chunk& data) -{ - etp instance; - instance.from_data(data); - return instance; -} - -etp etp::factory_from_data(std::istream& stream) -{ - etp instance; - instance.from_data(stream); - return instance; -} - -etp etp::factory_from_data(reader& source) -{ - etp instance; - instance.from_data(source); - return instance; -} - void etp::reset() { value= 0; @@ -68,19 +47,8 @@ bool etp::is_valid() const return true; } -bool etp::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool etp::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} -bool etp::from_data(reader& source) +bool etp::from_data_t(reader& source) { /* reset(); @@ -92,23 +60,7 @@ bool etp::from_data(reader& source) return true; } -data_chunk etp::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void etp::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void etp::to_data(writer& sink) const +void etp::to_data_t(writer& sink) const { //sink.write_8_bytes_little_endian(value); // not use etp now } diff --git a/src/lib/bitcoin/chain/attachment/etp/etp_award.cpp b/src/lib/bitcoin/chain/attachment/etp/etp_award.cpp index 8c6cc94e0..cd139953e 100644 --- a/src/lib/bitcoin/chain/attachment/etp/etp_award.cpp +++ b/src/lib/bitcoin/chain/attachment/etp/etp_award.cpp @@ -38,27 +38,6 @@ etp_award::etp_award(uint64_t height): } -etp_award etp_award::factory_from_data(const data_chunk& data) -{ - etp_award instance; - instance.from_data(data); - return instance; -} - -etp_award etp_award::factory_from_data(std::istream& stream) -{ - etp_award instance; - instance.from_data(stream); - return instance; -} - -etp_award etp_award::factory_from_data(reader& source) -{ - etp_award instance; - instance.from_data(source); - return instance; -} - void etp_award::reset() { height= 0; @@ -68,19 +47,7 @@ bool etp_award::is_valid() const return true; } -bool etp_award::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool etp_award::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool etp_award::from_data(reader& source) +bool etp_award::from_data_t(reader& source) { reset(); height = source.read_8_bytes_little_endian(); @@ -89,23 +56,8 @@ bool etp_award::from_data(reader& source) return result; } -data_chunk etp_award::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void etp_award::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} -void etp_award::to_data(writer& sink) const +void etp_award::to_data_t(writer& sink) const { sink.write_8_bytes_little_endian(height); } diff --git a/src/lib/bitcoin/chain/attachment/message/message.cpp b/src/lib/bitcoin/chain/attachment/message/message.cpp index 4a31772d6..2e6c2b887 100644 --- a/src/lib/bitcoin/chain/attachment/message/message.cpp +++ b/src/lib/bitcoin/chain/attachment/message/message.cpp @@ -37,26 +37,6 @@ blockchain_message::blockchain_message(std::string content): } -blockchain_message blockchain_message::factory_from_data(const data_chunk& data) -{ - blockchain_message instance; - instance.from_data(data); - return instance; -} - -blockchain_message blockchain_message::factory_from_data(std::istream& stream) -{ - blockchain_message instance; - instance.from_data(stream); - return instance; -} - -blockchain_message blockchain_message::factory_from_data(reader& source) -{ - blockchain_message instance; - instance.from_data(source); - return instance; -} void blockchain_message::reset() { @@ -70,19 +50,7 @@ bool blockchain_message::is_valid() const || variable_string_size(content_) + 1 > BLOCKCHAIN_MESSAGE_FIX_SIZE); } -bool blockchain_message::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool blockchain_message::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool blockchain_message::from_data(reader& source) +bool blockchain_message::from_data_t(reader& source) { reset(); content_ = source.read_string(); @@ -91,23 +59,7 @@ bool blockchain_message::from_data(reader& source) return result; } -data_chunk blockchain_message::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void blockchain_message::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void blockchain_message::to_data(writer& sink) const +void blockchain_message::to_data_t(writer& sink) const { sink.write_string(content_); } diff --git a/src/lib/bitcoin/chain/block.cpp b/src/lib/bitcoin/chain/block.cpp index 27c460c8e..d1cf68742 100644 --- a/src/lib/bitcoin/chain/block.cpp +++ b/src/lib/bitcoin/chain/block.cpp @@ -33,31 +33,9 @@ namespace libbitcoin { namespace chain { -block block::factory_from_data(const data_chunk& data, - bool with_transaction_count) -{ - block instance; - instance.from_data(data, with_transaction_count); - return instance; -} - -block block::factory_from_data(std::istream& stream, - bool with_transaction_count) -{ - block instance; - instance.from_data(stream, with_transaction_count); - return instance; -} - -block block::factory_from_data(reader& source, - bool with_transaction_count) -{ - block instance; - instance.from_data(source, with_transaction_count); - return instance; -} block::block() + : header{} { } @@ -103,19 +81,7 @@ void block::reset() transactions.shrink_to_fit(); } -bool block::from_data(const data_chunk& data, bool with_transaction_count) -{ - data_source istream(data); - return from_data(istream, with_transaction_count); -} - -bool block::from_data(std::istream& stream, bool with_transaction_count) -{ - istream_reader source(stream); - return from_data(source, with_transaction_count); -} - -bool block::from_data(reader& source, bool with_transaction_count) +bool block::from_data_t(reader& source, bool with_transaction_count) { reset(); @@ -140,23 +106,8 @@ bool block::from_data(reader& source, bool with_transaction_count) return result; } -data_chunk block::to_data(bool with_transaction_count) const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream, with_transaction_count); - ostream.flush(); - BITCOIN_ASSERT(header.number <= 1270000 || data.size() == serialized_size(with_transaction_count)); - return data; -} - -void block::to_data(std::ostream& stream, bool with_transaction_count) const -{ - ostream_writer sink(stream); - to_data(sink, with_transaction_count); -} -void block::to_data(writer& sink, bool with_transaction_count) const +void block::to_data_t(writer& sink, bool with_transaction_count) const { header.to_data(sink, with_transaction_count); diff --git a/src/lib/bitcoin/chain/business_data.cpp b/src/lib/bitcoin/chain/business_data.cpp index b2fddc89b..a77fffb42 100644 --- a/src/lib/bitcoin/chain/business_data.cpp +++ b/src/lib/bitcoin/chain/business_data.cpp @@ -26,40 +26,19 @@ #include #include -#define ETP_TYPE KIND2UINT16(business_kind::etp) -#define ETP_AWARD_TYPE KIND2UINT16(business_kind::etp_award) -#define ASSET_ISSUE_TYPE KIND2UINT16(business_kind::asset_issue) -#define ASSET_TRANSFER_TYPE KIND2UINT16(business_kind::asset_transfer) -#define ASSET_CERT_TYPE KIND2UINT16(business_kind::asset_cert) -#define ASSET_MIT_TYPE KIND2UINT16(business_kind::asset_mit) -#define MESSAGE_TYPE KIND2UINT16(business_kind::message) -#define DID_REGISTER_TYPE KIND2UINT16(business_kind::did_register) -#define DID_TRANSFER_TYPE KIND2UINT16(business_kind::did_transfer) +#define TYPE_ETP KIND2UINT16(business_kind::etp) +#define TYPE_ETP_AWARD KIND2UINT16(business_kind::etp_award) +#define TYPE_ASSET_ISSUE KIND2UINT16(business_kind::asset_issue) +#define TYPE_ASSET_TRANSFER KIND2UINT16(business_kind::asset_transfer) +#define TYPE_ASSET_CERT KIND2UINT16(business_kind::asset_cert) +#define TYPE_ASSET_MIT KIND2UINT16(business_kind::asset_mit) +#define TYPE_MESSAGE KIND2UINT16(business_kind::message) +#define TYPE_DID_REGISTER KIND2UINT16(business_kind::did_register) +#define TYPE_DID_TRANSFER KIND2UINT16(business_kind::did_transfer) namespace libbitcoin { namespace chain { -business_data business_data::factory_from_data(const data_chunk& data) -{ - business_data instance; - instance.from_data(data); - return instance; -} - -business_data business_data::factory_from_data(std::istream& stream) -{ - business_data instance; - instance.from_data(stream); - return instance; -} - -business_data business_data::factory_from_data(reader& source) -{ - business_data instance; - instance.from_data(source); - return instance; -} - void business_data::reset() { kind = business_kind::etp; @@ -74,30 +53,18 @@ bool business_data::is_valid() const bool business_data::is_valid_type() const { - return ((ETP_TYPE == KIND2UINT16(kind)) - || (ASSET_ISSUE_TYPE == KIND2UINT16(kind)) - || (ASSET_TRANSFER_TYPE == KIND2UINT16(kind)) - || (ASSET_CERT_TYPE == KIND2UINT16(kind)) - || (ASSET_MIT_TYPE == KIND2UINT16(kind))) - || (ETP_AWARD_TYPE == KIND2UINT16(kind)) - || (MESSAGE_TYPE == KIND2UINT16(kind)) - || (DID_REGISTER_TYPE == KIND2UINT16(kind)) - || (DID_TRANSFER_TYPE == KIND2UINT16(kind)); -} - -bool business_data::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool business_data::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); + return ((TYPE_ETP == KIND2UINT16(kind)) + || (TYPE_ASSET_ISSUE == KIND2UINT16(kind)) + || (TYPE_ASSET_TRANSFER == KIND2UINT16(kind)) + || (TYPE_ASSET_CERT == KIND2UINT16(kind)) + || (TYPE_ASSET_MIT == KIND2UINT16(kind))) + || (TYPE_ETP_AWARD == KIND2UINT16(kind)) + || (TYPE_MESSAGE == KIND2UINT16(kind)) + || (TYPE_DID_REGISTER == KIND2UINT16(kind)) + || (TYPE_DID_TRANSFER == KIND2UINT16(kind)); } -bool business_data::from_data(reader& source) +bool business_data::from_data_t(reader& source) { reset(); kind = static_cast(source.read_2_bytes_little_endian()); @@ -108,47 +75,47 @@ bool business_data::from_data(reader& source) { switch (KIND2UINT16(kind)) { - case ETP_TYPE: + case TYPE_ETP: { data = etp(); break; } - case ETP_AWARD_TYPE: + case TYPE_ETP_AWARD: { data = etp_award(); break; } - case ASSET_ISSUE_TYPE: + case TYPE_ASSET_ISSUE: { data = asset_detail(); break; } - case ASSET_TRANSFER_TYPE: + case TYPE_ASSET_TRANSFER: { data = asset_transfer(); break; } - case ASSET_CERT_TYPE: + case TYPE_ASSET_CERT: { data = asset_cert(); break; } - case ASSET_MIT_TYPE: + case TYPE_ASSET_MIT: { data = asset_mit(); break; } - case MESSAGE_TYPE: + case TYPE_MESSAGE: { data = blockchain_message(); break; } - case DID_REGISTER_TYPE: + case TYPE_DID_REGISTER: { data = did_detail(); break; } - case DID_TRANSFER_TYPE: + case TYPE_DID_TRANSFER: { data = did_detail(); break; @@ -167,22 +134,7 @@ bool business_data::from_data(reader& source) } -data_chunk business_data::to_data() -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - return data; -} - -void business_data::to_data(std::ostream& stream) -{ - ostream_writer sink(stream); - to_data(sink); -} - -void business_data::to_data(writer& sink) +void business_data::to_data_t(writer& sink) { sink.write_2_bytes_little_endian(KIND2UINT16(kind)); sink.write_4_bytes_little_endian(timestamp); diff --git a/src/lib/bitcoin/chain/header.cpp b/src/lib/bitcoin/chain/header.cpp index 8599a7bec..48151cf36 100644 --- a/src/lib/bitcoin/chain/header.cpp +++ b/src/lib/bitcoin/chain/header.cpp @@ -32,36 +32,13 @@ namespace libbitcoin { namespace chain { -header header::factory_from_data(const data_chunk& data, - bool with_transaction_count) -{ - header instance; - instance.from_data(data, with_transaction_count); - return instance; -} - -header header::factory_from_data(std::istream& stream, - bool with_transaction_count) -{ - header instance; - instance.from_data(stream, with_transaction_count); - return instance; -} - -header header::factory_from_data(reader& source, - bool with_transaction_count) -{ - header instance; - instance.from_data(source, with_transaction_count); - return instance; -} - uint64_t header::satoshi_fixed_size_without_transaction_count() { return 148; } header::header() + : header(0, null_hash, null_hash, 0, 0, 0, 0, 0, 0) { } @@ -163,20 +140,7 @@ void header::reset() mutex_.unlock(); } -bool header::from_data(const data_chunk& data, - bool with_transaction_count) -{ - data_source istream(data); - return from_data(istream, with_transaction_count); -} - -bool header::from_data(std::istream& stream, bool with_transaction_count) -{ - istream_reader source(stream); - return from_data(source, with_transaction_count); -} - -bool header::from_data(reader& source, bool with_transaction_count) +bool header::from_data_t(reader& source, bool with_transaction_count) { reset(); @@ -209,24 +173,8 @@ bool header::from_data(reader& source, bool with_transaction_count) return result; } -data_chunk header::to_data(bool with_transaction_count) const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream, with_transaction_count); - ostream.flush(); - BITCOIN_ASSERT(data.size() == serialized_size(with_transaction_count)); - return data; -} - -void header::to_data(std::ostream& stream, - bool with_transaction_count) const -{ - ostream_writer sink(stream); - to_data(sink, with_transaction_count); -} -void header::to_data(writer& sink, bool with_transaction_count) const +void header::to_data_t(writer& sink, bool with_transaction_count) const { sink.write_4_bytes_little_endian(version); sink.write_hash(previous_block_hash); diff --git a/src/lib/bitcoin/chain/input.cpp b/src/lib/bitcoin/chain/input.cpp index 3b7e96d8f..55e917c35 100644 --- a/src/lib/bitcoin/chain/input.cpp +++ b/src/lib/bitcoin/chain/input.cpp @@ -31,27 +31,50 @@ namespace libbitcoin { namespace chain { -input input::factory_from_data(const data_chunk& data) + + +input::input():sequence(0) +{ + +} + +input::input(input&& other) +: input(std::move(other.previous_output), std::move(other.script),other.sequence) +{ +} +input::input(const input& other) +:input(other.previous_output, other.script, other.sequence) { - input instance; - instance.from_data(data); - return instance; } -input input::factory_from_data(std::istream& stream) +input::input(output_point&& previous_output, chain::script&& script, uint32_t sequence) +: previous_output(std::move(previous_output)), script(std::move(script)) +,sequence(sequence) { - input instance; - instance.from_data(stream); - return instance; } -input input::factory_from_data(reader& source) +input::input(const output_point& previous_output, const chain::script& script, const uint32_t& sequence) +: previous_output(previous_output), script(script),sequence(sequence) { - input instance; - instance.from_data(source); - return instance; } +input& input::operator=(input&& other) +{ + previous_output = std::move(other.previous_output); + script = std::move(other.script); + sequence = std::move(other.sequence); + return *this; +} + +input& input::operator=(const input& other) +{ + previous_output = other.previous_output; + script = other.script; + sequence = other.sequence; + return *this; +} + + bool input::is_valid() const { return (sequence != 0) || @@ -66,19 +89,7 @@ void input::reset() sequence = 0; } -bool input::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool input::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool input::from_data(reader& source) +bool input::from_data_t(reader& source) { reset(); @@ -106,23 +117,7 @@ bool input::from_data(reader& source) return result; } -data_chunk input::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void input::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void input::to_data(writer& sink) const +void input::to_data_t(writer& sink) const { previous_output.to_data(sink); script.to_data(sink, true); @@ -151,6 +146,27 @@ bool input::is_final() const return (sequence == max_input_sequence); } +bool input::is_locked(size_t block_height, uint32_t median_time_past) const +{ + if ((sequence & relative_locktime_disabled) != 0) + return false; + + // bip68: a minimum block-height constraint over the input's age. + const auto minimum = (sequence & relative_locktime_mask); + const auto& prevout = previous_output.metadata; + + if ((sequence & relative_locktime_time_locked) != 0) { + // Median time past must be monotonically-increasing by block. + BITCOIN_ASSERT(median_time_past >= prevout.median_time_past); + const auto age_seconds = median_time_past - prevout.median_time_past; + return age_seconds < (minimum << relative_locktime_seconds_shift); + } + + BITCOIN_ASSERT(block_height >= prevout.height); + const auto age_blocks = block_height - prevout.height; + return age_blocks < minimum; +} + std::string input::get_script_address() const { auto payment_address = wallet::payment_address::extract(script); diff --git a/src/lib/bitcoin/chain/output.cpp b/src/lib/bitcoin/chain/output.cpp index 3e66aa60c..1f1e48e44 100644 --- a/src/lib/bitcoin/chain/output.cpp +++ b/src/lib/bitcoin/chain/output.cpp @@ -33,26 +33,46 @@ namespace libbitcoin { namespace chain { -output output::factory_from_data(const data_chunk& data) + +output::output(){} + +output::output(output&& other) +: output(std::move(other.value), std::move(other.script),std::move(other.attach_data)) +{ +} +output::output(const output& other) +:output(other.value, other.script, other.attach_data) +{ +} + +output::output(uint64_t&& value, chain::script&& script, attachment&& attach_data) +: value(std::move(value)), script(std::move(script)) +,attach_data(std::move(attach_data)) +{ +} + +output::output(const uint64_t& value, const chain::script& script, const attachment& attach_data) +: value(value), script(script),attach_data(attach_data) { - output instance; - instance.from_data(data); - return instance; } -output output::factory_from_data(std::istream& stream) +output& output::operator=(output&& other) { - output instance; - instance.from_data(stream); - return instance; + value = std::move(other.value); + script = std::move(other.script); + attach_data = std::move(other.attach_data); + return *this; } -output output::factory_from_data(reader& source) +output& output::operator=(const output& other) { - output instance; - instance.from_data(source); - return instance; + value = other.value; + script = other.script; + attach_data = other.attach_data; + return *this; } + + bool output::is_valid_symbol(const std::string& symbol, uint32_t tx_version) { if (symbol.empty()) @@ -179,19 +199,7 @@ void output::reset() attach_data.reset(); // added for asset issue/transfer } -bool output::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool output::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool output::from_data(reader& source) +bool output::from_data_t(reader& source) { reset(); @@ -213,25 +221,7 @@ bool output::from_data(reader& source) return result; } -data_chunk output::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - log::debug("output::to_data") << "data.size=" << data.size(); - log::debug("output::to_data") << "serialized_size=" << serialized_size(); - //BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void output::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void output::to_data(writer& sink) const +void output::to_data_t(writer& sink) const { sink.write_8_bytes_little_endian(value); script.to_data(sink, true); diff --git a/src/lib/bitcoin/chain/output_point.cpp b/src/lib/bitcoin/chain/output_point.cpp new file mode 100644 index 000000000..3362ee097 --- /dev/null +++ b/src/lib/bitcoin/chain/output_point.cpp @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2011-2017 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace chain { + +// Constructors. +//----------------------------------------------------------------------------- + +output_point::output_point() + : point{}, metadata{} +{ +} + +output_point::output_point(point&& value) + : point(std::move(value)), metadata{} +{ +} + +output_point::output_point(const point& value) + : point(value), metadata{} +{ +} + +output_point::output_point(const output_point& other) + : point(other), metadata(other.metadata) +{ +} + +output_point::output_point(output_point&& other) + : point(std::move(other)), metadata(std::move(other.metadata)) +{ +} + +output_point::output_point(hash_digest&& hash, uint32_t index) + : point({ std::move(hash), index }), metadata{} +{ +} + +output_point::output_point(const hash_digest& hash, uint32_t index) + : point(hash, index) +{ +} + +// Operators. +//----------------------------------------------------------------------------- + +output_point& output_point::operator=(point&& other) +{ + reset(); + point::operator=(std::move(other)); + return *this; +} + +output_point& output_point::operator=(const point& other) +{ + reset(); + point::operator=(other); + return *this; +} + +output_point& output_point::operator=(output_point&& other) +{ + point::operator=(std::move(other)); + metadata = std::move(other.metadata); + return *this; +} + +output_point& output_point::operator=(const output_point& other) +{ + point::operator=(other); + metadata = other.metadata; + return *this; +} + +bool output_point::operator==(const point& other) const +{ + return point::operator==(other); +} + +bool output_point::operator!=(const point& other) const +{ + return point::operator!=(other); +} + +bool output_point::operator==(const output_point& other) const +{ + return point::operator==(other); +} + +bool output_point::operator!=(const output_point& other) const +{ + return !(*this == other); +} + +// Deserialization. +//----------------------------------------------------------------------------- + +output_point output_point::factory(const data_chunk& data) +{ + output_point instance; + instance.from_data(data); + return instance; +} + +output_point output_point::factory(std::istream& stream) +{ + output_point instance; + instance.from_data(stream); + return instance; +} + +output_point output_point::factory(reader& source) +{ + output_point instance; + instance.from_data(source); + return instance; +} + +// Validation. +//----------------------------------------------------------------------------- + +// For tx pool validation height is that of the candidate block. +bool output_point::is_mature(size_t height) const +{ + // Coinbase (null) inputs and those with non-coinbase prevouts are mature. + if (!metadata.coinbase || is_null()) + return true; + + // The (non-coinbase) input refers to a coinbase output, so validate depth. + return floor_subtract(height, metadata.height) >= coinbase_maturity; +} + +} // namespace chain +} // namespace libbitcoin diff --git a/src/lib/bitcoin/chain/point.cpp b/src/lib/bitcoin/chain/point.cpp index b83a5a457..b3ab5884a 100644 --- a/src/lib/bitcoin/chain/point.cpp +++ b/src/lib/bitcoin/chain/point.cpp @@ -35,51 +35,86 @@ namespace libbitcoin { namespace chain { -point point::factory_from_data(const data_chunk& data) +// Constructors. +//----------------------------------------------------------------------------- + +// A default instance is invalid (until modified). +point::point() + : hash(null_hash), index(0) { - point instance; - instance.from_data(data); - return instance; } -point point::factory_from_data(std::istream& stream) +point::point(const hash_digest& hash_, uint32_t index_) + : hash(hash_), index(index_) { - point instance; - instance.from_data(stream); - return instance; } -point point::factory_from_data(reader& source) +point::point(hash_digest&& hash_, uint32_t index_) + : hash(std::move(hash_)), index(index_) { - point instance; - instance.from_data(source); - return instance; } -bool point::is_valid() const +point::point(const point& other) + : point(other.hash, other.index) { - return (index != 0) || (hash != null_hash); } -void point::reset() +point::point(point&& other) + : point(std::move(other.hash), other.index) { - hash.fill(0); - index = 0; } -bool point::from_data(const data_chunk& data) +point::~point() +{ +} + +// Operators. +//----------------------------------------------------------------------------- + +point& point::operator=(point&& other) +{ + hash = std::move(other.hash); + index = other.index; + return *this; +} + +point& point::operator=(const point& other) +{ + hash = other.hash; + index = other.index; + return *this; +} + +// This arbitrary order is produced to support set uniqueness determinations. +bool point::operator<(const point& other) const +{ + // The index is primary only because its comparisons are simpler. + return index == other.index ? hash < other.hash : + index < other.index; +} + +bool point::operator==(const point& other) const +{ + return (hash == other.hash) && (index == other.index); +} + +bool point::operator!=(const point& other) const { - data_source istream(data); - return from_data(istream); + return !(*this == other); } -bool point::from_data(std::istream& stream) +bool point::is_valid() const { - istream_reader source(stream); - return from_data(source); + return (index != 0) || (hash != null_hash); } -bool point::from_data(reader& source) +void point::reset() +{ + hash = null_hash; + index = 0; +} + +bool point::from_data_t(reader& source) { reset(); @@ -93,23 +128,7 @@ bool point::from_data(reader& source) return result; } -data_chunk point::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - BITCOIN_ASSERT(data.size() == serialized_size()); - return data; -} - -void point::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void point::to_data(writer& sink) const +void point::to_data_t(writer& sink) const { sink.write_hash(hash); sink.write_4_bytes_little_endian(index); @@ -165,6 +184,7 @@ uint64_t point::checksum() const const auto index_lower_15_bits = tx_index & ~mask; return tx_upper_49_bits | index_lower_15_bits; } + #if 0 // old version checksum method // This is used with output_point identification within a set of history rows // of the same address. Collision will result in miscorrelation of points by @@ -188,21 +208,22 @@ uint64_t point::checksum() const // return std::hash()(*this); } #endif -bool operator==(const point& left, const point& right) -{ - return left.hash == right.hash && left.index == right.index; -} -bool operator!=(const point& left, const point& right) -{ - return !(left == right); -} - -bool operator<(const point& left, const point& right) -{ - typedef std::tuple tupe_cmp; - return tupe_cmp(left.hash, left.index) < tupe_cmp(right.hash, right.index); -} +// bool operator==(const point& left, const point& right) +// { +// return left.hash == right.hash && left.index == right.index; +// } + +// bool operator!=(const point& left, const point& right) +// { +// return !(left == right); +// } + +// bool operator<(const point& left, const point& right) +// { +// typedef std::tuple tupe_cmp; +// return tupe_cmp(left.hash, left.index) < tupe_cmp(right.hash, right.index); +// } } // namspace chain } // namspace libbitcoin diff --git a/src/lib/bitcoin/chain/script/opcode.cpp b/src/lib/bitcoin/chain/script/opcode.cpp index 97abe58bf..dd3794f7e 100644 --- a/src/lib/bitcoin/chain/script/opcode.cpp +++ b/src/lib/bitcoin/chain/script/opcode.cpp @@ -19,6 +19,7 @@ * along with this program. If not, see . */ #include +#include #include #include @@ -234,14 +235,15 @@ std::string opcode_to_string(opcode value, uint32_t flags) return "checkmultisig"; case opcode::checkmultisigverify: return "checkmultisigverify"; + case opcode::op_nop1: + return "nop1"; case opcode::checklocktimeverify: return "checklocktimeverify"; case opcode::checkattenuationverify: return "checkattenuationverify"; - case opcode::op_nop1: - return "nop1"; - case opcode::op_nop4: - return "nop4"; + case opcode::checksequenceverify: + return script::is_active(flags, script_context::bip112_enabled) ? + "checksequenceverify" : "nop4"; case opcode::op_nop5: return "nop5"; case opcode::op_nop6: @@ -471,16 +473,16 @@ opcode string_to_opcode(const std::string& value) return opcode::checkmultisig; else if (value == "checkmultisigverify") return opcode::checkmultisigverify; + else if (value == "nop1") + return opcode::op_nop1; // Replaces nop2 with BIP65 activation. else if (value == "nop2" || value == "checklocktimeverify") return opcode::checklocktimeverify; // Replaces nop3 with attenuation, see MIP7 and MIP8. else if (value == "nop3" || value == "checkattenuationverify") return opcode::checkattenuationverify; - else if (value == "nop1") - return opcode::op_nop1; - else if (value == "nop4") - return opcode::op_nop4; + else if (value == "nop4" || value == "checksequenceverify") + return opcode::checksequenceverify; else if (value == "nop5") return opcode::op_nop5; else if (value == "nop6") diff --git a/src/lib/bitcoin/chain/script/script.cpp b/src/lib/bitcoin/chain/script/script.cpp index 5e638336c..86f869174 100644 --- a/src/lib/bitcoin/chain/script/script.cpp +++ b/src/lib/bitcoin/chain/script/script.cpp @@ -1441,6 +1441,37 @@ bool op_checklocktimeverify(evaluation_context& context, const script& script, return is_locktime_type_match(stack, transaction); } +bool op_checksequenceverify(evaluation_context& context, const script& script, + const transaction& parent_tx, uint32_t input_index) +{ + if (input_index >= parent_tx.inputs.size()) + return false; + + if (context.stack.empty()) + return false; + + // nSequence, like nLockTime, is a 32-bit unsigned integer + // field. See the comment in CHECKLOCKTIMEVERIFY regarding + // 5-byte numeric operands. + script_number number; + if (!number.set_data(context.pop_stack(), csv_max_script_number_size)) + return false; + + // In the rare event that the argument may be < 0 due to + // some arithmetic being done first, you can always use + // 0 MAX CHECKSEQUENCEVERIFY. + if (number < 0) + return false; + + // To provide for future soft-fork extensibility, if the + // operand has the disabled lock-time flag set, + // CHECKSEQUENCEVERIFY behaves as a NOP. + if ((number.int64() & (1 << 31)/*CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG*/) != 0) + return false; + + return true; +} + bool op_checkattenuationverify(evaluation_context& context, const script& script, const transaction& parent_tx, uint32_t input_index) { @@ -1735,15 +1766,17 @@ bool run_operation(const operation& op, const transaction& parent_tx, case opcode::checklocktimeverify: return script::is_active(context.flags, script_context::bip65_enabled) ? - op_checklocktimeverify(context, script, parent_tx, - input_index) : true; + op_checklocktimeverify(context, script, parent_tx, input_index) : true; case opcode::checkattenuationverify: return script::is_active(context.flags, script_context::attenuation_enabled) ? op_checkattenuationverify(context, script, parent_tx, input_index) : true; + case opcode::checksequenceverify: + return script::is_active(context.flags, script_context::bip112_enabled) ? + op_checksequenceverify(context, script, parent_tx, input_index) : true; + case opcode::op_nop1: - case opcode::op_nop4: case opcode::op_nop5: case opcode::op_nop6: case opcode::op_nop7: diff --git a/src/lib/bitcoin/chain/transaction.cpp b/src/lib/bitcoin/chain/transaction.cpp index fc816fdc3..a7dc7e3ed 100644 --- a/src/lib/bitcoin/chain/transaction.cpp +++ b/src/lib/bitcoin/chain/transaction.cpp @@ -35,27 +35,6 @@ namespace libbitcoin { namespace chain { -transaction transaction::factory_from_data(const data_chunk& data) -{ - transaction instance; - instance.from_data(data); - return instance; -} - -transaction transaction::factory_from_data(std::istream& stream) -{ - transaction instance; - instance.from_data(stream); - return instance; -} - -transaction transaction::factory_from_data(reader& source) -{ - transaction instance; - instance.from_data(source); - return instance; -} - // default constructors transaction::transaction() @@ -134,19 +113,7 @@ void transaction::reset() mutex_.unlock(); } -bool transaction::from_data(const data_chunk& data) -{ - data_source istream(data); - return from_data(istream); -} - -bool transaction::from_data(std::istream& stream) -{ - istream_reader source(stream); - return from_data(source); -} - -bool transaction::from_data(reader& source) +bool transaction::from_data_t(reader& source) { reset(); version = source.read_4_bytes_little_endian(); @@ -202,25 +169,7 @@ bool transaction::from_data(reader& source) return result; } -data_chunk transaction::to_data() const -{ - data_chunk data; - data_sink ostream(data); - to_data(ostream); - ostream.flush(); - - BITCOIN_ASSERT(data.size() == serialized_size()); - - return data; -} - -void transaction::to_data(std::ostream& stream) const -{ - ostream_writer sink(stream); - to_data(sink); -} - -void transaction::to_data(writer& sink) const +void transaction::to_data_t(writer& sink) const { sink.write_4_bytes_little_endian(version); sink.write_variable_uint_little_endian(inputs.size()); @@ -323,6 +272,21 @@ bool transaction::is_final(uint64_t block_height, uint32_t block_time) const return true; } +bool transaction::is_locked(size_t block_height, + uint32_t median_time_past) const +{ + if (version < relative_locktime_min_version || is_coinbase()) + return false; + + const auto locked = [block_height, median_time_past](const input& input) + { + return input.is_locked(block_height, median_time_past); + }; + + // If any input is relative time locked the transaction is as well. + return std::any_of(inputs.begin(), inputs.end(), locked); +} + bool transaction::is_locktime_conflict() const { auto locktime_set = locktime != 0; diff --git a/src/lib/bitcoin/error.cpp b/src/lib/bitcoin/error.cpp index 18445c4e9..de0f70a22 100644 --- a/src/lib/bitcoin/error.cpp +++ b/src/lib/bitcoin/error.cpp @@ -261,6 +261,9 @@ std::string error_category_impl::message(int ev) const BC_NOEXCEPT case error::mit_symbol_invalid: return "MIT symbol invalid"; + case error::sequence_locked: + return "transaction currently locked"; + // unknown errors case error::unknown: default: diff --git a/src/lib/blockchain/block_chain_impl.cpp b/src/lib/blockchain/block_chain_impl.cpp index fe91025e7..c28d02422 100644 --- a/src/lib/blockchain/block_chain_impl.cpp +++ b/src/lib/blockchain/block_chain_impl.cpp @@ -1022,11 +1022,11 @@ std::shared_ptr block_chain_impl::get_spends_output(const in { const auto spend = database_.spends.get(input); if (spend.valid){ - + const auto result = database_.transactions.get(spend.hash); if(result) { return std::make_shared(result.transaction()); - } + } } return nullptr; @@ -1328,7 +1328,7 @@ static history::list expand_history(history_compact::list& compact) // an output and its spend. In this case we return just the spend. { history row; - row.output = { null_hash, max_uint32 }; + row.output = output_point( null_hash, max_uint32 ); row.output_height = max_uint64; row.value = max_uint64; row.spend = spend.point; @@ -1938,8 +1938,8 @@ std::string block_chain_impl::get_did_from_address(const std::string& did_addres [fork_index](const blockchain_did & item){ return is_blackhole_address(item.get_did().get_address()) || item.get_height() <= fork_index; }); - - if(iter == blockchain_didlist->end() || iter->get_did().get_address() != did_address) + + if(iter == blockchain_didlist->end() || iter->get_did().get_address() != did_address) return ""; } else if(did_symbol == "" && fork_index != max_uint64) @@ -2300,7 +2300,7 @@ bool block_chain_impl::get_history_callback(const payment_address& address, if (!found) { history row; - row.output = { null_hash, max_uint32 }; + row.output = output_point( null_hash, max_uint32 ); row.output_height = max_uint64; row.value = max_uint64; row.spend = spend.point; diff --git a/src/lib/blockchain/validate_block.cpp b/src/lib/blockchain/validate_block.cpp index 0086e1dd3..a183e08e4 100644 --- a/src/lib/blockchain/validate_block.cpp +++ b/src/lib/blockchain/validate_block.cpp @@ -151,26 +151,32 @@ void validate_block::initialize_context() // good for all, no votes is needed. activations_ |= script_context::attenuation_enabled; - // bip65 is activated based on 75% of preceding 1000 mainnet blocks. - if (activate(count_4)) + // bip65/112 is activated based on 75% of preceding 1000 mainnet blocks. + if (activate(count_4)) { activations_ |= script_context::bip65_enabled; + activations_ |= script_context::bip112_enabled; + } // bip66 is activated based on 75% of preceding 1000 mainnet blocks. - if (activate(count_3)) + if (activate(count_3)) { activations_ |= script_context::bip66_enabled; + } // bip34 is activated based on 75% of preceding 1000 mainnet blocks. - if (activate(count_2)) + if (activate(count_2)) { activations_ |= script_context::bip34_enabled; + } // bip30 applies to all but two mainnet blocks that violate the rule. if (height_ != bip30_exception_height1 && - height_ != bip30_exception_height2) + height_ != bip30_exception_height2) { activations_ |= script_context::bip30_enabled; + } // bip16 was activated with a one-time test on mainnet/testnet (~55% rule). - if (height_ >= bip16_activation_height) + if (height_ >= bip16_activation_height) { activations_ |= script_context::bip16_enabled; + } } // initialize_context must be called first (to set activations_). @@ -182,6 +188,7 @@ bool validate_block::is_active(script_context flag) const const auto version = current_block_.header.version; return (flag == script_context::attenuation_enabled) || + (flag == script_context::bip112_enabled && version >= version_4) || (flag == script_context::bip65_enabled && version >= version_4) || (flag == script_context::bip66_enabled && version >= version_3) || (flag == script_context::bip34_enabled && version >= version_2); @@ -543,6 +550,15 @@ code validate_block::accept_block() const !is_valid_coinbase_height(height_, current_block_)) return error::coinbase_height_mismatch; + if (is_active(script_context::bip112_enabled)) { + for (const auto& tx : current_block_.transactions) { + if (tx.is_locked(height_, median_time_past())) { + return error::sequence_locked; + } + + RETURN_IF_STOPPED(); + } + } return error::success; } diff --git a/src/lib/blockchain/validate_transaction.cpp b/src/lib/blockchain/validate_transaction.cpp index 831d16e73..faa800861 100644 --- a/src/lib/blockchain/validate_transaction.cpp +++ b/src/lib/blockchain/validate_transaction.cpp @@ -1339,6 +1339,18 @@ code validate_transaction::check_transaction_basic() const if (tx.serialized_size() > max_transaction_size) return error::size_limits; + // check double spend in inputs + std::set set; + for (auto& input : tx.inputs) { + auto tx_hash = libbitcoin::encode_hash(input.previous_output.hash); + auto value = tx_hash + ":" + std::to_string(input.previous_output.index); + if (set.count(value)) { + return error::double_spend; + } + + set.insert(value); + } + // Check for negative or overflow output values uint64_t total_output_value = 0; @@ -1461,6 +1473,9 @@ bool validate_transaction::check_consensus(const script& prevout_script, if ((flags & script_context::attenuation_enabled) != 0) consensus_flags |= verify_flags_checkattenuationverify; + if ((flags & script_context::bip112_enabled) != 0) + consensus_flags |= verify_flags_checksequenceverify; + const auto result = verify_script(current_transaction.data(), current_transaction.size(), previous_output_script.data(), previous_output_script.size(), input_index32, consensus_flags); diff --git a/src/lib/client/proxy.cpp b/src/lib/client/proxy.cpp index 5c3a3f924..a60d1113b 100644 --- a/src/lib/client/proxy.cpp +++ b/src/lib/client/proxy.cpp @@ -444,7 +444,7 @@ history::list proxy::expand(history_compact::list& compact) if (!found) { history row; - row.output = { null_hash, max_uint32 }; + row.output = output_point( null_hash, max_uint32 ); row.output_height = max_uint64; row.value = max_uint64; row.spend = spend.point; diff --git a/src/lib/consensus/clone/primitives/transaction.h b/src/lib/consensus/clone/primitives/transaction.h index 2fb41698e..6784636bf 100644 --- a/src/lib/consensus/clone/primitives/transaction.h +++ b/src/lib/consensus/clone/primitives/transaction.h @@ -62,13 +62,40 @@ class CTxIn CScript scriptSig; uint32_t nSequence; + /* Setting sequence to this value for every input in a transaction + * disables nLockTime. */ + static const uint32_t SEQUENCE_FINAL = 0xffffffff; + + /* Below flags apply in the context of BIP 68*/ + /* If this flag set, input::sequence is NOT interpreted as a + * relative lock-time. */ + static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31); + + /* If input::sequence encodes a relative lock-time and this flag + * is set, the relative lock-time has units of 512 seconds, + * otherwise it specifies blocks with a granularity of 1. */ + static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22); + + /* If input::sequence encodes a relative lock-time, this mask is + * applied to extract that lock-time from the sequence field. */ + static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff; + + /* In order to use the same number of bits to encode roughly the + * same wall-clock duration, and because blocks are naturally + * limited to occur every 600s on average, the minimum granularity + * for time-based relative lock-time is fixed at 512 seconds. + * Converting from input::sequence to seconds is performed by + * multiplying by 512 = 2^9, or equivalently shifting up by + * 9 bits. */ + static const int SEQUENCE_LOCKTIME_GRANULARITY = 9; + CTxIn() { - nSequence = std::numeric_limits::max(); + nSequence = SEQUENCE_FINAL; } - explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits::max()); - CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits::max()); + explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL); + CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL); ADD_SERIALIZE_METHODS; @@ -81,7 +108,7 @@ class CTxIn bool IsFinal() const { - return (nSequence == std::numeric_limits::max()); + return (nSequence == SEQUENCE_FINAL); } friend bool operator==(const CTxIn& a, const CTxIn& b) diff --git a/src/lib/consensus/clone/script/interpreter.cpp b/src/lib/consensus/clone/script/interpreter.cpp index 47ddf8469..dfe95db39 100644 --- a/src/lib/consensus/clone/script/interpreter.cpp +++ b/src/lib/consensus/clone/script/interpreter.cpp @@ -394,10 +394,47 @@ bool EvalScript(vector >& stack, const CScript& script, un popstack(stack); popstack(stack); + break; } - break; - case OP_NOP1: case OP_NOP4: case OP_NOP5: + case OP_CHECKSEQUENCEVERIFY: + { + if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) { + // not enabled; treat as a NOP3 + if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); + } + break; + } + + if (stack.size() < 1) + return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); + + // nSequence, like nLockTime, is a 32-bit unsigned integer + // field. See the comment in CHECKLOCKTIMEVERIFY regarding + // 5-byte numeric operands. + const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5); + + // In the rare event that the argument may be < 0 due to + // some arithmetic being done first, you can always use + // 0 MAX CHECKSEQUENCEVERIFY. + if (nSequence < 0) + return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME); + + // To provide for future soft-fork extensibility, if the + // operand has the disabled lock-time flag set, + // CHECKSEQUENCEVERIFY behaves as a NOP. + if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0) + break; + + // Compare the specified sequence number with the input. + if (!checker.CheckSequence(nSequence)) + return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME); + + break; + } + + case OP_NOP1: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: { if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) @@ -1180,6 +1217,51 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con return true; } +bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const +{ + // Relative lock times are supported by comparing the passed + // in operand to the sequence number of the input. + const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence; + + // Fail if the transaction's version number is not set high + // enough to trigger BIP 68 rules. + if (static_cast(txTo->nVersion) < 2) + return false; + + // Sequence numbers with their most significant bit set are not + // consensus constrained. Testing that the transaction's sequence + // number do not have this bit set prevents using this property + // to get around a CHECKSEQUENCEVERIFY check. + if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) + return false; + + // Mask off any bits that do not have consensus-enforced meaning + // before doing the integer comparisons + const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK; + const int64_t txToSequenceMasked = txToSequence & nLockTimeMask; + const CScriptNum nSequenceMasked = nSequence & nLockTimeMask; + + // There are two kinds of nSequence: lock-by-blockheight + // and lock-by-blocktime, distinguished by whether + // nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG. + // + // We want to compare apples to apples, so fail the script + // unless the type of nSequenceMasked being tested is the same as + // the nSequenceMasked in the transaction. + if (!( + (txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) || + (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) + )) { + return false; + } + + // Now that we know we're comparing apples-to-apples, the + // comparison is a simple numeric one. + if (nSequenceMasked > txToSequenceMasked) + return false; + + return true; +} bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) { diff --git a/src/lib/consensus/clone/script/interpreter.h b/src/lib/consensus/clone/script/interpreter.h index 5c65485c8..43ac8be74 100644 --- a/src/lib/consensus/clone/script/interpreter.h +++ b/src/lib/consensus/clone/script/interpreter.h @@ -84,6 +84,9 @@ enum // Verify CHECKATTENUATIONVERIFY SCRIPT_VERIFY_CHECKATTENUATIONVERIFY = (1U << 10), + + // Verify CHECKSEQUENCEVERIFY + SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 11), }; bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); @@ -103,6 +106,11 @@ class BaseSignatureChecker return false; } + virtual bool CheckSequence(const CScriptNum& nSequence) const + { + return false; + } + virtual ~BaseSignatureChecker() {} }; @@ -119,6 +127,7 @@ class TransactionSignatureChecker : public BaseSignatureChecker TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {} bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const; bool CheckLockTime(const CScriptNum& nLockTime) const; + bool CheckSequence(const CScriptNum& nSequence) const override; }; class MutableTransactionSignatureChecker : public TransactionSignatureChecker diff --git a/src/lib/consensus/clone/script/script.cpp b/src/lib/consensus/clone/script/script.cpp index a89ba1770..ecb098f06 100644 --- a/src/lib/consensus/clone/script/script.cpp +++ b/src/lib/consensus/clone/script/script.cpp @@ -133,7 +133,7 @@ const char* GetOpName(opcodetype opcode) case OP_NOP1 : return "OP_NOP1"; case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY"; case OP_CHECKATTENUATIONVERIFY : return "OP_CHECKATTENUATIONVERIFY"; - case OP_NOP4 : return "OP_NOP4"; + case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY"; case OP_NOP5 : return "OP_NOP5"; case OP_NOP6 : return "OP_NOP6"; case OP_NOP7 : return "OP_NOP7"; diff --git a/src/lib/consensus/clone/script/script.h b/src/lib/consensus/clone/script/script.h index 1f67c989c..587185a79 100644 --- a/src/lib/consensus/clone/script/script.h +++ b/src/lib/consensus/clone/script/script.h @@ -167,6 +167,7 @@ enum opcodetype OP_NOP3 = 0xb2, OP_CHECKATTENUATIONVERIFY = OP_NOP3, OP_NOP4 = 0xb3, + OP_CHECKSEQUENCEVERIFY = OP_NOP4, OP_NOP5 = 0xb4, OP_NOP6 = 0xb5, OP_NOP7 = 0xb6, @@ -260,6 +261,11 @@ class CScriptNum inline CScriptNum& operator+=( const CScriptNum& rhs) { return operator+=(rhs.m_value); } inline CScriptNum& operator-=( const CScriptNum& rhs) { return operator-=(rhs.m_value); } + inline CScriptNum operator&( const int64_t& rhs) const { return CScriptNum(m_value & rhs);} + inline CScriptNum operator&( const CScriptNum& rhs) const { return operator&(rhs.m_value); } + + inline CScriptNum& operator&=( const CScriptNum& rhs) { return operator&=(rhs.m_value); } + inline CScriptNum operator-() const { assert(m_value != std::numeric_limits::min()); @@ -288,6 +294,12 @@ class CScriptNum return *this; } + inline CScriptNum& operator&=( const int64_t& rhs) + { + m_value &= rhs; + return *this; + } + int getint() const { if (m_value > std::numeric_limits::max()) diff --git a/src/lib/consensus/consensus/consensus.cpp b/src/lib/consensus/consensus/consensus.cpp index 850c3daea..56fa12036 100644 --- a/src/lib/consensus/consensus/consensus.cpp +++ b/src/lib/consensus/consensus/consensus.cpp @@ -108,7 +108,7 @@ verify_result_type script_error_to_verify_result(ScriptError_t code) case SCRIPT_ERR_UNBALANCED_CONDITIONAL: return verify_result_unbalanced_conditional; - // BIP65 + // BIP65/BIP112 (shared codes) case SCRIPT_ERR_NEGATIVE_LOCKTIME: return verify_result_negative_locktime; case SCRIPT_ERR_UNSATISFIED_LOCKTIME: @@ -175,6 +175,8 @@ unsigned int verify_flags_to_script_flags(unsigned int flags) script_flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; if ((flags & verify_flags_checkattenuationverify) != 0) script_flags |= SCRIPT_VERIFY_CHECKATTENUATIONVERIFY; + if ((flags & verify_flags_checksequenceverify) != 0) + script_flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; return script_flags; } diff --git a/src/lib/consensus/miner.cpp b/src/lib/consensus/miner.cpp index e4eeac206..c67ca9f90 100644 --- a/src/lib/consensus/miner.cpp +++ b/src/lib/consensus/miner.cpp @@ -42,6 +42,7 @@ using namespace std; namespace libbitcoin { namespace consensus { +static BC_CONSTEXPR uint32_t block_version = 1; static BC_CONSTEXPR unsigned int min_tx_fee = 10000; // tuples: (priority, fee_per_kb, fee, transaction_ptr) @@ -253,7 +254,7 @@ miner::block_ptr miner::create_genesis_block(bool is_mainnet) // Create coinbase tx transaction tx_new; tx_new.inputs.resize(1); - tx_new.inputs[0].previous_output = {null_hash, max_uint32}; + tx_new.inputs[0].previous_output = output_point(null_hash, max_uint32); tx_new.inputs[0].script.operations = {{chain::opcode::raw_data, {text.begin(), text.end()}}}; tx_new.outputs.resize(1); @@ -293,8 +294,8 @@ miner::transaction_ptr miner::create_coinbase_tx( transaction_ptr ptransaction = make_shared(); ptransaction->inputs.resize(1); - ptransaction->version = version; - ptransaction->inputs[0].previous_output = {null_hash, max_uint32}; + ptransaction->version = transaction_version::first; + ptransaction->inputs[0].previous_output = output_point(null_hash, max_uint32); script_number number(block_height); ptransaction->inputs[0].script.operations.push_back({ chain::opcode::special, number.data() }); @@ -542,7 +543,7 @@ miner::block_ptr miner::create_new_block(const wallet::payment_address& pay_addr pblock->header.previous_block_hash = prev_header.hash(); pblock->header.merkle = pblock->generate_merkle_root(pblock->transactions); pblock->header.timestamp = get_adjust_time(pblock->header.number); - pblock->header.version = version; + pblock->header.version = block_version; pblock->header.bits = HeaderAux::calculateDifficulty(pblock->header, prev_header); pblock->header.nonce = 0; pblock->header.mixhash = 0; diff --git a/src/lib/database/databases/address_asset_database.cpp b/src/lib/database/databases/address_asset_database.cpp index 00482d95c..0d578aa61 100644 --- a/src/lib/database/databases/address_asset_database.cpp +++ b/src/lib/database/databases/address_asset_database.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -506,7 +507,7 @@ business_history::list address_asset_database::get_business_history(const short_ if (!found) { business_history row; - row.output = { null_hash, max_uint32 }; + row.output = output_point( null_hash, max_uint32 ); row.output_height = max_uint64; row.value = max_uint64; row.spend = spend.point; diff --git a/src/lib/database/databases/address_did_database.cpp b/src/lib/database/databases/address_did_database.cpp index 8fa588a6f..e266735ba 100644 --- a/src/lib/database/databases/address_did_database.cpp +++ b/src/lib/database/databases/address_did_database.cpp @@ -502,7 +502,7 @@ business_history::list address_did_database::get_business_history(const short_ha if (!found) { business_history row; - row.output = { null_hash, max_uint32 }; + row.output = output_point( null_hash, max_uint32 ); row.output_height = max_uint64; row.value = max_uint64; row.spend = spend.point; diff --git a/src/lib/database/databases/address_mit_database.cpp b/src/lib/database/databases/address_mit_database.cpp index 8fac143a7..d6c2e94be 100644 --- a/src/lib/database/databases/address_mit_database.cpp +++ b/src/lib/database/databases/address_mit_database.cpp @@ -524,7 +524,7 @@ business_history::list address_mit_database::get_business_history(const short_ha if (!found) { business_history row; - row.output = { null_hash, max_uint32 }; + row.output = output_point( null_hash, max_uint32 ); row.output_height = max_uint64; row.value = max_uint64; row.spend = spend.point; diff --git a/src/lib/explorer/extensions/base_helper.cpp b/src/lib/explorer/extensions/base_helper.cpp index ec1636e54..68e8cc8a4 100644 --- a/src/lib/explorer/extensions/base_helper.cpp +++ b/src/lib/explorer/extensions/base_helper.cpp @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include namespace libbitcoin { namespace explorer { @@ -67,6 +69,55 @@ utxo_attach_type get_utxo_attach_type(const chain::output& output_) + std::to_string(output.attach_data.get_type())); } +//Check if address is checksum of ETH address +bool is_ETH_Address(const string& address) +{ + // regex checking + { + sregex_iterator end; + + // check if it has the basic requirements of an address + static const regex reg_common("^0x[0-9a-fA-F]{40}$"); + sregex_iterator it(address.begin(), address.end(), reg_common); + if (it == end) { + return false; + } + + // If it's all small caps, return true + static const regex reg_alllower("^0x[0-9a-f]{40}$"); + sregex_iterator it1(address.begin(), address.end(), reg_alllower); + if (it1 != end) { + return true; + } + + // If it's all caps, return true + static const regex reg_allupper("^0x[0-9A-F]{40}$"); + sregex_iterator it2(address.begin(), address.end(), reg_allupper); + if (it2 != end) { + return true; + } + } + + // Otherwise check each case + auto addr = address.substr(2); // get rid of prefix "0x" + auto address_hash = bc::sha3(boost::to_lower_copy(addr)).hex(); + + for (size_t i = 0; i < addr.size(); ++i) { + auto c = addr[i]; + if (std::isdigit(c)) { + continue; + } + // the nth letter should be uppercase if the nth digit of casemap is 1 (89abcdef) + bool is_less_than_8 = (address_hash[i] >= '0' && address_hash[i] < '8'); + if ((is_less_than_8 && !std::islower(c)) || + (!is_less_than_8 && !std::isupper(c))) { + return false; + } + } + + return true; +} + void check_did_symbol(const std::string& symbol, bool check_sensitive) { if (!chain::output::is_valid_did_symbol(symbol, check_sensitive)) { @@ -124,6 +175,13 @@ void check_mit_symbol(const std::string& symbol, bool check_sensitive) } } +void check_message(const std::string& message, bool check_sensitive) +{ + if (!message.empty() && message.size() >= 0xfd/* 253, see serializer.ipp */) { + throw argument_size_invalid_exception{"message length out of bounds."}; + } +} + std::string get_address(const std::string& did_or_address, bc::blockchain::block_chain_impl& blockchain) { @@ -1267,8 +1325,8 @@ attachment base_transfer_common::populate_output_attachment(const receiver_recor } else if (record.type == utxo_attach_type::message) { auto msg = boost::get(record.attach_elem.get_attach()); - if (msg.get_content().size() > 128) { - throw tx_attachment_value_exception{"memo text length should be less than 128"}; + if (msg.get_content().size() >= 0xfd/* 253, see serializer.ipp */) { + throw tx_attachment_value_exception{"memo text length should be less than 253"}; } if (!msg.is_valid()) { throw tx_attachment_value_exception{"invalid message attachment"}; diff --git a/src/lib/explorer/extensions/command_extension_func.cpp b/src/lib/explorer/extensions/command_extension_func.cpp index 1bc8af072..d06882961 100644 --- a/src/lib/explorer/extensions/command_extension_func.cpp +++ b/src/lib/explorer/extensions/command_extension_func.cpp @@ -72,6 +72,7 @@ #include #include #include +// #include #include #include #include @@ -196,6 +197,7 @@ void broadcast_extension(const function)> func, std::os func(make_shared()); func(make_shared()); func(make_shared()); + // func(make_shared()); os <<"\r\n"; //did @@ -361,6 +363,8 @@ shared_ptr find_extension(const string& symbol) return make_shared(); if (symbol == getmit::symbol()) return make_shared(); + // if (symbol == swapmit::symbol()) + // return make_shared(); // did if (symbol == registerdid::symbol()) diff --git a/src/lib/explorer/extensions/commands/issuecert.cpp b/src/lib/explorer/extensions/commands/issuecert.cpp index 615e8cf12..033a531cc 100644 --- a/src/lib/explorer/extensions/commands/issuecert.cpp +++ b/src/lib/explorer/extensions/commands/issuecert.cpp @@ -134,6 +134,13 @@ console_result issuecert::invoke (Json::Value& jv_output, attachment("", to_did)} }; + if (!option_.memo.empty()) { + check_message(option_.memo); + + receiver.push_back({to_address, "", 0, 0, utxo_attach_type::message, + attachment(0, 0, blockchain_message(option_.memo))}); + } + if (certs_create == asset_cert_ns::naming) { auto&& domain = asset_cert::get_domain(argument_.symbol); receiver.push_back( diff --git a/src/lib/explorer/extensions/commands/secondaryissue.cpp b/src/lib/explorer/extensions/commands/secondaryissue.cpp index 747947f6d..d70c30f14 100644 --- a/src/lib/explorer/extensions/commands/secondaryissue.cpp +++ b/src/lib/explorer/extensions/commands/secondaryissue.cpp @@ -91,6 +91,13 @@ console_result secondaryissue::invoke(Json::Value& jv_output, utxo_attach_type::asset_cert, attachment("", to_did)} }; + if (!option_.memo.empty()) { + check_message(option_.memo); + + receiver.push_back({to_address, "", 0, 0, utxo_attach_type::message, + attachment(0, 0, blockchain_message(option_.memo))}); + } + auto issue_helper = secondary_issuing_asset(*this, blockchain, std::move(auth_.name), std::move(auth_.auth), std::move(to_address), std::move(argument_.symbol), diff --git a/src/lib/explorer/extensions/commands/send.cpp b/src/lib/explorer/extensions/commands/send.cpp index 87bfe93af..082895c12 100644 --- a/src/lib/explorer/extensions/commands/send.cpp +++ b/src/lib/explorer/extensions/commands/send.cpp @@ -51,9 +51,7 @@ console_result send::invoke(Json::Value& jv_output, }; if (!option_.memo.empty()) { - if ( option_.memo.size() >= 255) { - throw argument_size_invalid_exception{"memo length out of bounds."}; - } + check_message(option_.memo); receiver.push_back({to_address, "", 0, 0, utxo_attach_type::message, attachment(0, 0, blockchain_message(option_.memo))}); diff --git a/src/lib/explorer/extensions/commands/sendasset.cpp b/src/lib/explorer/extensions/commands/sendasset.cpp index a901801f4..6f48c7e43 100644 --- a/src/lib/explorer/extensions/commands/sendasset.cpp +++ b/src/lib/explorer/extensions/commands/sendasset.cpp @@ -37,9 +37,7 @@ console_result sendasset::invoke(Json::Value& jv_output, blockchain.is_account_passwd_valid(auth_.name, auth_.auth); blockchain.uppercase_symbol(argument_.symbol); - if (!option_.memo.empty() && option_.memo.size() >= 255) { - throw argument_size_invalid_exception{"memo length out of bounds."}; - } + check_message(option_.memo); // check asset symbol check_asset_symbol(argument_.symbol); diff --git a/src/lib/explorer/extensions/commands/sendassetfrom.cpp b/src/lib/explorer/extensions/commands/sendassetfrom.cpp index d452dc63e..e989077a7 100644 --- a/src/lib/explorer/extensions/commands/sendassetfrom.cpp +++ b/src/lib/explorer/extensions/commands/sendassetfrom.cpp @@ -49,9 +49,7 @@ console_result sendassetfrom::invoke(Json::Value& jv_output, throw asset_amount_exception("invalid amount parameter!"); } - if (!option_.memo.empty() && option_.memo.size() >= 255) { - throw argument_size_invalid_exception{"memo length out of bounds."}; - } + check_message(option_.memo); // receiver utxo_attach_type attach_type = option_.attenuation_model_param.empty() diff --git a/src/lib/explorer/extensions/commands/sendfrom.cpp b/src/lib/explorer/extensions/commands/sendfrom.cpp index 1e8a4aa27..13b4d883f 100644 --- a/src/lib/explorer/extensions/commands/sendfrom.cpp +++ b/src/lib/explorer/extensions/commands/sendfrom.cpp @@ -51,9 +51,7 @@ console_result sendfrom::invoke(Json::Value& jv_output, }; if (!option_.memo.empty()) { - if ( option_.memo.size() >= 255) { - throw argument_size_invalid_exception{"memo length out of bounds."}; - } + check_message(option_.memo); receiver.push_back({to_address, "", 0, 0, utxo_attach_type::message, attachment(0, 0, blockchain_message(option_.memo))}); diff --git a/src/lib/explorer/extensions/commands/sendmore.cpp b/src/lib/explorer/extensions/commands/sendmore.cpp index e17cf574c..418ac2885 100644 --- a/src/lib/explorer/extensions/commands/sendmore.cpp +++ b/src/lib/explorer/extensions/commands/sendmore.cpp @@ -37,6 +37,8 @@ console_result sendmore::invoke (Json::Value& jv_output, auto& blockchain = node.chain_impl(); blockchain.is_account_passwd_valid(auth_.name, auth_.auth); + std::string msg_address; + // receiver std::vector receiver; @@ -50,11 +52,27 @@ console_result sendmore::invoke (Json::Value& jv_output, } receiver.push_back({address,"", item.second(), 0, utxo_attach_type::etp, attach}); + + if (msg_address.empty()) { + msg_address = address; + } } // change address std::string change_address = get_address(option_.change, blockchain); + // memo + if (!option_.memo.empty()) { + check_message(option_.memo); + + if (!change_address.empty()) { + msg_address = change_address; + } + + receiver.push_back({msg_address, "", 0, 0, utxo_attach_type::message, + attachment(0, 0, blockchain_message(option_.memo))}); + } + auto send_helper = sending_etp(*this, blockchain, std::move(auth_.name), std::move(auth_.auth), "", std::move(receiver), diff --git a/src/lib/explorer/extensions/commands/swapmit.cpp b/src/lib/explorer/extensions/commands/swapmit.cpp new file mode 100644 index 000000000..be232236c --- /dev/null +++ b/src/lib/explorer/extensions/commands/swapmit.cpp @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2016-2018 mvs developers + * + * This file is part of metaverse-explorer. + * + * metaverse-explorer is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License with + * additional permissions to the one published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. For more information see LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + + +namespace libbitcoin { +namespace explorer { +namespace commands { + +console_result swapmit::invoke(Json::Value& jv_output, + libbitcoin::server::server_node& node) +{ + auto& blockchain = node.chain_impl(); + auto acc = blockchain.is_account_passwd_valid(auth_.name, auth_.auth); + + // check foreign_addr + if (argument_.foreign_addr.empty() || argument_.foreign_addr.size() >= 200) { + throw argument_size_invalid_exception{"foreign address length out of bounds."}; + } + + // check ETH address + if (!is_ETH_Address(argument_.foreign_addr)) { + throw argument_legality_exception{argument_.foreign_addr + " is not a valid ETH address."}; + } + + // check symbol + check_mit_symbol(argument_.symbol); + + // check to did + auto to_did = argument_.to; + auto to_address = get_address_from_did(to_did, blockchain); + if (!blockchain.is_valid_address(to_address)) { + throw toaddress_invalid_exception("Invalid did parameter! " + to_did); + } + + // get mit + auto mits = blockchain.get_account_mits(auth_.name, argument_.symbol); + if (mits->size() == 0) { + throw asset_lack_exception("Not enough asset '" + argument_.symbol + "'"); + } + + // multisig support + auto& mit = *(mits->begin()); + std::string from_address(mit.get_address()); + bool is_multisig_address = blockchain.is_script_address(from_address); + + account_multisig acc_multisig; + if (is_multisig_address) { + auto multisig_vec = acc->get_multisig(from_address); + if (!multisig_vec || multisig_vec->empty()) { + throw multisig_notfound_exception("From address multisig record not found."); + } + + acc_multisig = *(multisig_vec->begin()); + } + + // swap fee + const std::string&& swapfee_address = bc::get_developer_community_address( + blockchain.chain_settings().use_testnet_rules); + + if (option_.swapfee < DEFAULT_SWAP_FEE) { + throw argument_legality_exception{"invalid swapfee parameter! must >= 1 ETP"}; + } + + // construct receivers + std::vector receiver{ + { + to_address, argument_.symbol, 0, 0, 0, + utxo_attach_type::asset_mit_transfer, attachment("", to_did) + }, + + { + swapfee_address, "", option_.swapfee, 0, + utxo_attach_type::etp, attachment() + } + }; + + // attach memo + if (!option_.memo.empty()) { + check_message(option_.memo); + + receiver.push_back({ + to_address, "", 0, 0, utxo_attach_type::message, + attachment(0, 0, blockchain_message(option_.memo)) + }); + } + + // attach swap info + std::string message("{\"type\":\"ETH\",\"address\":\"" + argument_.foreign_addr + "\"}"); + receiver.push_back({ + to_address, "", 0, 0, utxo_attach_type::message, + attachment(0, 0, blockchain_message(message)) + }); + + auto helper = transferring_mit( + *this, blockchain, + std::move(auth_.name), std::move(auth_.auth), + is_multisig_address ? std::move(from_address) : "", + std::move(argument_.symbol), + std::move(receiver), option_.fee, + std::move(acc_multisig)); + + helper.exec(); + + // json output + auto tx = helper.get_transaction(); + if (is_multisig_address) { + jv_output = config::json_helper(get_api_version()).prop_list_of_rawtx(tx, false, true); + } + else { + jv_output = config::json_helper(get_api_version()).prop_tree(tx, true); + } + + return console_result::okay; +} + +} // namespace commands +} // namespace explorer +} // namespace libbitcoin + diff --git a/src/lib/explorer/extensions/commands/swaptoken.cpp b/src/lib/explorer/extensions/commands/swaptoken.cpp index 2529a826b..89ee15503 100644 --- a/src/lib/explorer/extensions/commands/swaptoken.cpp +++ b/src/lib/explorer/extensions/commands/swaptoken.cpp @@ -33,54 +33,6 @@ namespace libbitcoin { namespace explorer { namespace commands { -//Check if address is checksum of ETH address -bool is_ETH_Address(const string& address) -{ - // regex checking - { - sregex_iterator end; - - // check if it has the basic requirements of an address - static const regex reg_common("^0x[0-9a-fA-F]{40}$"); - sregex_iterator it(address.begin(), address.end(), reg_common); - if (it == end) { - return false; - } - - // If it's all small caps, return true - static const regex reg_alllower("^0x[0-9a-f]{40}$"); - sregex_iterator it1(address.begin(), address.end(), reg_alllower); - if (it1 != end) { - return true; - } - - // If it's all caps, return true - static const regex reg_allupper("^0x[0-9A-F]{40}$"); - sregex_iterator it2(address.begin(), address.end(), reg_allupper); - if (it2 != end) { - return true; - } - } - - // Otherwise check each case - auto addr = address.substr(2); // get rid of prefix "0x" - auto address_hash = bc::sha3(boost::to_lower_copy(addr)).hex(); - - for (size_t i = 0; i < addr.size(); ++i) { - auto c = addr[i]; - if (std::isdigit(c)) { - continue; - } - // the nth letter should be uppercase if the nth digit of casemap is 1 (89abcdef) - bool is_less_than_8 = (address_hash[i] >= '0' && address_hash[i] < '8'); - if ((is_less_than_8 && !std::islower(c)) || - (!is_less_than_8 && !std::isupper(c))) { - return false; - } - } - - return true; -} console_result swaptoken::invoke(Json::Value& jv_output, libbitcoin::server::server_node& node) @@ -90,8 +42,8 @@ console_result swaptoken::invoke(Json::Value& jv_output, blockchain.uppercase_symbol(argument_.symbol); // check message - if (argument_.foreign_addr.empty() || argument_.foreign_addr.size() >= 255) { - throw argument_size_invalid_exception{"message length out of bounds."}; + if (argument_.foreign_addr.empty() || argument_.foreign_addr.size() >= 200) { + throw argument_size_invalid_exception{"foreign address length out of bounds."}; } // check ETH address @@ -127,6 +79,13 @@ console_result swaptoken::invoke(Json::Value& jv_output, {swapfee_address, "", option_.swapfee, 0, utxo_attach_type::etp, attach_fee}, }; + if (!option_.memo.empty()) { + check_message(option_.memo); + + receiver.push_back({to_address, "", 0, 0, utxo_attach_type::message, + attachment(0, 0, blockchain_message(option_.memo))}); + } + std::string message("{\"type\":\"ETH\",\"address\":\""+ argument_.foreign_addr + "\"}"); auto send_helper = sending_asset( diff --git a/src/lib/explorer/extensions/commands/transfermit.cpp b/src/lib/explorer/extensions/commands/transfermit.cpp index 0ba77c180..d8ebda972 100644 --- a/src/lib/explorer/extensions/commands/transfermit.cpp +++ b/src/lib/explorer/extensions/commands/transfermit.cpp @@ -74,6 +74,13 @@ console_result transfermit::invoke (Json::Value& jv_output, } }; + if (!option_.memo.empty()) { + check_message(option_.memo); + + receiver.push_back({to_address, "", 0, 0, utxo_attach_type::message, + attachment(0, 0, blockchain_message(option_.memo))}); + } + auto helper = transferring_mit( *this, blockchain, std::move(auth_.name), std::move(auth_.auth),