diff --git a/.gitignore b/.gitignore index 7fdb5211..75e0d74c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.a *.sw* +*.cmake CMakeCache.txt CMakeFiles Makefile @@ -19,7 +20,13 @@ tests/chain_test tests/intense_test tests/performance_test -/doxygen +doxygen + +programs/cli_wallet/cli_wallet +programs/js_operation_serializer/js_operation_serializer +programs/witness_node/witness_node +tests/intense_test +tests/performance_test witness_node_data_dir wallet.json diff --git a/.gitmodules b/.gitmodules index 789f4b5d..9680fb37 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,11 +1,11 @@ [submodule "docs"] path = docs - url = git@github.com:cryptonomex/graphene.wiki.git + url = https://github.com/cryptonomex/graphene.wiki.git [submodule "libraries/fc"] path = libraries/fc url = git@git.syncad.com:/fc.git ignore = dirty [submodule "libraries/leveldb"] path = libraries/leveldb - url = git@github.com:bitcoin/leveldb.git + url = https://github.com/bitcoin/leveldb.git ignore = dirty diff --git a/libraries/chain/asset.cpp b/libraries/chain/asset.cpp index b3b0152f..cb1f6fdb 100644 --- a/libraries/chain/asset.cpp +++ b/libraries/chain/asset.cpp @@ -116,7 +116,7 @@ namespace graphene { namespace chain { FC_ASSERT( base.amount > share_type(0) ); FC_ASSERT( quote.amount > share_type(0) ); FC_ASSERT( base.asset_id != quote.asset_id ); - } FC_CAPTURE_AND_RETHROW() } + } FC_CAPTURE_AND_RETHROW( (base)(quote) ) } void price_feed::validate() const { try { @@ -133,6 +133,7 @@ namespace graphene { namespace chain { FC_ASSERT( required_maintenance_collateral < required_initial_collateral ); FC_ASSERT( required_maintenance_collateral >= 1000 ); FC_ASSERT( call_limit.is_null() || call_limit < ~short_limit ); - } FC_CAPTURE_AND_RETHROW() } + } FC_CAPTURE_AND_RETHROW( (call_limit.is_null())(short_limit.is_null())(call_limit)(short_limit) + (max_margin_period_sec)(required_maintenance_collateral)(required_initial_collateral) ) } } } // graphene::chain diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 1b2e343f..7125932c 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -219,7 +219,7 @@ void database::init_genesis(const genesis_allocation& initial_allocation) _wso.scheduler._min_token_count = init_witnesses.size() / 2; _wso.scheduler.update( init_witness_set ); - for( int i=0; i database::get_scheduled_witness(uint32_t slot_num)co // ask the near scheduler who goes in the given slot witness_id_type wid; - bool slot_is_near = wso.scheduler.get_slot(slot_num, wid); + bool slot_is_near = wso.scheduler.get_slot(slot_num-1, wid); if( ! slot_is_near ) { // if the near scheduler doesn't know, we have to extend it to @@ -47,7 +47,7 @@ pair database::get_scheduled_witness(uint32_t slot_num)co far_future_witness_scheduler far_scheduler = far_future_witness_scheduler(wso.scheduler, far_rng); - if( !far_scheduler.get_slot(slot_num, wid) ) + if( !far_scheduler.get_slot(slot_num-1, wid) ) { // no scheduled witness -- somebody set up us the bomb // n.b. this code path is impossible, the present @@ -84,7 +84,7 @@ vector database::get_near_witness_schedule()const vector result; result.reserve(wso.scheduler.size()); - uint32_t slot_num = 1; + uint32_t slot_num = 0; witness_id_type wid; while( wso.scheduler.get_slot(slot_num++, wid) ) diff --git a/libraries/chain/include/graphene/chain/blinded_balance_object.hpp b/libraries/chain/include/graphene/chain/blinded_balance_object.hpp new file mode 100644 index 00000000..4d4ea044 --- /dev/null +++ b/libraries/chain/include/graphene/chain/blinded_balance_object.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + */ +#pragma once + +namespace graphene { namespace chain { + + /** + * @class blinded_balance_object + * @brief tracks a blinded balance commitment + * @ingroup object + * @ingroup protocol + */ + class blinded_balance_object : public graphene::db::abstract_object + { + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = blinded_balance_object_type; + + fc::ecc::commitment_type commitment; + asset_id_type asset_id; + optional owner; + address key; + }; + + struct by_asset; + struct by_owner; + struct by_commitment; + + /** + * @ingroup object_index + */ + typedef multi_index_container< + blinded_balance_object, + indexed_by< + ordered_unique< tag, member< object, object_id_type, &object::id > >, + hashed_unique< tag, member >, + ordered_non_unique< tag, member >, + ordered_non_unique< tag, member > + > + > blinded_balance_object_multi_index_type; + typedef generic_index balance_index; + + +} } // graphene::chain + +FC_REFLECT( graphene::chain::blinded_balance_object, (commitment)(asset_id)(last_update_block_num)(owner) ) diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 1efea9bc..507b5641 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -114,3 +114,13 @@ #define GRAPHENE_MAX_INTEREST_APR uint16_t( 10000 ) #define GRAPHENE_LEGACY_NAME_IMPORT_PERIOD 3000000 /** 3 million blocks */ +/** + * Reserved Account IDs with special meaning + */ +///@{ +#define GRAPHENE_GENESIS_ACCOUNT (graphene::chain::account_id_type(0)) +#define GRAPHENE_WITNESS_ACCOUNT (graphene::chain::account_id_type(1)) +#define GRAPHENE_DELEGATE_ACCOUNT (graphene::chain::account_id_type(2)) +#define GRAPHENE_NULL_ACCOUNT (graphene::chain::account_id_type(3)) +#define GRAPHENE_TEMP_ACCOUNT (graphene::chain::account_id_type(4)) +///@} diff --git a/libraries/chain/include/graphene/chain/key_object.hpp b/libraries/chain/include/graphene/chain/key_object.hpp index 3a9d07da..6500e34f 100644 --- a/libraries/chain/include/graphene/chain/key_object.hpp +++ b/libraries/chain/include/graphene/chain/key_object.hpp @@ -1,19 +1,6 @@ /* * Copyright (c) 2015, Cryptonomex, Inc. * All rights reserved. - * - * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and - * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, - * are permitted until September 8, 2015, provided that the following conditions are met: - * - * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include diff --git a/libraries/chain/include/graphene/chain/operations.hpp b/libraries/chain/include/graphene/chain/operations.hpp index d53b649a..278d4811 100644 --- a/libraries/chain/include/graphene/chain/operations.hpp +++ b/libraries/chain/include/graphene/chain/operations.hpp @@ -276,6 +276,8 @@ namespace graphene { namespace chain { void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const { acc.adjust( fee_payer(), -fee ); } }; +<<<<<<< HEAD +======= /** * @brief Create a delegate object, as a bid to hold a delegate seat on the network. * @ingroup operations @@ -295,6 +297,7 @@ namespace graphene { namespace chain { share_type calculate_fee( const fee_schedule_type& k )const; void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const { acc.adjust( fee_payer(), -fee ); } }; +>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2 /** * @brief Create a witness object, as a bid to hold a witness position on the network. @@ -466,6 +469,114 @@ namespace graphene { namespace chain { } }; + /** + * There are two ways to transfer value while maintaining privacy: + * 1. account to account with amount kept secret + * 2. stealth transfers with amount sender/receiver kept secret + * + * When doing account to account transfers, everyone with access to the + * memo key can see the amounts, but they will not have access to the funds. + * + * When using stealth transfers the same key is used for control and reading + * the memo. + * + * This operation is more expensive than a normal transfer and has + * a fee proportional to the size of the operation. + * + * All assets in a blind transfer must be of the same type: fee.asset_id + * The fee_payer is the temp account and can be funded from the blinded values. + * + * Using this operation you can transfer from an account and/or blinded balances + * to an account and/or blinded balances. + * + * The sum of the blind_inputs + public inputs - public outputs - blind_outputs - fee must + * be 0. + * + * Stealth Transfers: + * + * Assuming Receiver has key pair R,r and has shared public key R with Sender + * Assuming Sender has key pair S,s + * Generate one time key pair O,o as s.child(nonce) where nonce can be inferred from transaction + * Calculate secret V = o*R + * blinding_factor = sha256(V) + * memo is encrypted via aes of V + * owner = R.child(sha256(blinding_factor)) + * + * Sender gives Receiver output ID to complete the payment. + * + * This process can also be used to send money to a cold wallet without having to + * pre-register any accounts. + * + * Outputs are assigned the same IDs as the inputs until no more input IDs are available, + * in which case a the return value will be the *first* ID allocated for an output. Additional + * output IDs are allocated sequentially thereafter. If there are fewer outputs than inputs + * then the input IDs are freed and never used again. + */ + struct blind_transfer_operation + { + /** + * This data is encrypted and stored in the + * encrypted memo portion of the blind output. + */ + struct blind_memo + { + account_id_type from; + share_type amount; + string message; + /** set to the first 4 bytes of the shared secret + * used to encrypt the memo. Used to verify that + * decryption was successful. + */ + uint32_t check= 0; + }; + + struct blind_input + { + fc::ecc::commitment_type commitment; + /** provided to maintain the invariant that all authority + * required by an operation is explicit in the operation. Must + * match blinded_balance_id->owner + */ + static_variant owner; + }; + + /** + * The blinded output that must be proven to be greater than 0 + */ + struct blind_output + { + fc::ecc::commitment_type commitment; + /** only required if there is more than one blind output */ + range_proof_type range_proof; + static_variant owner; + public_key_type one_time_key; + /** encrypted via aes with shared secret derived from + * one_time_key and (owner or owner.memo_key) + */ + vector encrypted_memo; + }; + + asset fee; + account_id_type fee_payer_id; + account_id_type from_account; + /** unblinded amount transfered from from account */ + share_type from_amount; + account_id_type to_account; + /** unblinded amount transfered to to_account */ + share_type to_amount; + string to_account_name; + optional
to_address; + vector inputs; + vector outputs; + + account_id_type fee_payer()const; + void get_required_auth( flat_set& active_auth_set, + flat_set& )const; + void validate()const; + share_type calculate_fee( const fee_schedule_type& k )const; + void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const; + }; + /** * @ingroup operations */ @@ -1503,6 +1614,7 @@ namespace graphene { namespace chain { } }; + /** * @defgroup workers The Blockchain Worker System * @ingroup operations @@ -1868,5 +1980,21 @@ FC_REFLECT( graphene::chain::worker_create_operation, FC_REFLECT( graphene::chain::custom_operation, (fee)(payer)(required_auths)(id)(data) ) FC_REFLECT( graphene::chain::void_result, ) +FC_REFLECT( graphene::chain::blind_transfer_operation::blind_memo, + (from)(amount)(message)(check) ) +FC_REFLECT( graphene::chain::blind_transfer_operation::blind_input, + (commitment)(owner) ) +FC_REFLECT( graphene::chain::blind_transfer_operation::blind_output, + (commitment)(range_proof)(owner)(one_time_key)(encrypted_memo) ) +FC_REFLECT( graphene::chain::blind_transfer_operation, + (fee)(fee_payer_id) + (from_account)(from_amount) + (to_account)(to_account_name)(to_address)(to_amount) ) + FC_REFLECT_TYPENAME( graphene::chain::operation ) +<<<<<<< HEAD + + +======= FC_REFLECT_TYPENAME( fc::flat_set ) +>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2 diff --git a/libraries/chain/include/graphene/chain/transaction.hpp b/libraries/chain/include/graphene/chain/transaction.hpp index a048fbeb..e4d7616b 100644 --- a/libraries/chain/include/graphene/chain/transaction.hpp +++ b/libraries/chain/include/graphene/chain/transaction.hpp @@ -1,19 +1,6 @@ /* * Copyright (c) 2015, Cryptonomex, Inc. * All rights reserved. - * - * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and - * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, - * are permitted until September 8, 2015, provided that the following conditions are met: - * - * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include @@ -142,10 +129,17 @@ namespace graphene { namespace chain { : transaction(trx){} void sign( key_id_type id, const private_key_type& key ); + flat_map signatures; + /** some operations may depend only upon a signature and not + * require account approval. This allows those extra signatures + * to be added to the transaction. + */ + flat_map extra_signatures; + /// Removes all operations and signatures - void clear() { operations.clear(); signatures.clear(); } + void clear() { operations.clear(); signatures.clear(); extra_signatures.clear(); } }; /** @@ -177,6 +171,8 @@ namespace graphene { namespace chain { } } FC_REFLECT( graphene::chain::transaction, (ref_block_num)(ref_block_prefix)(relative_expiration)(operations) ) -FC_REFLECT_DERIVED( graphene::chain::signed_transaction, (graphene::chain::transaction), (signatures) ) +FC_REFLECT_DERIVED( graphene::chain::signed_transaction, + (graphene::chain::transaction), + (signatures)(extra_signatures) ) FC_REFLECT_DERIVED( graphene::chain::processed_transaction, (graphene::chain::signed_transaction), (operation_results) ) diff --git a/libraries/chain/include/graphene/chain/types.hpp b/libraries/chain/include/graphene/chain/types.hpp index 91ae6dde..e11f1d19 100644 --- a/libraries/chain/include/graphene/chain/types.hpp +++ b/libraries/chain/include/graphene/chain/types.hpp @@ -63,6 +63,9 @@ namespace graphene { namespace chain { using fc::flat_map; using fc::flat_set; using fc::static_variant; + using fc::ecc::range_proof_type; + using fc::ecc::range_proof_info; + using fc::ecc::commitment_type; typedef fc::ecc::private_key private_key_type; @@ -86,6 +89,57 @@ namespace graphene { namespace chain { }; inline bool is_relative( object_id_type o ){ return o.space() == 0; } +<<<<<<< HEAD + /** + * There are many types of fees charged by the network + * for different operations. These fees are published by + * the delegates and can change over time. + */ + enum fee_type + { + key_create_fee_type, ///< the cost to register a public key with the blockchain + account_create_fee_type, ///< the cost to register the cheapest non-free account + account_len8_fee_type, + account_len7_fee_type, + account_len6_fee_type, + account_len5_fee_type, + account_len4_fee_type, + account_len3_fee_type, + account_premium_fee_type, ///< accounts on the reserved list of top 100K domains + account_whitelist_fee_type, ///< the fee to whitelist an account + delegate_create_fee_type, ///< fixed fee for registering as a delegate, used to discourage frivioulous delegates + witness_withdraw_pay_fee_type, ///< fee for withdrawing witness pay + transfer_fee_type, ///< fee for transferring some asset + limit_order_fee_type, ///< fee for placing a limit order in the markets + short_order_fee_type, ///< fee for placing a short order in the markets + publish_feed_fee_type, ///< fee for publishing a price feed + asset_create_fee_type, ///< the cost to register the cheapest asset + asset_update_fee_type, ///< the cost to modify a registered asset + asset_issue_fee_type, ///< the cost to modify a registered asset + asset_fund_fee_pool_fee_type, ///< the cost to add funds to an asset's fee pool + asset_settle_fee_type, ///< the cost to trigger a forced settlement of a market-issued asset + market_fee_type, ///< a percentage charged on market orders + transaction_fee_type, ///< a base price for every transaction + data_fee_type, ///< a price per 1024 bytes of user data + signature_fee_type, ///< a surcharge on transactions with more than 2 signatures. + global_parameters_update_fee_type, ///< the cost to update the global parameters + prime_upgrade_fee_type, ///< the cost to upgrade an account to prime + withdraw_permission_update_fee_type, ///< the cost to create/update a withdraw permission + create_bond_offer_fee_type, + cancel_bond_offer_fee_type, + accept_bond_offer_fee_type, + claim_bond_collateral_fee_type, + file_storage_fee_per_day_type, ///< the cost of leasing a file with 2^16 bytes for 1 day + vesting_balance_create_fee_type, + vesting_balance_withdraw_fee_type, + global_settle_fee_type, + worker_create_fee_type, ///< the cost to create a new worker + worker_delete_fee_type, ///< the cost to delete a worker + blind_transfer_fee_type, ///< the cost per killobyte of the blinded transfer size + FEE_TYPE_COUNT ///< Sentry value which contains the number of different fee types + }; +======= +>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2 /** * List all object types from all namespaces here so they can @@ -225,6 +279,8 @@ namespace graphene { namespace chain { typedef fc::sha224 secret_hash_type; typedef uint16_t weight_type; + + /** * @brief An ID for some votable object * @@ -323,6 +379,56 @@ namespace graphene { namespace chain { struct fee_schedule_type { +<<<<<<< HEAD + fee_schedule_type() + { + memset( (char*)this, 0, sizeof(*this) ); + } + void set( uint32_t f, share_type v ){ FC_ASSERT( f < FEE_TYPE_COUNT && v.value <= uint32_t(-1) ); *(&key_create_fee + f) = v.value; } + const share_type at( uint32_t f )const { FC_ASSERT( f < FEE_TYPE_COUNT ); return *(&key_create_fee + f); } + size_t size()const{ return FEE_TYPE_COUNT; } + + + uint32_t key_create_fee; ///< the cost to register a public key with the blockchain + uint32_t account_create_fee; ///< the cost to register the cheapest non-free account + uint32_t account_len8_fee; + uint32_t account_len7_fee; + uint32_t account_len6_fee; + uint32_t account_len5_fee; + uint32_t account_len4_fee; + uint32_t account_len3_fee; + uint32_t account_premium_fee; ///< accounts on the reserved list of top 100K domains + uint32_t account_whitelist_fee; ///< the fee to whitelist an account + uint32_t delegate_create_fee; ///< fixed fee for registering as a delegate; used to discourage frivioulous delegates + uint32_t witness_withdraw_pay_fee; ///< fee for withdrawing witness pay + uint32_t transfer_fee; ///< fee for transferring some asset + uint32_t limit_order_fee; ///< fee for placing a limit order in the markets + uint32_t short_order_fee; ///< fee for placing a short order in the markets + uint32_t publish_feed_fee; ///< fee for publishing a price feed + uint32_t asset_create_fee; ///< the cost to register the cheapest asset + uint32_t asset_update_fee; ///< the cost to modify a registered asset + uint32_t asset_issue_fee; ///< the cost to modify a registered asset + uint32_t asset_fund_fee_pool_fee; ///< the cost to add funds to an asset's fee pool + uint32_t asset_settle_fee; ///< the cost to trigger a forced settlement of a market-issued asset + uint32_t market_fee; ///< a percentage charged on market orders + uint32_t transaction_fee; ///< a base price for every transaction + uint32_t data_fee; ///< a price per 1024 bytes of user data + uint32_t signature_fee; ///< a surcharge on transactions with more than 2 signatures. + uint32_t global_parameters_update_fee; ///< the cost to update the global parameters + uint32_t prime_upgrade_fee; ///< the cost to upgrade an account to prime + uint32_t withdraw_permission_update_fee; ///< the cost to create/update a withdraw permission + uint32_t create_bond_offer_fee; + uint32_t cancel_bond_offer_fee; + uint32_t accept_bond_offer_fee; + uint32_t claim_bond_collateral_fee; + uint32_t file_storage_fee_per_day; ///< the cost of leasing a file with 2^16 bytes for 1 day + uint32_t vesting_balance_create_fee; + uint32_t vesting_balance_withdraw_fee; + uint32_t global_settle_fee; + uint32_t worker_create_fee; ///< the cost to create a new worker + uint32_t worker_delete_fee; ///< the cost to delete a worker + uint32_t blind_transfer_fee; ///< cost per kb for blind transfers +======= /** * @brief The fee_set_visitor struct sets all fees to a particular value in one fell swoop * @@ -389,6 +495,7 @@ namespace graphene { namespace chain { uint32_t global_settle_fee; uint32_t worker_create_fee; ///< the cost to create a new worker uint32_t worker_delete_fee; ///< the cost to delete a worker +>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2 }; @@ -573,6 +680,53 @@ FC_REFLECT( graphene::chain::fee_schedule_type, (worker_delete_fee) ) +<<<<<<< HEAD + +FC_REFLECT_ENUM( graphene::chain::fee_type, + (key_create_fee_type) + (account_create_fee_type) + (account_len8_fee_type) + (account_len7_fee_type) + (account_len6_fee_type) + (account_len5_fee_type) + (account_len4_fee_type) + (account_len3_fee_type) + (account_premium_fee_type) + (account_whitelist_fee_type) + (delegate_create_fee_type) + (witness_withdraw_pay_fee_type) + (transfer_fee_type) + (limit_order_fee_type) + (short_order_fee_type) + (publish_feed_fee_type) + (asset_create_fee_type) + (asset_update_fee_type) + (asset_issue_fee_type) + (asset_fund_fee_pool_fee_type) + (asset_settle_fee_type) + (market_fee_type) + (transaction_fee_type) + (data_fee_type) + (signature_fee_type) + (global_parameters_update_fee_type) + (prime_upgrade_fee_type) + (withdraw_permission_update_fee_type) + (create_bond_offer_fee_type) + (cancel_bond_offer_fee_type) + (accept_bond_offer_fee_type) + (claim_bond_collateral_fee_type) + (file_storage_fee_per_day_type) + (vesting_balance_create_fee_type) + (vesting_balance_withdraw_fee_type) + (global_settle_fee_type) + (worker_create_fee_type) + (worker_delete_fee_type) + (blind_transfer_fee_type) + (FEE_TYPE_COUNT) + ) + +======= +>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2 FC_REFLECT( graphene::chain::chain_parameters, (current_fees) (block_interval) diff --git a/libraries/chain/operations.cpp b/libraries/chain/operations.cpp index 8805895f..2f87ba5c 100644 --- a/libraries/chain/operations.cpp +++ b/libraries/chain/operations.cpp @@ -1,19 +1,6 @@ /* * Copyright (c) 2015, Cryptonomex, Inc. * All rights reserved. - * - * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and - * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, - * are permitted until September 8, 2015, provided that the following conditions are met: - * - * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include @@ -923,6 +910,65 @@ memo_message memo_message::deserialize(const string& serial) return result; } +<<<<<<< HEAD +/** + * If fee_payer = temp_account_id, then the fee is paid by the surplus balance of inputs-outputs and + * 100% of the fee goes to the network. + */ +account_id_type blind_transfer_operation::fee_payer()const +{ + return fee_payer_id; +} + +void blind_transfer_operation::get_required_auth(flat_set& active_auth_set, flat_set&)const +{ + active_auth_set.insert( fee_payer_id ); + active_auth_set.insert( from_account ); + for( auto input : inputs ) + { + if( input.owner.which() == static_variant::tag::value ) + active_auth_set.insert( input.owner.get() ); + } +} + +/** + * This method can be computationally intensive because it verifies that input commitments - output commitments add up to 0 + */ +void blind_transfer_operation::validate()const +{ + vector in(inputs.size()); + vector out(outputs.size()); + int64_t net_public = from_amount.value - to_amount.value; + for( uint32_t i = 0; i < in.size(); ++i ) in[i] = inputs[i].commitment; + for( uint32_t i = 0; i < out.size(); ++i ) out[i] = outputs[i].commitment; + FC_ASSERT( in.size() + out.size() || net_public == 0 ); + if( fee_payer_id == GRAPHENE_TEMP_ACCOUNT ) net_public -= fee.amount.value; + FC_ASSERT( fc::ecc::verify_sum( in, out, net_public ) ); + + if( outputs.size() > 1 ) + { + for( auto out : outputs ) + { + auto info = fc::ecc::range_get_info( out.range_proof ); + FC_ASSERT( info.min_value >= 0 ); + FC_ASSERT( info.max_value <= GRAPHENE_MAX_SHARE_SUPPLY ); + } + } +} + +share_type blind_transfer_operation::calculate_fee( const fee_schedule_type& k )const +{ + auto size = 1024 + fc::raw::pack_size(*this); + return (k.blind_transfer_fee * size)/1024; +} + +void blind_transfer_operation::get_balance_delta( balance_accumulator& acc, + const operation_result& result)const +{ + acc.adjust( fee_payer(), -fee ); + acc.adjust( from_account, asset(-from_amount,fee.asset_id) ); + acc.adjust( to_account, asset(to_amount,fee.asset_id) ); +======= void account_upgrade_operation::validate() const { FC_ASSERT( fee.amount >= 0 ); @@ -933,6 +979,7 @@ share_type account_upgrade_operation::calculate_fee(const fee_schedule_type& k) if( upgrade_to_lifetime_member ) return k.membership_lifetime_fee; return k.membership_annual_fee; +>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2 } } } // namespace graphene::chain diff --git a/libraries/fc b/libraries/fc index 74a377ae..18e80eca 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 74a377aee55d2493caf4f9fa5cae5b0e78bf13e0 +Subproject commit 18e80eca239c5c2b0e349091d3d0894196b7b895 diff --git a/tests/intense/block_tests.cpp b/tests/intense/block_tests.cpp index f603fb74..993cf074 100644 --- a/tests/intense/block_tests.cpp +++ b/tests/intense/block_tests.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -252,7 +253,7 @@ BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture ) * This test checks the requirement using Monte Carlo approach * (produce lots of blocks and check the invariant holds). */ -BOOST_FIXTURE_TEST_CASE( delegate_groups_mc_test, database_fixture ) +BOOST_FIXTURE_TEST_CASE( witness_order_mc_test, database_fixture ) { try { size_t num_witnesses = db.get_global_properties().active_witnesses.size(); @@ -267,6 +268,7 @@ BOOST_FIXTURE_TEST_CASE( delegate_groups_mc_test, database_fixture ) cur_round.reserve( num_witnesses ); full_schedule.reserve( total_blocks ); + cur_round.push_back( db.get_dynamic_global_properties().current_witness ); // we assert so the test doesn't continue, which would // corrupt memory @@ -274,12 +276,15 @@ BOOST_FIXTURE_TEST_CASE( delegate_groups_mc_test, database_fixture ) while( full_schedule.size() < total_blocks ) { + if( (db.head_block_num() & 0x3FFF) == 0 ) + { + wdump( (db.head_block_num()) ); + } witness_id_type wid = db.get_scheduled_witness( 1 ).first; full_schedule.push_back( wid ); cur_round.push_back( wid ); if( cur_round.size() == num_witnesses ) { - wdump( (cur_round) ); // check that the current round contains exactly 1 copy // of each witness witness_seen.reset(); @@ -310,4 +315,92 @@ BOOST_FIXTURE_TEST_CASE( delegate_groups_mc_test, database_fixture ) } } +/** + * To have a secure random number we need to ensure that the same + * delegate does not get to produce two blocks in a row. There is + * always a chance that the last delegate of one round will be the + * first delegate of the next round. + * + * This means that when we shuffle delegates we need to make sure + * that there is at least N/2 delegates between consecutive turns + * of the same delegate. This means that durring the random + * shuffle we need to restrict the placement of delegates to maintain + * this invariant. + * + * This test checks the requirement using Monte Carlo approach + * (produce lots of blocks and check the invariant holds). + */ +BOOST_FIXTURE_TEST_CASE( generic_scheduler_mc_test, database_fixture ) +{ + try { + size_t num_witnesses = db.get_global_properties().active_witnesses.size(); + size_t dmin = num_witnesses >> 1; + witness_scheduler_rng rng( + // - - - - + - - - - 1 - - - - + - - - - 2 - - - - + - - - + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + ); + witness_scheduler scheduler; + vector< witness_id_type > witness_ids; + + witness_ids.reserve( num_witnesses ); + for( size_t i=0; i cur_round; + vector< witness_id_type > full_schedule; + // if we make the maximum witness count testable, + // we'll need to enlarge this. + std::bitset< 0x40 > witness_seen; + size_t total_blocks = 1000000; + + cur_round.reserve( num_witnesses ); + full_schedule.reserve( total_blocks ); + + // we assert so the test doesn't continue, which would + // corrupt memory + assert( num_witnesses <= witness_seen.size() ); + + while( full_schedule.size() < total_blocks ) + { + scheduler.produce_schedule( rng ); + witness_id_type wid = scheduler.consume_schedule(); + full_schedule.push_back( wid ); + cur_round.push_back( wid ); + if( cur_round.size() == num_witnesses ) + { + // check that the current round contains exactly 1 copy + // of each witness + witness_seen.reset(); + for( const witness_id_type& w : cur_round ) + { + uint64_t inst = w.instance.value; + BOOST_CHECK( !witness_seen.test( inst ) ); + assert( !witness_seen.test( inst ) ); + witness_seen.set( inst ); + } + cur_round.clear(); + } + } + + for( size_t i=0,m=full_schedule.size(); i