Merge branch 'github_master'
Conflicts: .gitmodules libraries/fc
This commit is contained in:
commit
52f66b6c7a
14 changed files with 524 additions and 53 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
||||||
*.a
|
*.a
|
||||||
*.sw*
|
*.sw*
|
||||||
|
|
||||||
|
*.cmake
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
CMakeFiles
|
CMakeFiles
|
||||||
Makefile
|
Makefile
|
||||||
|
|
@ -19,7 +20,13 @@ tests/chain_test
|
||||||
tests/intense_test
|
tests/intense_test
|
||||||
tests/performance_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
|
witness_node_data_dir
|
||||||
wallet.json
|
wallet.json
|
||||||
|
|
|
||||||
4
.gitmodules
vendored
4
.gitmodules
vendored
|
|
@ -1,11 +1,11 @@
|
||||||
[submodule "docs"]
|
[submodule "docs"]
|
||||||
path = docs
|
path = docs
|
||||||
url = git@github.com:cryptonomex/graphene.wiki.git
|
url = https://github.com/cryptonomex/graphene.wiki.git
|
||||||
[submodule "libraries/fc"]
|
[submodule "libraries/fc"]
|
||||||
path = libraries/fc
|
path = libraries/fc
|
||||||
url = git@git.syncad.com:/fc.git
|
url = git@git.syncad.com:/fc.git
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "libraries/leveldb"]
|
[submodule "libraries/leveldb"]
|
||||||
path = libraries/leveldb
|
path = libraries/leveldb
|
||||||
url = git@github.com:bitcoin/leveldb.git
|
url = https://github.com/bitcoin/leveldb.git
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ namespace graphene { namespace chain {
|
||||||
FC_ASSERT( base.amount > share_type(0) );
|
FC_ASSERT( base.amount > share_type(0) );
|
||||||
FC_ASSERT( quote.amount > share_type(0) );
|
FC_ASSERT( quote.amount > share_type(0) );
|
||||||
FC_ASSERT( base.asset_id != quote.asset_id );
|
FC_ASSERT( base.asset_id != quote.asset_id );
|
||||||
} FC_CAPTURE_AND_RETHROW() }
|
} FC_CAPTURE_AND_RETHROW( (base)(quote) ) }
|
||||||
|
|
||||||
void price_feed::validate() const
|
void price_feed::validate() const
|
||||||
{ try {
|
{ try {
|
||||||
|
|
@ -133,6 +133,7 @@ namespace graphene { namespace chain {
|
||||||
FC_ASSERT( required_maintenance_collateral < required_initial_collateral );
|
FC_ASSERT( required_maintenance_collateral < required_initial_collateral );
|
||||||
FC_ASSERT( required_maintenance_collateral >= 1000 );
|
FC_ASSERT( required_maintenance_collateral >= 1000 );
|
||||||
FC_ASSERT( call_limit.is_null() || call_limit < ~short_limit );
|
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
|
} } // graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
|
||||||
_wso.scheduler._min_token_count = init_witnesses.size() / 2;
|
_wso.scheduler._min_token_count = init_witnesses.size() / 2;
|
||||||
_wso.scheduler.update( init_witness_set );
|
_wso.scheduler.update( init_witness_set );
|
||||||
|
|
||||||
for( int i=0; i<init_witnesses.size(); i++ )
|
for( size_t i=0; i<init_witnesses.size(); i++ )
|
||||||
_wso.scheduler.produce_schedule( rng );
|
_wso.scheduler.produce_schedule( rng );
|
||||||
|
|
||||||
_wso.last_scheduling_block = 0;
|
_wso.last_scheduling_block = 0;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ pair<witness_id_type, bool> database::get_scheduled_witness(uint32_t slot_num)co
|
||||||
|
|
||||||
// ask the near scheduler who goes in the given slot
|
// ask the near scheduler who goes in the given slot
|
||||||
witness_id_type wid;
|
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( ! slot_is_near )
|
||||||
{
|
{
|
||||||
// if the near scheduler doesn't know, we have to extend it to
|
// if the near scheduler doesn't know, we have to extend it to
|
||||||
|
|
@ -47,7 +47,7 @@ pair<witness_id_type, bool> database::get_scheduled_witness(uint32_t slot_num)co
|
||||||
|
|
||||||
far_future_witness_scheduler far_scheduler =
|
far_future_witness_scheduler far_scheduler =
|
||||||
far_future_witness_scheduler(wso.scheduler, far_rng);
|
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
|
// no scheduled witness -- somebody set up us the bomb
|
||||||
// n.b. this code path is impossible, the present
|
// n.b. this code path is impossible, the present
|
||||||
|
|
@ -84,7 +84,7 @@ vector<witness_id_type> database::get_near_witness_schedule()const
|
||||||
|
|
||||||
vector<witness_id_type> result;
|
vector<witness_id_type> result;
|
||||||
result.reserve(wso.scheduler.size());
|
result.reserve(wso.scheduler.size());
|
||||||
uint32_t slot_num = 1;
|
uint32_t slot_num = 0;
|
||||||
witness_id_type wid;
|
witness_id_type wid;
|
||||||
|
|
||||||
while( wso.scheduler.get_slot(slot_num++, wid) )
|
while( wso.scheduler.get_slot(slot_num++, wid) )
|
||||||
|
|
|
||||||
|
|
@ -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<blinded_balance_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<account_id_type> 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<by_id>, member< object, object_id_type, &object::id > >,
|
||||||
|
hashed_unique< tag<by_commitment>, member<blinded_balance_object, commitment_type, &blinded_balance_object::commitment> >,
|
||||||
|
ordered_non_unique< tag<by_owner>, member<blinded_balance_object, account_id_type, &blinded_balance_object::owner> >,
|
||||||
|
ordered_non_unique< tag<by_asset>, member<blinded_balance_object, asset_id_type, &blinded_balance_object::asset_type> >
|
||||||
|
>
|
||||||
|
> blinded_balance_object_multi_index_type;
|
||||||
|
typedef generic_index<blinded_balance_object, blinded_balance_object_multi_index_type> balance_index;
|
||||||
|
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
FC_REFLECT( graphene::chain::blinded_balance_object, (commitment)(asset_id)(last_update_block_num)(owner) )
|
||||||
|
|
@ -114,3 +114,13 @@
|
||||||
#define GRAPHENE_MAX_INTEREST_APR uint16_t( 10000 )
|
#define GRAPHENE_MAX_INTEREST_APR uint16_t( 10000 )
|
||||||
#define GRAPHENE_LEGACY_NAME_IMPORT_PERIOD 3000000 /** 3 million blocks */
|
#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))
|
||||||
|
///@}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||||
* All rights reserved.
|
* 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
|
#pragma once
|
||||||
#include <graphene/db/object.hpp>
|
#include <graphene/db/object.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 ); }
|
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.
|
* @brief Create a delegate object, as a bid to hold a delegate seat on the network.
|
||||||
* @ingroup operations
|
* @ingroup operations
|
||||||
|
|
@ -295,6 +297,7 @@ namespace graphene { namespace chain {
|
||||||
share_type calculate_fee( const fee_schedule_type& k )const;
|
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 ); }
|
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.
|
* @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<address,account_id_type> 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<address,account_id_type> 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<char> 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<address> to_address;
|
||||||
|
vector<blind_input> inputs;
|
||||||
|
vector<blind_output> outputs;
|
||||||
|
|
||||||
|
account_id_type fee_payer()const;
|
||||||
|
void get_required_auth( flat_set<account_id_type>& active_auth_set,
|
||||||
|
flat_set<account_id_type>& )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
|
* @ingroup operations
|
||||||
*/
|
*/
|
||||||
|
|
@ -1503,6 +1614,7 @@ namespace graphene { namespace chain {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup workers The Blockchain Worker System
|
* @defgroup workers The Blockchain Worker System
|
||||||
* @ingroup operations
|
* @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::custom_operation, (fee)(payer)(required_auths)(id)(data) )
|
||||||
FC_REFLECT( graphene::chain::void_result, )
|
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 )
|
FC_REFLECT_TYPENAME( graphene::chain::operation )
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
|
|
||||||
|
=======
|
||||||
FC_REFLECT_TYPENAME( fc::flat_set<graphene::chain::vote_id_type> )
|
FC_REFLECT_TYPENAME( fc::flat_set<graphene::chain::vote_id_type> )
|
||||||
|
>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||||
* All rights reserved.
|
* 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
|
#pragma once
|
||||||
#include <graphene/chain/types.hpp>
|
#include <graphene/chain/types.hpp>
|
||||||
|
|
@ -142,10 +129,17 @@ namespace graphene { namespace chain {
|
||||||
: transaction(trx){}
|
: transaction(trx){}
|
||||||
|
|
||||||
void sign( key_id_type id, const private_key_type& key );
|
void sign( key_id_type id, const private_key_type& key );
|
||||||
|
|
||||||
flat_map<key_id_type,signature_type> signatures;
|
flat_map<key_id_type,signature_type> 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<address,signature_type> extra_signatures;
|
||||||
|
|
||||||
/// Removes all operations and 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( 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) )
|
FC_REFLECT_DERIVED( graphene::chain::processed_transaction, (graphene::chain::signed_transaction), (operation_results) )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,9 @@ namespace graphene { namespace chain {
|
||||||
using fc::flat_map;
|
using fc::flat_map;
|
||||||
using fc::flat_set;
|
using fc::flat_set;
|
||||||
using fc::static_variant;
|
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;
|
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; }
|
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
|
* 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 fc::sha224 secret_hash_type;
|
||||||
typedef uint16_t weight_type;
|
typedef uint16_t weight_type;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An ID for some votable object
|
* @brief An ID for some votable object
|
||||||
*
|
*
|
||||||
|
|
@ -323,6 +379,56 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
struct fee_schedule_type
|
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
|
* @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 global_settle_fee;
|
||||||
uint32_t worker_create_fee; ///< the cost to create a new worker
|
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 worker_delete_fee; ///< the cost to delete a worker
|
||||||
|
>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -573,6 +680,53 @@ FC_REFLECT( graphene::chain::fee_schedule_type,
|
||||||
(worker_delete_fee)
|
(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,
|
FC_REFLECT( graphene::chain::chain_parameters,
|
||||||
(current_fees)
|
(current_fees)
|
||||||
(block_interval)
|
(block_interval)
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||||
* All rights reserved.
|
* 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 <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
#include <graphene/chain/operations.hpp>
|
#include <graphene/chain/operations.hpp>
|
||||||
|
|
@ -923,6 +910,65 @@ memo_message memo_message::deserialize(const string& serial)
|
||||||
return result;
|
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<account_id_type>& active_auth_set, flat_set<account_id_type>&)const
|
||||||
|
{
|
||||||
|
active_auth_set.insert( fee_payer_id );
|
||||||
|
active_auth_set.insert( from_account );
|
||||||
|
for( auto input : inputs )
|
||||||
|
{
|
||||||
|
if( input.owner.which() == static_variant<address,account_id_type>::tag<account_id_type>::value )
|
||||||
|
active_auth_set.insert( input.owner.get<account_id_type>() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<commitment_type> in(inputs.size());
|
||||||
|
vector<commitment_type> 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
|
void account_upgrade_operation::validate() const
|
||||||
{
|
{
|
||||||
FC_ASSERT( fee.amount >= 0 );
|
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 )
|
if( upgrade_to_lifetime_member )
|
||||||
return k.membership_lifetime_fee;
|
return k.membership_lifetime_fee;
|
||||||
return k.membership_annual_fee;
|
return k.membership_annual_fee;
|
||||||
|
>>>>>>> dfee44a40827e40becf4d8f21bff5b2bfa1303a2
|
||||||
}
|
}
|
||||||
|
|
||||||
} } // namespace graphene::chain
|
} } // namespace graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 74a377aee55d2493caf4f9fa5cae5b0e78bf13e0
|
Subproject commit 18e80eca239c5c2b0e349091d3d0894196b7b895
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include <graphene/chain/key_object.hpp>
|
#include <graphene/chain/key_object.hpp>
|
||||||
#include <graphene/chain/account_object.hpp>
|
#include <graphene/chain/account_object.hpp>
|
||||||
#include <graphene/chain/proposal_object.hpp>
|
#include <graphene/chain/proposal_object.hpp>
|
||||||
|
#include <graphene/chain/witness_schedule_object.hpp>
|
||||||
|
|
||||||
#include <fc/crypto/digest.hpp>
|
#include <fc/crypto/digest.hpp>
|
||||||
|
|
||||||
|
|
@ -252,7 +253,7 @@ BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture )
|
||||||
* This test checks the requirement using Monte Carlo approach
|
* This test checks the requirement using Monte Carlo approach
|
||||||
* (produce lots of blocks and check the invariant holds).
|
* (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 {
|
try {
|
||||||
size_t num_witnesses = db.get_global_properties().active_witnesses.size();
|
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 );
|
cur_round.reserve( num_witnesses );
|
||||||
full_schedule.reserve( total_blocks );
|
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
|
// we assert so the test doesn't continue, which would
|
||||||
// corrupt memory
|
// corrupt memory
|
||||||
|
|
@ -274,12 +276,15 @@ BOOST_FIXTURE_TEST_CASE( delegate_groups_mc_test, database_fixture )
|
||||||
|
|
||||||
while( full_schedule.size() < total_blocks )
|
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;
|
witness_id_type wid = db.get_scheduled_witness( 1 ).first;
|
||||||
full_schedule.push_back( wid );
|
full_schedule.push_back( wid );
|
||||||
cur_round.push_back( wid );
|
cur_round.push_back( wid );
|
||||||
if( cur_round.size() == num_witnesses )
|
if( cur_round.size() == num_witnesses )
|
||||||
{
|
{
|
||||||
wdump( (cur_round) );
|
|
||||||
// check that the current round contains exactly 1 copy
|
// check that the current round contains exactly 1 copy
|
||||||
// of each witness
|
// of each witness
|
||||||
witness_seen.reset();
|
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<num_witnesses; i++ )
|
||||||
|
witness_ids.push_back( witness_id_type(i) );
|
||||||
|
|
||||||
|
scheduler._min_token_count = num_witnesses / 2;
|
||||||
|
|
||||||
|
scheduler.insert_all( witness_ids );
|
||||||
|
for( size_t i=0; i<num_witnesses; i++ )
|
||||||
|
scheduler.produce_schedule( rng );
|
||||||
|
|
||||||
|
vector< witness_id_type > 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<m; i++ )
|
||||||
|
{
|
||||||
|
for( size_t j=i+1,n=std::min( m, i+dmin ); j<n; j++ )
|
||||||
|
{
|
||||||
|
BOOST_CHECK( full_schedule[i] != full_schedule[j] );
|
||||||
|
assert( full_schedule[i] != full_schedule[j] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (fc::exception& e) {
|
||||||
|
edump((e.to_detail_string()));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue