提交 c75a6ff1 编写于 作者: A Anton Perkov

Merge branch 'system-contract-voting-2' of github.com:EOSIO/eos into system-contract-voting-2

......@@ -6,11 +6,38 @@
#include "voting.hpp"
#include "delegate_bandwith.hpp"
#include <eosiolib/optional.hpp>
#include <eosiolib/generic_currency.hpp>
namespace eosiosystem {
struct PACKED(producer_key) {
account_name producer_name;
public_key block_signing_key;
EOSLIB_SERIALIZE(producer_key, (producer_name)(block_signing_key))
};
struct PACKED(producer_schedule) {
uint32_t version;
std::vector<producer_key> producers;
EOSLIB_SERIALIZE(producer_schedule, (version)(producers))
};
struct PACKED(block_header) {
checksum256 previous;
time timestamp;
checksum256 transaction_mroot;
checksum256 action_mroot;
checksum256 block_mroot;
account_name producer;
eosio::optional<producer_schedule> new_producers;
EOSLIB_SERIALIZE(block_header, (previous)(timestamp)(transaction_mroot)(action_mroot)(block_mroot)(producer)(new_producers))
};
template<account_name SystemAccount>
class contract : public voting<SystemAccount>, public delegate_bandwith<SystemAccount> {
public:
......@@ -29,6 +56,15 @@ namespace eosiosystem {
static void on( const nonce& ) {
}
ACTION(SystemAccount, onblock) {
block_header header;
EOSLIB_SERIALIZE(onblock, (header))
};
static void on(const onblock& ob) {
}
static void apply( account_name code, action_name act ) {
if ( !eosio::dispatch<currency, typename currency::transfer, typename currency::issue>( code, act ) ) {
if( !eosio::dispatch<contract, typename delegate_bandwith<SystemAccount>::delegatebw,
......@@ -40,6 +76,7 @@ namespace eosiosystem {
typename voting<SystemAccount>::stakevote,
typename voting<SystemAccount>::unstakevote,
typename voting<SystemAccount>::unstake_vote_deferred,
onblock,
nonce>( code, act) ) {
eosio::print("Unexpected action: ", eosio::name(act), "\n");
eosio_assert( false, "received unexpected action");
......
......@@ -458,4 +458,52 @@ bytes pack( const T& value ) {
return result;
}
template<typename Stream>
inline eosio::datastream<Stream>& operator<<(eosio::datastream<Stream>& ds, const public_key pk) {
ds.write((const char*)&pk, sizeof(pk));
return ds;
}
template<typename Stream>
inline eosio::datastream<Stream>& operator>>(eosio::datastream<Stream>& ds, public_key& pk) {
ds.read((char*)&pk, sizeof(pk));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator<<(datastream<Stream>& ds, const checksum160& cs) {
ds.write((const char*)&cs, sizeof(cs));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator>>(datastream<Stream>& ds, checksum160& cs) {
ds.read((char*)&cs, sizeof(cs));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator<<(datastream<Stream>& ds, const checksum256& cs) {
ds.write((const char*)&cs, sizeof(cs));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator>>(datastream<Stream>& ds, checksum256& cs) {
ds.read((char*)&cs, sizeof(cs));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator<<(datastream<Stream>& ds, const checksum512& cs) {
ds.write((const char*)&cs, sizeof(cs));
return ds;
}
template<typename Stream>
inline datastream<Stream>& operator>>(datastream<Stream>& ds, checksum512& cs) {
ds.read((char*)&cs, sizeof(cs));
return ds;
}
}
#pragma once
#include <utility>
namespace eosio {
template<typename T>
class optional {
public:
typedef T value_type;
optional():_valid(false){}
~optional(){ reset(); }
optional( optional& o )
:_valid(false)
{
if( o._valid ) new (ptr()) T( *o );
_valid = o._valid;
}
optional( const optional& o )
:_valid(false)
{
if( o._valid ) new (ptr()) T( *o );
_valid = o._valid;
}
optional( optional&& o )
:_valid(false)
{
if( o._valid ) new (ptr()) T( std::move(*o) );
_valid = o._valid;
o.reset();
}
template<typename U>
optional( const optional<U>& o )
:_valid(false)
{
if( o._valid ) new (ptr()) T( *o );
_valid = o._valid;
}
template<typename U>
optional( optional<U>& o )
:_valid(false)
{
if( o._valid )
{
new (ptr()) T( *o );
}
_valid = o._valid;
}
template<typename U>
optional( optional<U>&& o )
:_valid(false)
{
if( o._valid ) new (ptr()) T( std::move(*o) );
_valid = o._valid;
o.reset();
}
template<typename U>
optional( U&& u )
:_valid(true)
{
new ((char*)ptr()) T( std::forward<U>(u) );
}
template<typename U>
optional& operator=( U&& u )
{
reset();
new (ptr()) T( std::forward<U>(u) );
_valid = true;
return *this;
}
template<typename ...Args>
void emplace(Args&& ... args) {
if (_valid) {
reset();
}
new ((char*)ptr()) T( std::forward<Args>(args)... );
_valid = true;
}
template<typename U>
optional& operator=( optional<U>& o ) {
if (this != &o) {
if( _valid && o._valid ) {
ref() = *o;
} else if( !_valid && o._valid ) {
new (ptr()) T( *o );
_valid = true;
} else if (_valid) {
reset();
}
}
return *this;
}
template<typename U>
optional& operator=( const optional<U>& o ) {
if (this != &o) {
if( _valid && o._valid ) {
ref() = *o;
} else if( !_valid && o._valid ) {
new (ptr()) T( *o );
_valid = true;
} else if (_valid) {
reset();
}
}
return *this;
}
optional& operator=( optional& o ) {
if (this != &o) {
if( _valid && o._valid ) {
ref() = *o;
} else if( !_valid && o._valid ) {
new (ptr()) T( *o );
_valid = true;
} else if (_valid) {
reset();
}
}
return *this;
}
optional& operator=( const optional& o ) {
if (this != &o) {
if( _valid && o._valid ) {
ref() = *o;
} else if( !_valid && o._valid ) {
new (ptr()) T( *o );
_valid = true;
} else if (_valid) {
reset();
}
}
return *this;
}
template<typename U>
optional& operator=( optional<U>&& o )
{
if (this != &o)
{
if( _valid && o._valid )
{
ref() = std::move(*o);
o.reset();
} else if ( !_valid && o._valid ) {
*this = std::move(*o);
} else if (_valid) {
reset();
}
}
return *this;
}
optional& operator=( optional&& o )
{
if (this != &o)
{
if( _valid && o._valid )
{
ref() = std::move(*o);
o.reset();
} else if ( !_valid && o._valid ) {
*this = std::move(*o);
} else if (_valid) {
reset();
}
}
return *this;
}
bool valid()const { return _valid; }
bool operator!()const { return !_valid; }
// this operation is not safe and can result in unintential
// casts and comparisons, use valid() or !!
explicit operator bool()const { return _valid; }
T& operator*() { assert(_valid); return ref(); }
const T& operator*()const { assert(_valid); return ref(); }
T* operator->()
{
assert(_valid);
return ptr();
}
const T* operator->()const
{
assert(_valid);
return ptr();
}
optional& operator=(std::nullptr_t)
{
reset();
return *this;
}
void reset()
{
if( _valid )
{
ref().~T(); // cal destructor
}
_valid = false;
}
friend bool operator < ( const optional a, optional b )
{
if( a.valid() && b.valid() ) return *a < *b;
return a.valid() < b.valid();
}
friend bool operator == ( const optional a, optional b )
{
if( a.valid() && b.valid() ) return *a == *b;
return a.valid() == b.valid();
}
template<typename Stream>
friend inline eosio::datastream<Stream>& operator>> (eosio::datastream<Stream>& ds, optional& op)
{
char valid = 0;
ds >> valid;
if (valid) {
op._valid = true;
ds >> *op;
}
return ds;
}
template<typename Stream>
friend inline eosio::datastream<Stream>& operator<< (eosio::datastream<Stream>& ds, const optional& op)
{
char valid = op._valid;
ds << valid;
if (valid) ds << *op;
return ds;
}
private:
template<typename U> friend class optional;
T& ref() { return *ptr(); }
const T& ref()const { return *ptr(); }
T* ptr() { void* v = &_value[0]; return static_cast<T*>(v); }
const T* ptr()const { const void* v = &_value[0]; return static_cast<const T*>(v); }
// force alignment... to 8 byte boundaries
uint64_t _value[((sizeof(T)+7)/8)];
bool _valid;
};
template<typename T>
bool operator == ( const optional<T>& left, const optional<T>& right ) {
return (!left == !right) || (!!left && *left == *right);
}
template<typename T, typename U>
bool operator == ( const optional<T>& left, const U& u ) {
return !!left && *left == u;
}
template<typename T>
bool operator != ( const optional<T>& left, const optional<T>& right ) {
return (!left != !right) || (!!left && *left != *right);
}
template<typename T, typename U>
bool operator != ( const optional<T>& left, const U& u ) {
return !left || *left != u;
}
} // namespace eosio
......@@ -6,10 +6,6 @@
#include <stdint.h>
#include <wchar.h>
/*
struct checksum_base {
};
*/
#ifdef __cplusplus
extern "C" {
......
......@@ -330,6 +330,17 @@ transaction_trace chain_controller::_push_transaction( transaction_metadata&& da
return result;
}
block_header chain_controller::head_block_header() const
{
auto b = _fork_db.fetch_block(head_block_id());
if( b ) return b->data;
if (auto head_block = fetch_block_by_id(head_block_id()))
return *head_block;
return block_header();
}
void chain_controller::_start_pending_block()
{
FC_ASSERT( !_pending_block );
......@@ -339,6 +350,28 @@ void chain_controller::_start_pending_block()
_pending_block->regions.resize(1);
_pending_block_trace->region_traces.resize(1);
_start_pending_cycle();
_apply_on_block_transaction();
}
transaction chain_controller::_get_on_block_transaction()
{
action on_block_act;
on_block_act.account = config::system_account_name;
on_block_act.name = N(onblock);
on_block_act.authorization = vector<permission_level>{{config::system_account_name, config::active_name}};
on_block_act.data = fc::raw::pack(head_block_header());
transaction trx;
trx.actions.emplace_back(std::move(on_block_act));
trx.set_reference_block(head_block_id());
return trx;
}
void chain_controller::_apply_on_block_transaction()
{
auto trx = _get_on_block_transaction();
transaction_metadata mtrx(packed_transaction(trx), get_chain_id(), head_block_time());
_push_transaction(std::move(mtrx));
}
/**
......@@ -604,7 +637,11 @@ void chain_controller::__apply_block(const signed_block& next_block)
/// cache the input tranasction ids so that they can be looked up when executing the
/// summary
vector<transaction_metadata> input_metas;
input_metas.reserve(next_block.input_transactions.size());
input_metas.reserve(next_block.input_transactions.size() + 1);
{
auto trx = _get_on_block_transaction();
input_metas.emplace_back(packed_transaction(trx), get_chain_id(), head_block_time());
}
map<transaction_id_type,size_t> trx_index;
for( const auto& t : next_block.input_transactions ) {
input_metas.emplace_back(t, chain_id_type(), next_block.timestamp);
......@@ -663,10 +700,16 @@ void chain_controller::__apply_block(const signed_block& next_block)
if( itr != trx_index.end() ) {
return &input_metas.at(itr->second);
} else {
const auto& gtrx = _db.get<generated_transaction_object,by_trx_id>(receipt.id);
auto trx = fc::raw::unpack<deferred_transaction>(gtrx.packed_trx.data(), gtrx.packed_trx.size());
_temp.emplace(trx, gtrx.published, trx.sender, trx.sender_id, gtrx.packed_trx.data(), gtrx.packed_trx.size() );
return &*_temp;
const auto* gtrx = _db.find<generated_transaction_object,by_trx_id>(receipt.id);
if (gtrx != nullptr) {
auto trx = fc::raw::unpack<deferred_transaction>(gtrx->packed_trx.data(), gtrx->packed_trx.size());
_temp.emplace(trx, gtrx->published, trx.sender, trx.sender_id, gtrx->packed_trx.data(), gtrx->packed_trx.size() );
return &*_temp;
} else {
const auto& mtrx = input_metas[0];
FC_ASSERT(mtrx.id == receipt.id, "on-block transaction id mismatch");
return &input_metas[0];
}
}
};
......@@ -950,7 +993,6 @@ void chain_controller::update_global_properties(const signed_block& b) { try {
{
FC_ASSERT( schedule == *b.new_producers, "pending producer set different than expected" );
}
const auto& gpo = get_global_properties();
if( _head_producer_schedule() != schedule ) {
......
......@@ -278,6 +278,7 @@ namespace eosio { namespace chain {
uint32_t head_block_num()const;
block_id_type head_block_id()const;
account_name head_block_producer()const;
block_header head_block_header()const;
uint32_t last_irreversible_block_num() const;
......@@ -418,6 +419,9 @@ namespace eosio { namespace chain {
void _apply_cycle_trace( const cycle_trace& trace );
void _finalize_block( const block_trace& b );
transaction _get_on_block_transaction();
void _apply_on_block_transaction();
// producer_schedule_type calculate_next_round( const signed_block& next_block );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册