未验证 提交 31458635 编写于 作者: D Daniel Larimer 提交者: GitHub

Merge pull request #660 from pavybez/blk_ts

First implementation of block_timestamp
...@@ -1079,7 +1079,7 @@ void chain_controller::require_account(const types::AccountName& name) const { ...@@ -1079,7 +1079,7 @@ void chain_controller::require_account(const types::AccountName& name) const {
const producer_object& chain_controller::validate_block_header(uint32_t skip, const signed_block& next_block)const { const producer_object& chain_controller::validate_block_header(uint32_t skip, const signed_block& next_block)const {
EOS_ASSERT(head_block_id() == next_block.previous, block_validate_exception, "", EOS_ASSERT(head_block_id() == next_block.previous, block_validate_exception, "",
("head_block_id",head_block_id())("next.prev",next_block.previous)); ("head_block_id",head_block_id())("next.prev",next_block.previous));
EOS_ASSERT(head_block_time() < next_block.timestamp, block_validate_exception, "", EOS_ASSERT(head_block_time() < (fc::time_point_sec)next_block.timestamp, block_validate_exception, "",
("head_block_time",head_block_time())("next",next_block.timestamp)("blocknum",next_block.block_num())); ("head_block_time",head_block_time())("next",next_block.timestamp)("blocknum",next_block.block_num()));
if (next_block.block_num() % config::BlocksPerRound != 0) { if (next_block.block_num() % config::BlocksPerRound != 0) {
EOS_ASSERT(next_block.producer_changes.empty(), block_validate_exception, EOS_ASSERT(next_block.producer_changes.empty(), block_validate_exception,
...@@ -1091,7 +1091,7 @@ const producer_object& chain_controller::validate_block_header(uint32_t skip, co ...@@ -1091,7 +1091,7 @@ const producer_object& chain_controller::validate_block_header(uint32_t skip, co
block_validate_exception, "Producer changes are not sorted correctly", block_validate_exception, "Producer changes are not sorted correctly",
("changes", next_block.producer_changes)); ("changes", next_block.producer_changes));
} }
const producer_object& producer = get_producer(get_scheduled_producer(get_slot_at_time(next_block.timestamp))); const producer_object& producer = get_producer(get_scheduled_producer(get_slot_at_time((fc::time_point)next_block.timestamp)));
if(!(skip&skip_producer_signature)) if(!(skip&skip_producer_signature))
EOS_ASSERT(next_block.validate_signee(producer.signing_key), block_validate_exception, EOS_ASSERT(next_block.validate_signee(producer.signing_key), block_validate_exception,
...@@ -1157,6 +1157,10 @@ const dynamic_global_property_object&chain_controller::get_dynamic_global_proper ...@@ -1157,6 +1157,10 @@ const dynamic_global_property_object&chain_controller::get_dynamic_global_proper
} }
time_point_sec chain_controller::head_block_time()const { time_point_sec chain_controller::head_block_time()const {
return (time_point)head_block_timestamp();
}
block_timestamp_type chain_controller::head_block_timestamp()const {
return get_dynamic_global_properties().time; return get_dynamic_global_properties().time;
} }
...@@ -1355,8 +1359,9 @@ ProducerRound chain_controller::calculate_next_round(const signed_block& next_bl ...@@ -1355,8 +1359,9 @@ ProducerRound chain_controller::calculate_next_round(const signed_block& next_bl
EOS_ASSERT(boost::range::equal(next_block.producer_changes, changes), block_validate_exception, EOS_ASSERT(boost::range::equal(next_block.producer_changes, changes), block_validate_exception,
"Unexpected round changes in new block header", "Unexpected round changes in new block header",
("expected changes", changes)("block changes", next_block.producer_changes)); ("expected changes", changes)("block changes", next_block.producer_changes));
utilities::rand::random rng(next_block.timestamp.sec_since_epoch()); fc::time_point tp = (fc::time_point)next_block.timestamp;
utilities::rand::random rng(tp.sec_since_epoch());
rng.shuffle(schedule); rng.shuffle(schedule);
return schedule; return schedule;
} }
...@@ -1364,7 +1369,7 @@ ProducerRound chain_controller::calculate_next_round(const signed_block& next_bl ...@@ -1364,7 +1369,7 @@ ProducerRound chain_controller::calculate_next_round(const signed_block& next_bl
void chain_controller::update_global_dynamic_data(const signed_block& b) { void chain_controller::update_global_dynamic_data(const signed_block& b) {
const dynamic_global_property_object& _dgp = _db.get<dynamic_global_property_object>(); const dynamic_global_property_object& _dgp = _db.get<dynamic_global_property_object>();
uint32_t missed_blocks = head_block_num() == 0? 1 : get_slot_at_time(b.timestamp); uint32_t missed_blocks = head_block_num() == 0? 1 : get_slot_at_time((fc::time_point)b.timestamp);
assert(missed_blocks != 0); assert(missed_blocks != 0);
missed_blocks--; missed_blocks--;
...@@ -1409,7 +1414,7 @@ void chain_controller::update_global_dynamic_data(const signed_block& b) { ...@@ -1409,7 +1414,7 @@ void chain_controller::update_global_dynamic_data(const signed_block& b) {
void chain_controller::update_signing_producer(const producer_object& signing_producer, const signed_block& new_block) void chain_controller::update_signing_producer(const producer_object& signing_producer, const signed_block& new_block)
{ {
const dynamic_global_property_object& dpo = get_dynamic_global_properties(); const dynamic_global_property_object& dpo = get_dynamic_global_properties();
uint64_t new_block_aslot = dpo.current_absolute_slot + get_slot_at_time( new_block.timestamp ); uint64_t new_block_aslot = dpo.current_absolute_slot + get_slot_at_time( (fc::time_point)new_block.timestamp );
_db.modify( signing_producer, [&]( producer_object& _wit ) _db.modify( signing_producer, [&]( producer_object& _wit )
{ {
...@@ -1490,36 +1495,38 @@ types::AccountName chain_controller::get_scheduled_producer(uint32_t slot_num)co ...@@ -1490,36 +1495,38 @@ types::AccountName chain_controller::get_scheduled_producer(uint32_t slot_num)co
const dynamic_global_property_object& dpo = get_dynamic_global_properties(); const dynamic_global_property_object& dpo = get_dynamic_global_properties();
uint64_t current_aslot = dpo.current_absolute_slot + slot_num; uint64_t current_aslot = dpo.current_absolute_slot + slot_num;
const auto& gpo = _db.get<global_property_object>(); const auto& gpo = _db.get<global_property_object>();
return gpo.active_producers[current_aslot % gpo.active_producers.size()]; auto number_of_active_producers = gpo.active_producers.size();
auto index = current_aslot % (number_of_active_producers * 4); //TODO configure number of repetitions by producer
index /= 4;
return gpo.active_producers[index];
} }
fc::time_point_sec chain_controller::get_slot_time(uint32_t slot_num)const fc::time_point_sec chain_controller::get_slot_time(uint32_t slot_num)const
{ {
if( slot_num == 0 ) if( slot_num == 0)
return fc::time_point_sec(); return (fc::time_point)block_timestamp_type();
auto interval = block_interval();
const dynamic_global_property_object& dpo = get_dynamic_global_properties(); const dynamic_global_property_object& dpo = get_dynamic_global_properties();
if( head_block_num() == 0 ) if( head_block_num() == 0 )
{ {
// n.b. first block is at genesis_time plus one block interval // n.b. first block is at genesis_time plus one block interval
fc::time_point_sec genesis_time = dpo.time; auto genesis_time = block_timestamp_type(dpo.time);
return genesis_time + slot_num * interval; genesis_time.slot += slot_num;
return (fc::time_point)genesis_time;
} }
int64_t head_block_abs_slot = head_block_time().sec_since_epoch() / interval; auto head_block_abs_slot = head_block_timestamp();
fc::time_point_sec head_slot_time(head_block_abs_slot * interval); head_block_abs_slot.slot += slot_num;
return (fc::time_point)head_block_abs_slot;
return head_slot_time + (slot_num * interval);
} }
uint32_t chain_controller::get_slot_at_time(fc::time_point_sec when)const uint32_t chain_controller::get_slot_at_time(fc::time_point_sec when)const
{ {
fc::time_point_sec first_slot_time = get_slot_time( 1 ); fc::time_point_sec first_slot_time = get_slot_time(1);
if( when < first_slot_time ) if( when < first_slot_time )
return 0; return 0;
return (when - first_slot_time).to_seconds() / block_interval() + 1; return block_timestamp_type(when).slot - block_timestamp_type(first_slot_time).slot + 1;
} }
uint32_t chain_controller::producer_participation_rate()const uint32_t chain_controller::producer_participation_rate()const
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* @copyright defined in eos/LICENSE.txt * @copyright defined in eos/LICENSE.txt
*/ */
#pragma once #pragma once
#include <eos/chain/block_timestamp.hpp>
#include <eos/chain/transaction.hpp> #include <eos/chain/transaction.hpp>
namespace eosio { namespace chain { namespace eosio { namespace chain {
...@@ -15,7 +16,7 @@ namespace eosio { namespace chain { ...@@ -15,7 +16,7 @@ namespace eosio { namespace chain {
block_id_type previous; block_id_type previous;
fc::time_point_sec timestamp; block_timestamp_type timestamp;
checksum_type transaction_merkle_root; checksum_type transaction_merkle_root;
AccountName producer; AccountName producer;
/** /**
......
#pragma once
#include <stdint.h>
#include <fc/time.hpp>
#include <fc/variant.hpp>
#include <fc/string.hpp>
#include <fc/optional.hpp>
namespace eosio { namespace chain {
/**
* This class is used in the block headers to represent the block time
* It is a parameterised class that takes an Epoch in milliseconds and
* and an interval in milliseconds and computes the number of slots.
**/
template<uint16_t Interval, uint64_t EpochMs>
class block_timestamp {
public:
explicit block_timestamp( uint32_t s=0 ) :slot(s){}
block_timestamp(const fc::time_point& t) {
set_time_point(t);
}
block_timestamp(const fc::time_point_sec& t) {
set_time_point(t);
}
static block_timestamp maximum() { return block_timestamp( 0xffff ); }
static block_timestamp min() { return block_timestamp(0); }
operator fc::time_point() const {
int64_t msec = slot * (int64_t)Interval;
msec += EpochMs;
return fc::time_point(fc::microseconds(msec * 1000));
}
void operator = (const fc::time_point& t ) {
set_time_point(t);
}
void operator = (const fc::time_point_sec& t ) {
set_time_point(t);
}
bool operator > ( const block_timestamp& t )const { return slot > t.slot; }
bool operator >=( const block_timestamp& t )const { return slot >= t.slot; }
bool operator < ( const block_timestamp& t )const { return slot < t.slot; }
bool operator <=( const block_timestamp& t )const { return slot <= t.slot; }
bool operator ==( const block_timestamp& t )const { return slot == t.slot; }
bool operator !=( const block_timestamp& t )const { return slot != t.slot; }
uint32_t slot;
private:
void set_time_point(const fc::time_point& t) {
auto micro_since_epoch = t.time_since_epoch();
auto msec_since_epoch = micro_since_epoch.count() / 1000;
slot = ( msec_since_epoch - EpochMs ) / Interval;
}
void set_time_point(const fc::time_point_sec& t) {
uint64_t sec_since_epoch = t.sec_since_epoch();
slot = (sec_since_epoch * 1000 - EpochMs) / Interval;
}
}; // block_timestamp
typedef block_timestamp<3000,946684800000ll> block_timestamp_type; // epoch is year 2000.
} } /// eosio::chain
#include <fc/reflect/reflect.hpp>
FC_REFLECT(eosio::chain::block_timestamp_type, (slot))
namespace fc {
template<uint16_t Interval, uint64_t EpochMs>
void to_variant(const eosio::chain::block_timestamp<Interval,EpochMs>& t, fc::variant& v) {
auto tp = (fc::time_point)t;
to_variant(tp, v);
}
template<uint16_t Interval, uint64_t EpochMs>
void from_variant(const fc::variant& v, eosio::chain::block_timestamp<Interval,EpochMs>& t) {
fc::microseconds mc;
from_variant(v, mc);
t = fc::time_point(mc);
}
}
#ifdef _MSC_VER
#pragma warning (pop)
#endif /// #ifdef _MSC_VER
...@@ -252,10 +252,11 @@ namespace eosio { namespace chain { ...@@ -252,10 +252,11 @@ namespace eosio { namespace chain {
const dynamic_global_property_object& get_dynamic_global_properties()const; const dynamic_global_property_object& get_dynamic_global_properties()const;
const producer_object& get_producer(const AccountName& ownerName)const; const producer_object& get_producer(const AccountName& ownerName)const;
time_point_sec head_block_time()const; time_point_sec head_block_time()const;
uint32_t head_block_num()const; block_timestamp_type head_block_timestamp() const;
block_id_type head_block_id()const; uint32_t head_block_num()const;
AccountName head_block_producer()const; block_id_type head_block_id()const;
AccountName head_block_producer()const;
uint32_t block_interval()const { return config::BlockIntervalSeconds; } uint32_t block_interval()const { return config::BlockIntervalSeconds; }
......
...@@ -53,7 +53,8 @@ const static UInt32 DefaultMaxInlineMsgSize = 4 * 1024; ...@@ -53,7 +53,8 @@ const static UInt32 DefaultMaxInlineMsgSize = 4 * 1024;
const static UInt32 DefaultMaxGenTrxSize = 64 * 1024; const static UInt32 DefaultMaxGenTrxSize = 64 * 1024;
const static UInt32 ProducersAuthorityThreshold = 14; const static UInt32 ProducersAuthorityThreshold = 14;
const static int BlocksPerRound = 21; const static int ProducerRepetitions = 4;
const static int BlocksPerRound = 21 * ProducerRepetitions;
const static int VotedProducersPerRound = 20; const static int VotedProducersPerRound = 20;
const static int IrreversibleThresholdPercent = 70 * Percent1; const static int IrreversibleThresholdPercent = 70 * Percent1;
const static int MaxProducerVotes = 30; const static int MaxProducerVotes = 30;
......
...@@ -7,10 +7,9 @@ ...@@ -7,10 +7,9 @@
#include <fc/array.hpp> #include <fc/array.hpp>
#include <eos/chain/types.hpp> #include <eos/chain/types.hpp>
#include <eos/chain/block_timestamp.hpp>
#include <eos/chain/BlockchainConfiguration.hpp> #include <eos/chain/BlockchainConfiguration.hpp>
#include <chainbase/chainbase.hpp> #include <chainbase/chainbase.hpp>
#include "multi_index_includes.hpp" #include "multi_index_includes.hpp"
namespace eosio { namespace chain { namespace eosio { namespace chain {
...@@ -47,12 +46,12 @@ namespace eosio { namespace chain { ...@@ -47,12 +46,12 @@ namespace eosio { namespace chain {
{ {
OBJECT_CTOR(dynamic_global_property_object) OBJECT_CTOR(dynamic_global_property_object)
id_type id; id_type id;
uint32_t head_block_number = 0; uint32_t head_block_number = 0;
block_id_type head_block_id; block_id_type head_block_id;
time_point_sec time; fc::time_point time;
AccountName current_producer; AccountName current_producer;
uint32_t accounts_registered_this_interval = 0; uint32_t accounts_registered_this_interval = 0;
/** /**
* The current absolute slot number. Equal to the total * The current absolute slot number. Equal to the total
......
...@@ -26,7 +26,6 @@ if(WASM_TOOLCHAIN) ...@@ -26,7 +26,6 @@ if(WASM_TOOLCHAIN)
target_link_libraries( slow_test eos_native_contract eos_chain chainbase eos_utilities eos_egenesis_none chain_plugin producer_plugin fc ${PLATFORM_SPECIFIC_LIBS} ) target_link_libraries( slow_test eos_native_contract eos_chain chainbase eos_utilities eos_egenesis_none chain_plugin producer_plugin fc ${PLATFORM_SPECIFIC_LIBS} )
target_include_directories( slow_test PUBLIC ${CMAKE_BINARY_DIR}/contracts ) target_include_directories( slow_test PUBLIC ${CMAKE_BINARY_DIR}/contracts )
add_dependencies(slow_test currency exchange) add_dependencies(slow_test currency exchange)
add_subdirectory(api_tests/memory_test) add_subdirectory(api_tests/memory_test)
add_subdirectory(api_tests/extended_memory_test) add_subdirectory(api_tests/extended_memory_test)
add_subdirectory(api_tests/table_abi_test) add_subdirectory(api_tests/table_abi_test)
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <boost/test/unit_test.hpp>
#include <eos/chain/block_timestamp.hpp>
#include <fc/time.hpp>
#include <fc/exception/exception.hpp>
using namespace eosio;
using namespace chain;
BOOST_AUTO_TEST_SUITE(block_timestamp_tests)
BOOST_AUTO_TEST_CASE(constructor_test) {
block_timestamp_type bt;
BOOST_TEST( bt.slot == 0, "Default constructor gives wrong value");
fc::time_point t(fc::seconds(978307200));
block_timestamp_type bt2(t);
BOOST_TEST( bt2.slot == (978307200 - 946684800)*2, "Time point constructor gives wrong value");
}
BOOST_AUTO_TEST_CASE(conversion_test) {
block_timestamp_type bt;
fc::time_point t = (fc::time_point)bt;
BOOST_TEST(t.time_since_epoch().to_seconds() == 946684800ll, "Time point conversion failed");
block_timestamp_type bt1(200);
t = (fc::time_point)bt1;
BOOST_TEST(t.time_since_epoch().to_seconds() == 946684900ll, "Time point conversion failed");
}
BOOST_AUTO_TEST_SUITE_END()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册