提交 3dbcd511 编写于 作者: D Daniel Larimer

broken noon, god help us all

上级 31458635
......@@ -2,6 +2,7 @@ file(GLOB HEADERS "include/eos/chain/*.hpp")
## SORT .cpp by most likely to change / break compile
add_library( eos_chain
name.cpp
wast_to_wasm.cpp
chain_controller.cpp
wasm_interface.cpp
......@@ -24,7 +25,7 @@ add_library( eos_chain
${HEADERS}
)
target_link_libraries( eos_chain fc chainbase eos_types Logging IR WAST WASM Runtime )
target_link_libraries( eos_chain fc chainbase Logging IR WAST WASM Runtime )
target_include_directories( eos_chain
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include"
......
......@@ -13,19 +13,20 @@ namespace eosio { namespace chain {
class account_object : public chainbase::object<account_object_type, account_object> {
OBJECT_CTOR(account_object,(code)(abi))
id_type id;
AccountName name;
uint8_t vm_type = 0;
uint8_t vm_version = 0;
fc::sha256 code_version;
Time creation_date;
shared_vector<char> code;
shared_vector<char> abi;
void set_abi( const eosio::types::Abi& _abi ) {
abi.resize( fc::raw::pack_size( _abi ) );
id_type id;
account_name name;
uint8_t vm_type = 0;
uint8_t vm_version = 0;
digest_type code_version;
block_timestamp_type creation_date;
shared_vector<char> code;
shared_vector<char> abi;
void set_abi( const eosio::types::Abi& a ) {
abi.resize( fc::raw::pack_size( a ) );
fc::datastream<char*> ds( abi.data(), abi.size() );
fc::raw::pack( ds, _abi );
fc::raw::pack( ds, a );
}
};
using account_id_type = account_object::id_type;
......@@ -35,7 +36,7 @@ namespace eosio { namespace chain {
account_object,
indexed_by<
ordered_unique<tag<by_id>, member<account_object, account_object::id_type, &account_object::id>>,
ordered_unique<tag<by_name>, member<account_object, AccountName, &account_object::name>>
ordered_unique<tag<by_name>, member<account_object, account_name, &account_object::name>>
>
>;
......
......@@ -10,15 +10,18 @@ namespace eosio { namespace chain {
struct block_header
{
digest_type digest() const;
uint32_t block_num() const { return num_from_id(previous) + 1; }
digest_type digest() const;
uint32_t block_num() const { return num_from_id(previous) + 1; }
static uint32_t num_from_id(const block_id_type& id);
block_id_type previous;
block_timestamp_type timestamp;
checksum_type transaction_merkle_root;
AccountName producer;
checksum_type transaction_mroot; /// mroot of cycles_summary
checksum_type message_mroot;
checksum_type block_mroot;
account_name producer;
/**
* The changes in the round of producers after this block
*
......@@ -31,7 +34,7 @@ namespace eosio { namespace chain {
* Even though the above examples are semantically equivalent (replace A and B with X and Y), only the first is
* legal.
*/
RoundChanges producer_changes;
optional<producer_schedule_type> new_producers;
};
struct signed_block_header : public block_header
......@@ -44,21 +47,52 @@ namespace eosio { namespace chain {
signature_type producer_signature;
};
struct thread {
vector<ProcessedGeneratedTransaction> generated_input;
vector<ProcessedTransaction> user_input;
digest_type merkle_digest() const;
};
/**
* The block_summary defines the set of transactions that were successfully applied as they
* are organized into cycles and shards. A shard contains the set of transactions IDs which
* are either user generated transactions or code-generated transactions.
*
*
* The primary purpose of a block is to define the order in which messages are processed.
*
* The secodnary purpose of a block is certify that the messages are valid according to
* a group of 3rd party validators (producers).
*
* The next purpose of a block is to enable light-weight proofs that a transaction occured
* and was considered valid.
*
* The next purpose is to enable code to generate messages that are certified by the
* producers to be authorized.
*
* A block is therefore defined by the ordered set of executed and generated transactions,
* and the merkle proof is over set of messages delivered as a result of executing the
* transactions.
*
* A message is defined by { receiver, code, function, permission, data }, the merkle
* tree of a block should be generated over a set of message IDs rather than a set of
* transaction ids.
*/
struct block_summary : public signed_block_header {
typedef vector<transaction_receipt> shard; /// new or generated transactions
typedef vector<shard> cycle;
using cycle = vector<thread>;
vector<cycle> cycles_summary;
};
struct signed_block : public signed_block_header
{
checksum_type calculate_merkle_root() const;
vector<cycle> cycles;
/**
* This structure contains the set of signed transactions referenced by the
* block summary. This inherits from block_summary/signed_block_header and is
* what would be logged to disk to enable the regeneration of blockchain state.
*
* The transactions are grouped to mirror the cycles in block_summary, generated
* transactions are not included.
*/
struct signed_block : public block_summary {
vector<signed_transaction> input_transactions; /// this is loaded and indexed into map<id,trx> that is referenced by summary
};
} } // eosio::chain
FC_REFLECT(eosio::chain::block_header, (previous)(timestamp)(transaction_merkle_root)(producer)(producer_changes))
......
#pragma once
#include <eos/chain/config.hpp>
#include <stdint.h>
#include <fc/time.hpp>
#include <fc/variant.hpp>
......@@ -12,7 +14,7 @@ namespace eosio { namespace chain {
* 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>
template<uint16_t IntervalMs, uint64_t EpochMs>
class block_timestamp {
public:
explicit block_timestamp( uint32_t s=0 ) :slot(s){}
......@@ -29,7 +31,7 @@ namespace eosio { namespace chain {
static block_timestamp min() { return block_timestamp(0); }
operator fc::time_point() const {
int64_t msec = slot * (int64_t)Interval;
int64_t msec = slot * (int64_t)IntervalMs;
msec += EpochMs;
return fc::time_point(fc::microseconds(msec * 1000));
}
......@@ -54,16 +56,16 @@ namespace eosio { namespace chain {
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;
slot = ( msec_since_epoch - EpochMs ) / IntervalMs;
}
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;
slot = (sec_since_epoch * 1000 - EpochMs) / IntervalMs;
}
}; // block_timestamp
typedef block_timestamp<3000,946684800000ll> block_timestamp_type; // epoch is year 2000.
typedef block_timestamp<config::block_interval_ms,config::block_timestamp_epoch> block_timestamp_type;
} } /// eosio::chain
......@@ -72,14 +74,14 @@ namespace eosio { namespace chain {
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) {
template<uint16_t IntervalMs, uint64_t EpochMs>
void to_variant(const eosio::chain::block_timestamp<IntervalMs,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) {
template<uint16_t IntervalMs, uint64_t EpochMs>
void from_variant(const fc::variant& v, eosio::chain::block_timestamp<IntervalMs,EpochMs>& t) {
fc::microseconds mc;
from_variant(v, mc);
t = fc::time_point(mc);
......
......@@ -6,13 +6,7 @@
#include <eos/chain/types.hpp>
#include <eos/types/generated.hpp>
namespace eosio {
namespace chain {
namespace eosio { namespace chain {
/**
* @brief Producer-voted blockchain configuration parameters
......@@ -21,22 +15,29 @@ namespace chain {
* their preference for each of the parameters in this object, and the blockchain runs according to the median of the
* values specified by the producers.
*/
struct BlockchainConfiguration : public types::BlockchainConfiguration {
using types::BlockchainConfiguration::BlockchainConfiguration;
BlockchainConfiguration& operator= (const types::BlockchainConfiguration& other);
static BlockchainConfiguration get_median_values(std::vector<BlockchainConfiguration> votes);
friend std::ostream& operator<< (std::ostream& s, const BlockchainConfiguration& p);
struct chain_config {
uint32_t target_block_size;
share_type producer_pay;
uint32_t max_block_size;
uint64_t max_storage_size;
uint32_t max_transaction_lifetime;
uint16_t max_authority_depth;
uint32_t max_transaction_exec_time;
uint16_t max_inline_depth;
uint32_t max_inline_message_size;
uint32_t max_generated_transaction_size;
static chain_config get_median_values( const vector<chain_config>& votes );
};
bool operator==(const types::BlockchainConfiguration& a, const types::BlockchainConfiguration& b);
inline bool operator!=(const types::BlockchainConfiguration& a, const types::BlockchainConfiguration& b) {
return !(a == b);
}
bool operator==(const chain_config& a, const chain_config& b);
inline bool operator!=(const chain_config& a, const chain_config& b) { return !(a == b); }
}
} // namespace eosio::chain
} } // namespace eosio::chain
FC_REFLECT_DERIVED(eosio::chain::BlockchainConfiguration, (eosio::types::BlockchainConfiguration), )
FC_REFLECT(eosio::chain::chain_config,
(target_block_size)(producer_pay)
(max_block_size)(max_storage_size)
(max_transaction_lifetime)(max_authority_depth)(max_transaction_exec_time)
(max_inline_depth)(max_inline_message_size)(max_generated_transaction_size) )
......@@ -71,7 +71,7 @@ namespace eosio { namespace chain {
* This signal is emitted any time a new transaction is added to the pending
* block state.
*/
signal<void(const SignedTransaction&)> on_pending_transaction;
signal<void(const signed_transaction&)> on_pending_transaction;
/**
* @brief Check whether the controller is currently applying a block or not
......@@ -83,7 +83,7 @@ namespace eosio { namespace chain {
* The controller can override any script endpoint with native code.
*/
///@{
void set_apply_handler( const AccountName& contract, const AccountName& scope, const ActionName& action, apply_handler v );
void set_apply_handler( const account_name& contract, const account_name& scope, const ActionName& action, apply_handler v );
//@}
enum validation_steps
......@@ -117,22 +117,22 @@ namespace eosio { namespace chain {
block_id_type get_block_id_for_num( uint32_t block_num )const;
optional<signed_block> fetch_block_by_id( const block_id_type& id )const;
optional<signed_block> fetch_block_by_number( uint32_t num )const;
const SignedTransaction& get_recent_transaction( const transaction_id_type& trx_id )const;
const signed_transaction& get_recent_transaction( const transaction_id_type& trx_id )const;
std::vector<block_id_type> get_block_ids_on_fork(block_id_type head_of_fork)const;
const GeneratedTransaction& get_generated_transaction( const generated_transaction_id_type& id ) const;
const Generatedtransaction& get_generated_transaction( const generated_transaction_id_type& id ) const;
/**
* This method will convert a variant to a SignedTransaction using a contract's ABI to
* This method will convert a variant to a signed_transaction using a contract's ABI to
* interpret the message types.
*/
ProcessedTransaction transaction_from_variant( const fc::variant& v )const;
signed_transaction transaction_from_variant( const fc::variant& v )const;
/**
* This method will convert a signed transaction into a human-friendly variant that can be
* converted to JSON.
*/
fc::variant transaction_to_variant( const ProcessedTransaction& trx )const;
fc::variant transaction_to_variant( const signed_transaction& trx )const;
/**
* Usees the ABI for code::type to convert a JSON object (variant) into hex
......@@ -154,31 +154,31 @@ namespace eosio { namespace chain {
bool push_block( const signed_block& b, uint32_t skip = skip_nothing );
ProcessedTransaction push_transaction( const SignedTransaction& trx, uint32_t skip = skip_nothing );
ProcessedTransaction _push_transaction( const SignedTransaction& trx );
Processedtransaction push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
/**
* Determine which public keys are needed to sign the given transaction.
* @param trx Transaction that requires signature
* @param trx transaction that requires signature
* @param candidateKeys Set of public keys to examine for applicability
* @return Subset of candidateKeys whose private keys should be used to sign transaction
* @throws fc::exception if candidateKeys does not contain all required keys
*/
flat_set<public_key_type> get_required_keys(const SignedTransaction& trx, const flat_set<public_key_type>& candidateKeys)const;
flat_set<public_key_type> get_required_keys(const signed_transaction& trx, const flat_set<public_key_type>& candidateKeys)const;
bool _push_block( const signed_block& b );
signed_block generate_block(
fc::time_point_sec when,
const AccountName& producer,
const fc::ecc::private_key& block_signing_private_key,
block_schedule::factory scheduler = block_schedule::in_single_thread,
const & producer,
const private_key_type& block_signing_private_key,
uint32_t skip = skip_nothing
);
signed_block _generate_block(
fc::time_point_sec when,
const AccountName& producer,
const account_name& producer,
const fc::ecc::private_key& block_signing_private_key,
block_schedule::factory scheduler
);
......@@ -226,7 +226,7 @@ namespace eosio { namespace chain {
*
* Passing slot_num == 0 returns EOS_NULL_PRODUCER
*/
AccountName get_scheduled_producer(uint32_t slot_num)const;
account_name get_scheduled_producer(uint32_t slot_num)const;
/**
* Get the time at which the given slot occurs.
......@@ -250,13 +250,12 @@ namespace eosio { namespace chain {
const global_property_object& get_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 account_name& ownerName)const;
time_point_sec head_block_time()const;
block_timestamp_type head_block_timestamp() const;
time_point head_block_timestamp() const;
uint32_t head_block_num()const;
block_id_type head_block_id()const;
AccountName head_block_producer()const;
account_name head_block_producer()const;
uint32_t block_interval()const { return config::BlockIntervalSeconds; }
......@@ -269,7 +268,7 @@ namespace eosio { namespace chain {
bool should_check_scope()const { return !(_skip_flags&skip_scope_check); }
const deque<SignedTransaction>& pending()const { return _pending_transactions; }
const deque<signed_transaction>& pending()const { return _pending_transactions; }
/**
* Enum to indicate what type of rate limiting is being performed.
......@@ -294,7 +293,7 @@ namespace eosio { namespace chain {
* @throws tx_msgs_code_exceeded if current message rate exceeds the passed in rate_limit, and type is code_account
*/
static uint32_t _transaction_message_rate(const fc::time_point_sec& now, const fc::time_point_sec& last_update_sec, const fc::time_point_sec& rate_limit_time_frame_sec,
uint32_t rate_limit, uint32_t previous_rate, rate_limit_type type, const AccountName& name);
uint32_t rate_limit, uint32_t previous_rate, rate_limit_type type, const account_name& name);
struct txn_msg_rate_limits {
fc::time_point_sec per_auth_account_time_frame_sec = fc::time_point_sec(config::DefaultPerAuthAccountTimeFrameSeconds);
......@@ -304,6 +303,7 @@ namespace eosio { namespace chain {
};
private:
void _push_transaction( const signed_transaction& trx );
/// Reset the object graph in-memory
void initialize_indexes();
......@@ -323,18 +323,11 @@ namespace eosio { namespace chain {
return f();
}
void check_transaction_authorization(const SignedTransaction& trx, bool allow_unused_signatures = false)const;
void check_transaction_authorization(const signed_transaction& trx,
bool allow_unused_signatures = false)const;
template<typename T>
void check_transaction_output(const T& expected, const T& actual, const path_cons_list& path)const;
template<typename T>
typename T::Processed apply_transaction(const T& trx);
template<typename T>
typename T::Processed process_transaction(const T& trx, int depth, const fc::time_point& start_time);
void require_account(const AccountName& name) const;
void require_account(const account_name& name) const;
/**
* This method performs some consistency checks on a transaction.
......@@ -353,15 +346,12 @@ namespace eosio { namespace chain {
} FC_CAPTURE_AND_RETHROW( (trx) ) }
/// Validate transaction helpers @{
void validate_uniqueness(const SignedTransaction& trx)const;
void validate_uniqueness(const GeneratedTransaction& trx)const;
void validate_tapos(const Transaction& trx)const;
void validate_referenced_accounts(const Transaction& trx)const;
void validate_expiration(const Transaction& trx) const;
void validate_scope(const Transaction& trx) const;
void record_transaction(const SignedTransaction& trx);
void record_transaction(const GeneratedTransaction& trx);
void validate_uniqueness(const signed_transaction& trx)const;
void validate_tapos(const transaction& trx)const;
void validate_referenced_accounts(const transaction& trx)const;
void validate_expiration(const transaction& trx) const;
void validate_scope(const transaction& trx) const;
void record_transaction(const signed_transaction& trx);
/// @}
/**
......@@ -372,20 +362,14 @@ namespace eosio { namespace chain {
* @param type The type of message
* @return
*/
const permission_object& lookup_minimum_permission(types::AccountName authorizer_account,
types::AccountName code_account,
types::FuncName type) const;
const permission_object& lookup_minimum_permission( account_name authorizer_account,
scope_name code_account,
action_name type) const;
/**
* Calculate all rates associated with the given message and enforce rate limiting.
* @param message The message to calculate
* @throws tx_msgs_auth_exceeded if any of the calculated message rates exceed the configured authorization account rate limit
* @throws tx_msgs_code_exceeded if the calculated message rate exceed the configured code account rate limit
*/
void rate_limit_message(const Message& message);
void process_message(const Transaction& trx, AccountName code, const Message& message,
MessageOutput& output, apply_context* parent_context = nullptr);
void deliver_message( const transaction& trx, account_name receiving_code,
const action& act, actionOutput& output, apply_context* parent_context = nullptr);
void apply_message(apply_context& c);
bool should_check_for_duplicate_transactions()const { return !(_skip_flags&skip_transaction_dupe_check); }
......@@ -407,7 +391,7 @@ namespace eosio { namespace chain {
void spinup_db();
void spinup_fork_db();
ProducerRound calculate_next_round(const signed_block& next_block);
// producer_schedule_type calculate_next_round( const signed_block& next_block );
database& _db;
fork_database& _fork_db;
......@@ -416,7 +400,8 @@ namespace eosio { namespace chain {
unique_ptr<chain_administration_interface> _admin;
optional<database::session> _pending_tx_session;
deque<SignedTransaction> _pending_transactions;
optional<signed_block> _pending_block;
uint32_t _pending_transaction_count = 0;
bool _currently_applying_block = false;
bool _currently_replaying_blocks = false;
......@@ -432,9 +417,8 @@ namespace eosio { namespace chain {
flat_map<uint32_t,block_id_type> _checkpoints;
typedef pair<AccountName,types::Name> handler_key;
map< AccountName, map<handler_key, apply_handler> > apply_handlers;
typedef pair<scope_name,action_name> handler_key;
map< account_name, map<handler_key, apply_handler> > _apply_handlers;
};
} }
......@@ -3,32 +3,26 @@
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eos/types/types.hpp>
#include <eos/chain/name.hpp>
namespace eosio { namespace config {
using types::UInt16;
using types::UInt32;
using types::UInt64;
using types::UInt128;
using types::ShareType;
using types::Asset;
using types::AccountName;
using types::PermissionName;
const static char KeyPrefix[] = "EOS";
typedef __uint128_t uint128_t;
const static AccountName EosContractName = N(eos);
const static int producer_count = 21;
const static AccountName NobodyAccountName = N(nobody);
const static AccountName AnybodyAccountName = N(anybody);
const static AccountName ProducersAccountName = N(producers);
const static uint64_t system_account_name = N(eosio);
const static uint64_t nobody_account_name = N(nobody);
const static uint64_t anybody_account_name = N(anybody);
const static uint64_t producers_account_name = N(producers);
const static PermissionName ActiveName = N(active);
const static PermissionName OwnerName = N(owner);
const static uint64_t active_name = N(active);
const static uint64_t owner_name = N(owner);
const static ShareType InitialTokenSupply = Asset::fromString("90000000.0000 EOS").amount;
const static uint64_t initial_token_supply = 900*1000*1000*10000ll; /// 900,000,000.0000
const static int BlockIntervalSeconds = 3;
const static int block_interval_ms = 500;
const static uint64_t block_timestamp_epoch = 946684800000ll; // epoch is year 2000.
/** Percentages are fixed point with a denominator of 10,000 */
const static int Percent100 = 10000;
......@@ -39,19 +33,16 @@ const static int DefaultPerAuthAccount = 1800;
const static int DefaultPerCodeAccountTimeFrameSeconds = 18;
const static int DefaultPerCodeAccount = 18000;
const static UInt32 DefaultMaxBlockSize = 5 * 1024 * 1024;
const static UInt32 DefaultTargetBlockSize = 128 * 1024;
const static UInt64 DefaultMaxStorageSize = 10 * 1024;
const static ShareType DefaultElectedPay = Asset(100).amount;
const static ShareType DefaultRunnerUpPay = Asset(75).amount;
const static ShareType DefaultMinEosBalance = Asset(100).amount;
const static UInt32 DefaultMaxTrxLifetime = 60*60;
const static UInt16 DefaultAuthDepthLimit = 6;
const static UInt32 DefaultMaxTrxRuntime = 10*1000;
const static UInt16 DefaultInlineDepthLimit = 4;
const static UInt32 DefaultMaxInlineMsgSize = 4 * 1024;
const static UInt32 DefaultMaxGenTrxSize = 64 * 1024;
const static UInt32 ProducersAuthorityThreshold = 14;
const static uint32_t DefaultMaxBlockSize = 5 * 1024 * 1024;
const static uint32_t DefaultTargetBlockSize = 128 * 1024;
const static uint64_t DefaultMaxStorageSize = 10 * 1024;
const static uint32_t DefaultMaxTrxLifetime = 60*60;
const static uint16_t DefaultAuthDepthLimit = 6;
const static uint32_t DefaultMaxTrxRuntime = 10*1000;
const static uint16_t DefaultInlineDepthLimit = 4;
const static uint32_t DefaultMaxInlineMsgSize = 4 * 1024;
const static uint32_t DefaultMaxGenTrxSize = 64 * 1024;
const static uint32_t ProducersAuthorityThreshold = 14;
const static int ProducerRepetitions = 4;
const static int BlocksPerRound = 21 * ProducerRepetitions;
......@@ -59,7 +50,7 @@ const static int VotedProducersPerRound = 20;
const static int IrreversibleThresholdPercent = 70 * Percent1;
const static int MaxProducerVotes = 30;
const static UInt128 ProducerRaceLapLength = std::numeric_limits<UInt128>::max();
const static uint128_t ProducerRaceLapLength = std::numeric_limits<uint128_t>::max();
const static auto StakedBalanceCooldownSeconds = fc::days(3).to_seconds();
} } // namespace eosio::config
......
......@@ -8,7 +8,7 @@
#include <eos/chain/types.hpp>
#include <eos/chain/block_timestamp.hpp>
#include <eos/chain/BlockchainConfiguration.hpp>
#include <eos/chain/chain_config.hpp>
#include <chainbase/chainbase.hpp>
#include "multi_index_includes.hpp"
......@@ -26,9 +26,9 @@ namespace eosio { namespace chain {
{
OBJECT_CTOR(global_property_object)
id_type id;
BlockchainConfiguration configuration;
std::array<AccountName, config::BlocksPerRound> active_producers;
id_type id;
chain_config configuration;
std::array<account_name, config::BlocksPerRound> active_producers;
};
......@@ -49,8 +49,8 @@ namespace eosio { namespace chain {
id_type id;
uint32_t head_block_number = 0;
block_id_type head_block_id;
fc::time_point time;
AccountName current_producer;
fc::time_point time;
account_name current_producer;
uint32_t accounts_registered_this_interval = 0;
/**
......
#pragma once
#include <string>
#include <fc/reflect/reflect.hpp>
namespace eosio { namespace chain {
using std::string;
static constexpr char char_to_symbol( char c ) {
if( c >= 'a' && c <= 'z' )
return (c - 'a') + 6;
if( c >= '1' && c <= '5' )
return (c - '1') + 1;
return 0;
}
static constexpr uint64_t string_to_name( const char* str ) {
uint32_t len = 0;
while( str[len] ) ++len;
uint64_t value = 0;
for( uint32_t i = 0; i <= 12; ++i ) {
uint64_t c = 0;
if( i < len && i <= 12 ) c = char_to_symbol( str[i] );
if( i < 12 ) {
c &= 0x1f;
c <<= 64-5*(i+1);
}
else {
c &= 0x0f;
}
value |= c;
}
return value;
}
#define N(X) eosio::chain::string_to_name(#X)
struct name {
uint64_t value = 0;
bool empty()const { return 0 == value; }
bool good()const { return !empty(); }
name( const char* str ) { set(str); }
name( const string& str ) { set( str.c_str() ); }
void set( const char* str );
name( uint64_t v = 0 ):value(v){}
explicit operator string()const;
string to_string() const { return string(*this); }
name& operator=( uint64_t v ) {
value = v;
return *this;
}
name& operator=( const string& n ) {
value = name(n).value;
return *this;
}
name& operator=( const char* n ) {
value = name(n).value;
return *this;
}
template<typename Stream>
friend Stream& operator << ( Stream& out, const name& n ) {
return out << string(n);
}
friend bool operator < ( const name& a, const name& b ) { return a.value < b.value; }
friend bool operator <= ( const name& a, const name& b ) { return a.value <= b.value; }
friend bool operator > ( const name& a, const name& b ) { return a.value > b.value; }
friend bool operator >=( const name& a, const name& b ) { return a.value >= b.value; }
friend bool operator == ( const name& a, const name& b ) { return a.value == b.value; }
friend bool operator != ( const name& a, const name& b ) { return a.value != b.value; }
operator bool()const { return value; }
operator uint64_t()const { return value; }
};
} } // eosio::chain
namespace fc {
class variant;
void to_variant(const eosio::chain::name& c, fc::variant& v);
void from_variant(const fc::variant& v, eosio::chain::name& check);
} // fc
FC_REFLECT( eosio::chain::name, (value) )
#include <eosio/chain/config.hpp>
#include <eosio/chain/types.hpp>
namespace eosio { namespace chain {
/**
* Used as part of the producer_schedule_type, mapps the producer name to their key.
*/
struct producer_key {
account_name producer_name;
public_key_type block_signing_key;
};
/**
* Defines both the order, account name, and signing keys of the active set of producers.
*/
using producer_schedule_type = fc::array<producer_key,eosio::config::producer_count>;
} } /// eosio::chain
FC_REFLECT( eosio::chain::producer_key, (producer_name)(block_signing_key) )
......@@ -10,200 +10,123 @@
namespace eosio { namespace chain {
/**
* @defgroup transactions Transactions
*
* All transactions are sets of messages that must be applied atomically (all succeed or all fail). Transactions
* must refer to a recent block that defines the context of the operation so that they assert a known
* state-precondition assumed by the transaction signers.
*
* Rather than specify a full block number, we only specify the lower 16 bits of the block number which means you
* can reference any block within the last 65,536 blocks which is 2.2 days with a 3 second block interval.
*
* All transactions must expire so that the network does not have to maintain a permanent record of all transactions
* ever published. A transaction may not have an expiration date too far in the future because this would require
* keeping too much transaction history in memory.
*
* The block prefix is the first 4 bytes of the block hash of the reference block number, which is the second 4
* bytes of the @ref block_id_type (the first 4 bytes of the block ID are the block number)
*
* @note It is not recommended to set the @ref ref_block_num, @ref ref_block_prefix, and @ref expiration
* fields manually. Call @ref set_expiration instead.
*
* @{
*/
struct ProcessedTransaction;
struct InlineTransaction;
struct ProcessedGeneratedTransaction;
struct permission_level {
account_name actor;
permission_name level;
};
/**
* @brief methods that operate on @ref eosio::types::Transaction.
* An action is performed by an actor, aka an account. It may
* be created explicitly and authorized by signatures or might be
* generated implicitly by executing application code.
*
* These are utility methods for sharing common operations between inheriting types which define
* additional features and requirements based off of @ref eosio::types::Transaction.
* This follows the design pattern of React Flux where actions are
* named and then dispatched to one or more action handlers (aka stores).
* In the context of eosio, every action is dispatched to the handler defined
* by account 'scope' and function 'name', but the default handler may also
* forward the action to any number of additional handlers. Any application
* can write a handler for "scope::name" that will get executed if and only if
* this action is forwarded to that application.
*
* Each action may require the permission of specific actors. Actors can define
* any number of permission levels. The actors and their respective permission
* levels are declared on the action and validated independently of the executing
* application code. An application code will check to see if the required permissions
* were properly declared when it executes.
*/
/// Calculate the digest for a transaction
digest_type transaction_digest(const Transaction& t);
void transaction_set_reference_block(Transaction& t, const block_id_type& reference_block);
bool transaction_verify_reference_block(const Transaction& t, const block_id_type& reference_block);
template <typename T>
void transaction_set_message(Transaction& t, int index, const types::FuncName& type, T&& value) {
Message m(t.messages[index]);
m.set(type, std::forward<T>(value));
t.messages[index] = m;
}
template <typename T>
T transaction_message_as(Transaction& t, int index) {
Message m(t.messages[index]);
return m.as<T>();
}
template <typename... Args>
void transaction_emplace_message(Transaction& t, Args&&... a) {
t.messages.emplace_back(Message(std::forward<Args>(a)...));
}
struct action {
account_name scope;
function_name name;
vector<permission_level> permissions;
bytes data;
};
template <typename... Args>
void transaction_emplace_serialized_message(Transaction& t, Args&&... a) {
t.messages.emplace_back(types::Message(std::forward<Args>(a)...));
}
struct action_notice : public action {
account_name receiver;
};
/**
* clear all common data
*/
inline void transaction_clear(Transaction& t) {
t.messages.clear();
}
/**
* @brief A generated_transaction is a transaction which was internally generated by the blockchain, typically as a
* result of running a contract.
*
* When contracts run and seek to interact with other contracts, or mutate chain state, they generate transactions
* containing messages which effect these interactions and mutations. These generated transactions are automatically
* generated by contracts, and thus are authorized by the script that generated them rather than by signatures. The
* generated_transaction struct records such a transaction.
*
* These transactions are generated while processing other transactions. The generated transactions are assigned a
* sequential ID, then stored in the block that generated them. These generated transactions can then be included in
* subsequent blocks by referencing this ID.
* When a transaction is referenced by a block it could imply one of several outcomes which
* describe the state-transition undertaken by the block producer.
*/
struct GeneratedTransaction : public types::Transaction {
GeneratedTransaction() = default;
GeneratedTransaction(generated_transaction_id_type _id, const Transaction& trx)
: types::Transaction(trx)
, id(_id) {}
GeneratedTransaction(generated_transaction_id_type _id, const Transaction&& trx)
: types::Transaction(trx)
, id(_id) {}
generated_transaction_id_type id;
digest_type merkle_digest() const;
typedef ProcessedGeneratedTransaction Processed;
struct transaction_receipt {
enum status_enum {
generated = 0, ///< created, not yet known to be valid or invalid (no state transition)
executed = 1, ///< succeed, no error handler executed
soft_fail = 2, ///< objectively failed (not executed), error handler executed
hard_fail = 3 ///< objectively failed and error handler objectively failed thus no state change
};
fc::enum_type<uint8_t,status_enum> status;
transaction_id_type id;
};
/**
* @brief A transaction with signatures
* The transaction header contains the fixed-sized data
* associated with each transaction. It is separated from
* the transaction body to facilitate partial parsing of
* transactions without requiring dynamic memory allocation.
*
* signed_transaction is a transaction with an additional manifest of authorizations included with the transaction,
* and the signatures backing those authorizations.
* All transactions have an expiration time after which they
* may no longer be included in the blockchain. Once a block
* with a block_header::timestamp greater than expiration is
* deemed irreversible, then a user can safely trust the transaction
* will never be included.
*
* Transactions are divided into memory regions, the default region is 0.
* Each region is an independent blockchain, it is included as routing
* information for inter-blockchain communication. A contract in this
* region might generate or authorize a transaction intended for a foreign
* region.
*/
struct SignedTransaction : public types::SignedTransaction {
typedef types::SignedTransaction super;
using super::super;
/// Calculate the id of the transaction
transaction_id_type id()const;
/// Calculate the digest used for signature validation
digest_type sig_digest(const chain_id_type& chain_id)const;
/** signs and appends to signatures */
const signature_type& sign(const private_key_type& key, const chain_id_type& chain_id);
/** returns signature but does not append */
signature_type sign(const private_key_type& key, const chain_id_type& chain_id)const;
flat_set<public_key_type> get_signature_keys(const chain_id_type& chain_id)const;
struct transaction_header {
time_point_sec expiration; ///< the time at which a transaction expires
uint16_t region = 0; ///< the computational memory region this transaction applies to.
uint16_t ref_block_num = 0; ///< specifies a block num in the last 2^16 blocks.
uint32_t ref_block_prefix = 0; ///< specifies the lower 32 bits of the blockid at get_ref_blocknum
/**
* Removes all messages, signatures, and authorizations
* @return the absolute block number given the relative ref_block_num
*/
void clear() { transaction_clear(*this); signatures.clear(); }
digest_type merkle_digest() const;
typedef ProcessedTransaction Processed;
block_num_type get_ref_blocknum( block_num_type head_blocknum )const {
return ((head_blocknum/0xffff)*0xffff) + head_blocknum%0xffff;
}
};
struct PendingInlineTransaction : public types::Transaction {
typedef types::Transaction super;
using super::super;
explicit PendingInlineTransaction( const types::Transaction& t ):types::Transaction((const types::Transaction& )t){}
typedef InlineTransaction Processed;
};
struct MessageOutput;
struct InlineTransaction : public types::Transaction {
explicit InlineTransaction( const types::Transaction& t ):types::Transaction((const types::Transaction& )t){}
explicit InlineTransaction( const PendingInlineTransaction& t ):types::Transaction((const types::Transaction& )t){}
InlineTransaction(){}
vector<MessageOutput> output;
};
struct NotifyOutput;
/**
* Output generated by applying a particular message.
* A transaction consits of a set of messages which must all be applied or
* all are rejected. These messages have access to data within the given
* read and write scopes.
*/
struct MessageOutput {
vector<NotifyOutput> notify; ///< accounts to notify, may only be notified once
fc::optional<InlineTransaction> inline_transaction; ///< transactions generated and applied after notify
vector<GeneratedTransaction> deferred_transactions; ///< transactions generated but not applied
};
struct transaction : public transaction_header {
vector<account_name> read_scope;
vector<account_name> write_scope;
vector<action> actions;
struct NotifyOutput {
AccountName name;
MessageOutput output;
digest_type digest()const;
};
struct ProcessedTransaction : public SignedTransaction {
explicit ProcessedTransaction( const SignedTransaction& t ):SignedTransaction(t){}
ProcessedTransaction(){}
struct signed_transaction : public transaction {
vector<signature_type> signatures;
vector<MessageOutput> output;
transaction_id_type id()const;
};
struct ProcessedGeneratedTransaction {
explicit ProcessedGeneratedTransaction( const generated_transaction_id_type& _id ):id(_id){}
explicit ProcessedGeneratedTransaction( const GeneratedTransaction& t ):id(t.id){}
ProcessedGeneratedTransaction(){}
generated_transaction_id_type id;
vector<MessageOutput> output;
/**
* When a transaction is generated it can be scheduled to occur
* in the future. It may also fail to execute for some reason in
* which case the sender needs to be notified. When the sender
* sends a transaction they will assign it an ID which will be
* passed back to the sender if the transaction fails for some
* reason.
*/
struct deferred_transaction : public transaction
{
uint64_t id; /// ID assigned by sender of generated, accessible via WASM api when executing normal or error
account_name sender; /// receives error handler callback
time_point_sec execute_after; /// delayed exeuction
};
/// @} transactions group
} } // eosio::chain
FC_REFLECT(eosio::chain::GeneratedTransaction, (id))
FC_REFLECT_DERIVED(eosio::chain::SignedTransaction, (eosio::types::SignedTransaction), )
FC_REFLECT(eosio::chain::MessageOutput, (notify)(inline_transaction)(deferred_transactions) )
FC_REFLECT_DERIVED(eosio::chain::ProcessedTransaction, (eosio::types::SignedTransaction), (output) )
FC_REFLECT_DERIVED(eosio::chain::PendingInlineTransaction, (eosio::types::Transaction), )
FC_REFLECT_DERIVED(eosio::chain::InlineTransaction, (eosio::types::Transaction), (output) )
FC_REFLECT(eosio::chain::ProcessedGeneratedTransaction, (id)(output) )
FC_REFLECT(eosio::chain::NotifyOutput, (name)(output) )
......@@ -3,9 +3,7 @@
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eos/chain/config.hpp>
#include <eos/types/types.hpp>
#include <eos/chain/name.hpp>
#include <chainbase/chainbase.hpp>
......@@ -23,6 +21,7 @@
#include <fc/smart_ref_fwd.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/fixed_string.hpp>
#include <fc/crypto/private_key.hpp>
#include <memory>
#include <vector>
......@@ -76,6 +75,11 @@ namespace eosio { namespace chain {
using fc::ecc::range_proof_type;
using fc::ecc::range_proof_info;
using fc::ecc::commitment_type;
using public_key_type = fc::crypto::public_key;
using private_key_type = fc::crypto::private_key;
using signature_type = fc::crypto::signature;
struct void_t{};
using chainbase::allocator;
......@@ -85,51 +89,12 @@ namespace eosio { namespace chain {
template<typename T>
using shared_set = boost::interprocess::set<T, std::less<T>, allocator<T>>;
using private_key_type = fc::ecc::private_key;
using chain_id_type = fc::sha256;
using eosio::types::Name;
using ActionName = Name;
using eosio::types::AccountName;
using eosio::types::PermissionName;
using eosio::types::Asset;
using eosio::types::ShareType;
using eosio::types::Authority;
using eosio::types::PublicKey;
using eosio::types::Transaction;
using eosio::types::PermissionName;
using eosio::types::TypeName;
using eosio::types::FuncName;
using eosio::types::Time;
using eosio::types::Field;
using eosio::types::String;
using eosio::types::UInt8;
using eosio::types::UInt16;
using eosio::types::UInt32;
using eosio::types::UInt64;
using eosio::types::UInt128;
using eosio::types::UInt256;
using eosio::types::Int8;
using eosio::types::Int16;
using eosio::types::Int32;
using eosio::types::Int64;
using eosio::types::Int128;
using eosio::types::Int256;
using eosio::types::uint128_t;
using ProducerRound = std::array<AccountName, config::BlocksPerRound>;
using RoundChanges = std::map<AccountName, AccountName>;
using action_name = name;
using scope_name = name;
using account_name = name;
/**
* @brief Calculates the difference between two @ref ProducerRound objects
* @param a The first round of producers
* @param b The second round of producers
* @return The properly sorted RoundChanges expressing the difference between a and b
*
* Calculates the difference between two rounds of producers, returning a @ref RoundChanges object. The returned
* changes are sorted in the order defined by @ref block_header
*/
RoundChanges operator-(ProducerRound a, ProducerRound b);
/**
* List all object types from all namespaces here so they can
......@@ -173,25 +138,17 @@ namespace eosio { namespace chain {
class account_object;
class producer_object;
using block_id_type = fc::sha256;
using checksum_type = fc::sha256;
using transaction_id_type = fc::sha256;
using digest_type = fc::sha256;
using generated_transaction_id_type = fc::sha256;
using signature_type = fc::ecc::compact_signature;
using weight_type = uint16_t;
using Bytes = types::Bytes;
using block_id_type = fc::sha256;
using checksum_type = fc::sha256;
using transaction_id_type = checksum_type;
using digest_type = checksum_type;
using weight_type = uint16_t;
using share_type = uint64_t;
using public_key_type = eosio::types::PublicKey;
} } // eosio::chain
namespace fc {
void to_variant(const eosio::chain::shared_vector<eosio::types::Field>& c, fc::variant& v);
void from_variant(const fc::variant& v, eosio::chain::shared_vector<eosio::types::Field>& fields);
void to_variant(const eosio::chain::ProducerRound& r, fc::variant& v);
void from_variant(const fc::variant& v, eosio::chain::ProducerRound& r);
}
FC_REFLECT_ENUM(eosio::chain::object_type,
(null_object_type)
......
#include <eos/chain/name.hpp>
#include <fc/variant.hpp>
#include <boost/algorithm/string.hpp>
#include <fc/exception/exception.hpp>
namespace eosio { namespace chain {
void name::set( const char* str ) {
try {
const auto len = strnlen(str,14);
FC_ASSERT( len <= 13 );
value = string_to_name(str);
FC_ASSERT( to_string() == string(str), "name not properly normalized", ("name",string(str))("normalized",to_string()) );
}FC_CAPTURE_AND_RETHROW( (str) ) }
name::operator string()const {
static const char* charmap = ".12345abcdefghijklmnopqrstuvwxyz";
string str(13,'.');
uint64_t tmp = value;
for( uint32_t i = 0; i <= 12; ++i ) {
char c = charmap[tmp & (i == 0 ? 0x0f : 0x1f)];
str[12-i] = c;
tmp >>= (i == 0 ? 4 : 5);
}
boost::algorithm::trim_right_if( str, []( char c ){ return c == '.'; } );
return str;
}
} } /// eosio::chain
namespace fc {
void to_variant(const eosio::chain::name& c, fc::variant& v) { v = std::string(c); }
void from_variant(const fc::variant& v, eosio::chain::name& check) { check = v.get_string(); }
} // fc
......@@ -149,73 +149,7 @@ namespace fc {
static fc::sha256 get_secret( const EC_KEY * const k );
fc::fwd<detail::private_key_impl,32> my;
};
class extended_public_key : public public_key
{
public:
extended_public_key( const public_key& k, const sha256& c,
int child = 0, int parent_fp = 0, uint8_t depth = 0 );
extended_public_key derive_child( int i ) const;
extended_public_key derive_normal_child( int i ) const;
extended_key_data serialize_extended() const;
static extended_public_key deserialize( const extended_key_data& data );
fc::string str() const;
fc::string to_base58() const { return str(); }
static extended_public_key from_base58( const fc::string& base58 );
public_key generate_p( int i ) const;
public_key generate_q( int i ) const;
private:
sha256 c;
int child_num, parent_fp;
uint8_t depth;
};
class extended_private_key : public private_key
{
public:
extended_private_key( const private_key& k, const sha256& c,
int child = 0, int parent_fp = 0, uint8_t depth = 0 );
extended_public_key get_extended_public_key()const;
extended_private_key derive_child( int i ) const;
extended_private_key derive_normal_child( int i ) const;
extended_private_key derive_hardened_child( int i ) const;
extended_key_data serialize_extended() const;
static extended_private_key deserialize( const extended_key_data& data );
fc::string str() const;
fc::string to_base58() const { return str(); }
static extended_private_key from_base58( const fc::string& base58 );
static extended_private_key generate_master( const fc::string& seed );
static extended_private_key generate_master( const char* seed, uint32_t seed_len );
// Oleg Andreev's blind signature scheme,
// see http://blog.oleganza.com/post/77474860538/blind-signatures
public_key blind_public_key( const extended_public_key& bob, int i ) const;
blinded_hash blind_hash( const fc::sha256& hash, int i ) const;
blind_signature blind_sign( const blinded_hash& hash, int i ) const;
// WARNING! This may produce non-canonical signatures!
compact_signature unblind_signature( const extended_public_key& bob,
const blind_signature& sig,
const fc::sha256& hash, int i ) const;
private:
extended_private_key private_derive_rest( const fc::sha512& hash,
int num ) const;
private_key generate_a( int i ) const;
private_key generate_b( int i ) const;
private_key generate_c( int i ) const;
private_key generate_d( int i ) const;
private_key_secret compute_p( int i ) const;
private_key_secret compute_q( int i, const private_key_secret& p ) const;
sha256 c;
int child_num, parent_fp;
uint8_t depth;
};
;
struct range_proof_info
{
......
......@@ -43,14 +43,6 @@ namespace fc { namespace ecc {
*(*dest)++ = i & 0xff;
}
static unsigned int _get( unsigned char** src )
{
unsigned int result = *(*src)++ << 24;
result |= *(*src)++ << 16;
result |= *(*src)++ << 8;
result |= *(*src)++;
return result;
}
static chr37 _derive_message( char first, const char* key32, int i )
{
......@@ -67,10 +59,6 @@ namespace fc { namespace ecc {
return _derive_message( *key.begin(), key.begin() + 1, i );
}
static chr37 _derive_message( const private_key_secret& key, int i )
{
return _derive_message( 0, key.data(), i );
}
const ec_group& get_curve()
{
......@@ -229,163 +217,7 @@ namespace fc { namespace ecc {
return private_key( k );
}
static fc::string _to_base58( const extended_key_data& key )
{
char *buffer = (char*)alloca(key.size() + 4);
memcpy( buffer, key.begin(), key.size() );
fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( key.begin(), key.size() ));
memcpy( buffer + key.size(), double_hash.data(), 4 );
return fc::to_base58( buffer, sizeof(buffer) );
}
static void _parse_extended_data( unsigned char* buffer, fc::string base58 )
{
memset( buffer, 0, 78 );
std::vector<char> decoded = fc::from_base58( base58 );
unsigned int i = 0;
for ( char c : decoded )
{
if ( i >= 78 || i > decoded.size() - 4 ) { break; }
buffer[i++] = c;
}
}
extended_public_key extended_public_key::derive_child(int i) const
{
FC_ASSERT( !(i&0x80000000), "Can't derive hardened public key!" );
return derive_normal_child(i);
}
extended_key_data extended_public_key::serialize_extended() const
{
extended_key_data result;
unsigned char* dest = (unsigned char*) result.begin();
detail::_put( &dest, BTC_EXT_PUB_MAGIC );
*dest++ = depth;
detail::_put( &dest, parent_fp );
detail::_put( &dest, child_num );
memcpy( dest, c.data(), c.data_size() ); dest += 32;
public_key_data key = serialize();
memcpy( dest, key.begin(), key.size() );
return result;
}
extended_public_key extended_public_key::deserialize( const extended_key_data& data )
{
return from_base58( _to_base58( data ) );
}
fc::string extended_public_key::str() const
{
return _to_base58( serialize_extended() );
}
extended_public_key extended_public_key::from_base58( const fc::string& base58 )
{
unsigned char buffer[78];
unsigned char* ptr = buffer;
_parse_extended_data( buffer, base58 );
FC_ASSERT( detail::_get( &ptr ) == BTC_EXT_PUB_MAGIC, "Invalid extended private key" );
uint8_t d = *ptr++;
int fp = detail::_get( &ptr );
int cn = detail::_get( &ptr );
fc::sha256 chain;
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
public_key_data key;
memcpy( key.begin(), ptr, key.size() );
return extended_public_key( key, chain, cn, fp, d );
}
extended_public_key extended_private_key::get_extended_public_key() const
{
return extended_public_key( get_public_key(), c, child_num, parent_fp, depth );
}
public_key extended_public_key::generate_p(int i) const { return derive_normal_child(2*i + 0); }
public_key extended_public_key::generate_q(int i) const { return derive_normal_child(2*i + 1); }
extended_private_key extended_private_key::derive_child(int i) const
{
return i < 0 ? derive_hardened_child(i) : derive_normal_child(i);
}
extended_private_key extended_private_key::derive_normal_child(int i) const
{
const detail::chr37 data = detail::_derive_message( get_public_key().serialize(), i );
hmac_sha512 mac;
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
return private_derive_rest( l, i );
}
extended_private_key extended_private_key::derive_hardened_child(int i) const
{
hmac_sha512 mac;
private_key_secret key = get_secret();
const detail::chr37 data = detail::_derive_message( key, i );
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
return private_derive_rest( l, i );
}
extended_key_data extended_private_key::serialize_extended() const
{
extended_key_data result;
unsigned char* dest = (unsigned char*) result.begin();
detail::_put( &dest, BTC_EXT_PRIV_MAGIC );
*dest++ = depth;
detail::_put( &dest, parent_fp );
detail::_put( &dest, child_num );
memcpy( dest, c.data(), c.data_size() ); dest += 32;
*dest++ = 0;
private_key_secret key = get_secret();
memcpy( dest, key.data(), key.data_size() );
return result;
}
extended_private_key extended_private_key::deserialize( const extended_key_data& data )
{
return from_base58( _to_base58( data ) );
}
private_key extended_private_key::generate_a(int i) const { return derive_hardened_child(4*i + 0); }
private_key extended_private_key::generate_b(int i) const { return derive_hardened_child(4*i + 1); }
private_key extended_private_key::generate_c(int i) const { return derive_hardened_child(4*i + 2); }
private_key extended_private_key::generate_d(int i) const { return derive_hardened_child(4*i + 3); }
fc::string extended_private_key::str() const
{
return _to_base58( serialize_extended() );
}
extended_private_key extended_private_key::from_base58( const fc::string& base58 )
{
unsigned char buffer[78];
unsigned char* ptr = buffer;
_parse_extended_data( buffer, base58 );
FC_ASSERT( detail::_get( &ptr ) == BTC_EXT_PRIV_MAGIC, "Invalid extended private key" );
uint8_t d = *ptr++;
int fp = detail::_get( &ptr );
int cn = detail::_get( &ptr );
fc::sha256 chain;
memcpy( chain.data(), ptr, chain.data_size() ); ptr += chain.data_size();
ptr++;
private_key_secret key;
memcpy( key.data(), ptr, key.data_size() );
return extended_private_key( private_key::regenerate(key), chain, cn, fp, d );
}
extended_private_key extended_private_key::generate_master( const fc::string& seed )
{
return generate_master( seed.c_str(), seed.size() );
}
extended_private_key extended_private_key::generate_master( const char* seed, uint32_t seed_len )
{
hmac_sha512 mac;
fc::sha512 hash = mac.digest( "Bitcoin seed", 12, seed, seed_len );
extended_private_key result( private_key::regenerate( detail::_left(hash) ),
detail::_right(hash) );
return result;
}
}
void to_variant( const ecc::private_key& var, variant& vo )
......
......@@ -168,292 +168,6 @@ namespace fc { namespace ecc {
FC_ASSERT( pk_len == my->_key.size() );
}
extended_public_key::extended_public_key( const public_key& k, const fc::sha256& c,
int child, int parent, uint8_t depth )
: public_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { }
extended_public_key extended_public_key::derive_normal_child(int i) const
{
hmac_sha512 mac;
public_key_data key = serialize();
const detail::chr37 data = detail::_derive_message( key, i );
fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() );
fc::sha256 left = detail::_left(l);
FC_ASSERT( left < detail::get_curve_order() );
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) key.begin(), key.size(), (unsigned char*) left.data() ) > 0 );
// FIXME: check validity - if left + key == infinity then invalid
extended_public_key result( key, detail::_right(l), i, fingerprint(), depth + 1 );
return result;
}
static void to_bignum( const unsigned char* in, ssl_bignum& out, unsigned int len )
{
if ( *in & 0x80 )
{
unsigned char *buffer = (unsigned char*)alloca(len + 1);
*buffer = 0;
memcpy( buffer + 1, in, len );
BN_bin2bn( buffer, sizeof(buffer), out );
}
else
{
BN_bin2bn( in, len, out );
}
}
static void to_bignum( const private_key_secret& in, ssl_bignum& out )
{
to_bignum( (unsigned char*) in.data(), out, in.data_size() );
}
static void from_bignum( const ssl_bignum& in, unsigned char* out, unsigned int len )
{
unsigned int l = BN_num_bytes( in );
if ( l > len )
{
unsigned char *buffer = (unsigned char*)alloca(l);
BN_bn2bin( in, buffer );
memcpy( out, buffer + l - len, len );
}
else
{
memset( out, 0, len - l );
BN_bn2bin( in, out + len - l );
}
}
static void from_bignum( const ssl_bignum& in, private_key_secret& out )
{
from_bignum( in, (unsigned char*) out.data(), out.data_size() );
}
static void invert( const private_key_secret& in, private_key_secret& out )
{
ssl_bignum bn_in;
to_bignum( in, bn_in );
ssl_bignum bn_n;
to_bignum( detail::get_curve_order(), bn_n );
ssl_bignum bn_inv;
bn_ctx ctx( BN_CTX_new() );
FC_ASSERT( BN_mod_inverse( bn_inv, bn_in, bn_n, ctx ) );
from_bignum( bn_inv, out );
}
static void to_point( const public_key_data& in, ec_point& out )
{
bn_ctx ctx( BN_CTX_new() );
const ec_group& curve = detail::get_curve();
private_key_secret x;
memcpy( x.data(), in.begin() + 1, x.data_size() );
ssl_bignum bn_x;
to_bignum( x, bn_x );
FC_ASSERT( EC_POINT_set_compressed_coordinates_GFp( curve, out, bn_x, *in.begin() & 1, ctx ) > 0 );
}
static void from_point( const ec_point& in, public_key_data& out )
{
bn_ctx ctx( BN_CTX_new() );
const ec_group& curve = detail::get_curve();
ssl_bignum bn_x;
ssl_bignum bn_y;
FC_ASSERT( EC_POINT_get_affine_coordinates_GFp( curve, in, bn_x, bn_y, ctx ) > 0 );
private_key_secret x;
from_bignum( bn_x, x );
memcpy( out.begin() + 1, x.data(), out.size() - 1 );
*out.begin() = BN_is_bit_set( bn_y, 0 ) ? 3 : 2;
}
// static void print(const unsigned char* data) {
// for (int i = 0; i < 32; i++) {
// printf("%02x", *data++);
// }
// }
//
// static void print(private_key_secret key) {
// print((unsigned char*) key.data());
// }
//
// static void print(public_key_data key) {
// print((unsigned char*) key.begin() + 1);
// }
static void canonicalize( unsigned char *int256 )
{
fc::sha256 biggi( (char*) int256, 32 );
if ( detail::get_half_curve_order() >= biggi )
{
return; // nothing to do
}
ssl_bignum bn_k;
to_bignum( int256, bn_k, 32 );
ssl_bignum bn_n;
to_bignum( detail::get_curve_order(), bn_n );
FC_ASSERT( BN_sub( bn_k, bn_n, bn_k ) );
from_bignum( bn_k, int256, 32 );
}
static public_key compute_k( const private_key_secret& a, const private_key_secret& c,
const public_key& p )
{
private_key_secret prod = a;
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) c.data() ) > 0 );
invert( prod, prod );
public_key_data P = p.serialize();
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) P.begin(), P.size(), (unsigned char*) prod.data() ) );
// printf("K: "); print(P); printf("\n");
return public_key( P );
}
static public_key compute_t( const private_key_secret& a, const private_key_secret& b,
const private_key_secret& c, const private_key_secret& d,
const public_key_data& p, const public_key_data& q )
{
private_key_secret prod;
invert( c, prod ); // prod == c^-1
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) d.data() ) > 0 );
// prod == c^-1 * d
public_key_data accu = p;
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) prod.data() ) );
// accu == prod * P == c^-1 * d * P
ec_point point_accu( EC_POINT_new( detail::get_curve() ) );
to_point( accu, point_accu );
ec_point point_q( EC_POINT_new( detail::get_curve() ) );
to_point( q, point_q );
bn_ctx ctx(BN_CTX_new());
FC_ASSERT( EC_POINT_add( detail::get_curve(), point_accu, point_accu, point_q, ctx ) > 0 );
from_point( point_accu, accu );
// accu == c^-1 * a * P + Q
FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) b.data() ) );
// accu == c^-1 * a * P + Q + b*G
public_key_data k = compute_k( a, c, p ).serialize();
memcpy( prod.data(), k.begin() + 1, prod.data_size() );
// prod == Kx
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) a.data() ) > 0 );
// prod == Kx * a
invert( prod, prod );
// prod == (Kx * a)^-1
FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) prod.data() ) );
// accu == (c^-1 * a * P + Q + b*G) * (Kx * a)^-1
// printf("T: "); print(accu); printf("\n");
return public_key( accu );
}
extended_private_key::extended_private_key( const private_key& k, const sha256& c,
int child, int parent, uint8_t depth )
: private_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { }
extended_private_key extended_private_key::private_derive_rest( const fc::sha512& hash,
int i) const
{
fc::sha256 left = detail::_left(hash);
FC_ASSERT( left < detail::get_curve_order() );
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) left.data(), (unsigned char*) get_secret().data() ) > 0 );
extended_private_key result( private_key::regenerate( left ), detail::_right(hash),
i, fingerprint(), depth + 1 );
return result;
}
public_key extended_private_key::blind_public_key( const extended_public_key& bob, int i ) const
{
private_key_secret a = generate_a(i).get_secret();
private_key_secret b = generate_b(i).get_secret();
private_key_secret c = generate_c(i).get_secret();
private_key_secret d = generate_d(i).get_secret();
public_key_data p = bob.generate_p(i).serialize();
public_key_data q = bob.generate_q(i).serialize();
// printf("a: "); print(a); printf("\n");
// printf("b: "); print(b); printf("\n");
// printf("c: "); print(c); printf("\n");
// printf("d: "); print(d); printf("\n");
// printf("P: "); print(p); printf("\n");
// printf("Q: "); print(q); printf("\n");
return compute_t( a, b, c, d, p, q );
}
blinded_hash extended_private_key::blind_hash( const fc::sha256& hash, int i ) const
{
private_key_secret a = generate_a(i).get_secret();
private_key_secret b = generate_b(i).get_secret();
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) a.data(), (unsigned char*) hash.data() ) > 0 );
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) a.data(), (unsigned char*) b.data() ) > 0 );
// printf("hash: "); print(hash); printf("\n");
// printf("blinded: "); print(a); printf("\n");
return a;
}
private_key_secret extended_private_key::compute_p( int i ) const
{
private_key_secret p_inv = derive_normal_child( 2*i ).get_secret();
invert( p_inv, p_inv );
// printf("p: "); print(p_inv); printf("\n");
return p_inv;
}
private_key_secret extended_private_key::compute_q( int i, const private_key_secret& p ) const
{
private_key_secret q = derive_normal_child( 2*i + 1 ).get_secret();
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) q.data(), (unsigned char*) p.data() ) > 0 );
// printf("q: "); print(q); printf("\n");
return q;
}
blind_signature extended_private_key::blind_sign( const blinded_hash& hash, int i ) const
{
private_key_secret p = compute_p( i );
private_key_secret q = compute_q( i, p );
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) p.data(), (unsigned char*) hash.data() ) > 0 );
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) p.data(), (unsigned char*) q.data() ) > 0 );
// printf("blind_sig: "); print(p); printf("\n");
return p;
}
compact_signature extended_private_key::unblind_signature( const extended_public_key& bob,
const blind_signature& sig,
const fc::sha256& hash,
int i ) const
{
private_key_secret a = generate_a(i).get_secret();
private_key_secret b = generate_b(i).get_secret();
private_key_secret c = generate_c(i).get_secret();
private_key_secret d = generate_d(i).get_secret();
public_key p = bob.generate_p(i);
public_key q = bob.generate_q(i);
public_key_data k = compute_k( a, c, p );
public_key_data t = compute_t( a, b, c, d, p, q ).serialize();
FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) c.data(), (unsigned char*) sig.data() ) > 0 );
FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) c.data(), (unsigned char*) d.data() ) > 0 );
compact_signature result;
memcpy( result.begin() + 1, k.begin() + 1, 32 );
memcpy( result.begin() + 33, c.data(), 32 );
canonicalize( result.begin() + 33 );
// printf("unblinded: "); print(result.begin() + 33); printf("\n");
for ( int i = 0; i < 4; i++ )
{
unsigned char pubkey[33];
int pklen = 33;
if ( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) hash.data(),
(unsigned char*) result.begin() + 1,
pubkey, &pklen, 1, i ) )
{
if ( !memcmp( t.begin(), pubkey, sizeof(pubkey) ) )
{
*result.begin() = 27 + 4 + i;
return result;
// } else {
// printf("Candidate: "); print( pubkey ); printf("\n");
}
}
}
FC_ASSERT( 0, "Failed to unblind - use different i" );
}
commitment_type blind( const blind_factor_type& blind, uint64_t value )
{
......
......@@ -2,7 +2,6 @@ file(GLOB HEADERS "include/eos/types/*.hpp")
add_library( eos_types
Asset.cpp
PublicKey.cpp
TypeParser.cpp
AbiSerializer.cpp
native.cpp
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <eos/types/PublicKey.hpp>
#include <fc/crypto/base58.hpp>
#include <fc/crypto/ripemd160.hpp>
#include <fc/exception/exception.hpp>
#include <fc/io/raw.hpp>
#define KEY_PREFIX "EOS"
namespace eosio { namespace types {
PublicKey::PublicKey():key_data(){};
PublicKey::PublicKey(const fc::ecc::public_key_data& data)
:key_data( data ) {};
PublicKey::PublicKey(const fc::ecc::public_key& pubkey)
:key_data( pubkey ) {};
PublicKey::PublicKey(const std::string& base58str)
{
// TODO: Refactor syntactic checks into static is_valid()
// to make PublicKey API more similar to address API
std::string prefix( KEY_PREFIX );
const size_t prefix_len = prefix.size();
FC_ASSERT(base58str.size() > prefix_len);
FC_ASSERT(base58str.substr(0, prefix_len) == prefix , "", ("base58str", base58str));
auto bin = fc::from_base58(base58str.substr(prefix_len));
auto bin_key = fc::raw::unpack<BinaryKey>(bin);
key_data = bin_key.data;
FC_ASSERT(fc::ripemd160::hash(key_data.data, key_data.size())._hash[0] == bin_key.check);
}
PublicKey::operator fc::ecc::public_key_data() const
{
return key_data;
};
PublicKey::operator fc::ecc::public_key() const
{
return fc::ecc::public_key(key_data);
};
PublicKey::operator std::string() const
{
BinaryKey k;
k.data = key_data;
k.check = fc::ripemd160::hash( k.data.data, k.data.size() )._hash[0];
auto data = fc::raw::pack( k );
return KEY_PREFIX + fc::to_base58( data.data(), data.size() );
}
bool operator == (const PublicKey& p1, const fc::ecc::public_key& p2)
{
return p1.key_data == p2.serialize();
}
bool operator == (const PublicKey& p1, const PublicKey& p2)
{
return p1.key_data == p2.key_data;
}
bool operator != (const PublicKey& p1, const PublicKey& p2)
{
return p1.key_data != p2.key_data;
}
bool operator <(const PublicKey& p1, const PublicKey& p2)
{
return p1.key_data < p2.key_data;
};
std::ostream& operator<<(std::ostream& s, const PublicKey& k) {
s << "PublicKey(" << std::string(k) << ')';
return s;
}
}} // eosio::types
namespace fc
{
using namespace std;
void to_variant(const eosio::types::PublicKey& var, fc::variant& vo)
{
vo = std::string(var);
}
void from_variant(const fc::variant& var, eosio::types::PublicKey& vo)
{
vo = eosio::types::PublicKey(var.as_string());
}
} // fc
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <fc/crypto/elliptic.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/reflect/variant.hpp>
namespace eosio { namespace types {
struct PublicKey
{
struct BinaryKey
{
BinaryKey() {}
uint32_t check = 0;
fc::ecc::public_key_data data;
};
fc::ecc::public_key_data key_data;
PublicKey();
PublicKey(const fc::ecc::public_key_data& data);
PublicKey(const fc::ecc::public_key& pubkey);
explicit PublicKey(const std::string& base58str);
operator fc::ecc::public_key_data() const;
operator fc::ecc::public_key() const;
explicit operator std::string() const;
friend bool operator == ( const PublicKey& p1, const fc::ecc::public_key& p2);
friend bool operator == ( const PublicKey& p1, const PublicKey& p2);
friend bool operator != ( const PublicKey& p1, const PublicKey& p2);
friend bool operator < ( const PublicKey& p1, const PublicKey& p2);
friend std::ostream& operator<< (std::ostream& s, const PublicKey& k);
bool is_valid_v1(const std::string& base58str);
};
}} // namespace eosio::types
namespace fc
{
void to_variant(const eosio::types::PublicKey& var, fc::variant& vo);
void from_variant(const fc::variant& var, eosio::types::PublicKey& vo);
}
FC_REFLECT(eosio::types::PublicKey, (key_data))
FC_REFLECT(eosio::types::PublicKey::BinaryKey, (data)(check))
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <fc/io/datastream.hpp>
namespace eosio { namespace types {
using fc::datastream;
struct InputDatastream {
datastream<const char*> ds;
vector<char> value;
InputDatastream( const std::string& data )
:ds(nullptr,0) {
if( data.size() ) {
value.resize(data.size());
memcpy( value.data(), data.c_str(), data.size() );
ds = fc::datastream<const char*>( value.data(), value.size() );
}
}
std::string read( uint32_t bytes ) {
FC_ASSERT( bytes <= 1024*1024 );
vector<char> result; result.resize(bytes);
ds.read( result.data(), bytes );
return string(result.data(),bytes);
}
void read( char* data, uint32_t len ) {
ds.read( data, len );
}
uint32_t remaining()const { return ds.remaining(); }
};
struct OutputDatastream {
vector<char> value;
datastream<char*> ds;
OutputDatastream( uint64_t bytes )
:ds(nullptr,0) {
FC_ASSERT( bytes <= 1024*1024 );
if( bytes ) {
value.resize(bytes);
ds = fc::datastream<char*>( value.data(), value.size() );
}
}
void write( const char* d, uint32_t size ) {
ds.write( d, size );
}
void write( const std::string& data, uint32_t size ) {
FC_ASSERT( size <= data.size() );
ds.write( data.c_str(), size );
}
std::string data()const {
if( value.size() )
return std::string( value.data(), value.size() );
else
return std::string();
}
uint32_t tellp()const { return ds.tellp(); }
uint32_t remaining()const { return ds.remaining(); }
};
struct SizeDatastream {
datastream<size_t> ds;
SizeDatastream(){}
void write( const char* d, uint32_t size ) {
ds.write( d, size );
}
void write( const std::string& data, uint32_t size ) {
ds.write( nullptr, size );
}
uint32_t tellp()const { return ds.tellp(); }
};
}} // namespace eosio::types
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eos/types/native.hpp>
namespace eosio { namespace types {
class InputDatastream;
class OutputDatastream;
/**
* This class provides a wren wrapper for intergers up to 256 bits and
* supports seralizing from 8 to 256 bits based upon the arguments passed to
* unpack and pack.
*
* The WREN code generator will construct a UInt for all integer fields and then
* implement pack/unpack to the proper width. This minimizies the number of
* unique classes that we need to define for WREN and comes with minimal overhead
* due to boost::multiprecision's internal optimizations
*/
class UInt {
public:
UInt256 value;
UInt256( double value = 0 )
:value( int64_t(value) ){}
UInt operator+( const UInt& other )const {
return value + other.value;
}
void unpack( InputDatastream&, int size = 256 );
void pack( OutputDatastream&, int size = 256 )const;
#define BIND_OP(X) .bindMethod<decltype(&UInt::operator X), &UInt64::operator X>( false, ##X"(_)" )
static void registerWrenClass() {
wrenpp::beginModule( "main" )
.bindClass<Wren::UInt64, double>( "UInt" )
.bindMethod<decltype(&UInt::unpack), &UInt::unpack>( false, "unpack(_,_)" )
.bindMethod<decltype(&UInt::pack), &UInt::pack>( false, "pack(_,_)" )
BIND_OP(+)
/*
.bindMethod<decltype(&UInt::sub), &Wren::UInt64::sub>( false, "-(_)" )
.bindMethod<decltype(&UInt::mul), &Wren::UInt64::mul>( false, "*(_)" )
.bindMethod<decltype(&UInt::div), &Wren::UInt64::div>( false, "/(_)" )
.bindMethod<decltype(&UInt::mod), &Wren::UInt64::mod>( false, "%(_)" )
.bindMethod<decltype(&UInt::fromString), &Wren::UInt64::fromString>( true, "fromString(_)" )
.bindMethod<decltype(&UInt::toString), &Wren::UInt64::toString>( false, "toString()" )
*/
.endClass()
.endModule();
}
static string wrenScript() {
static const auto script = R"(
foreign class UInt64 {
construct new(v) {}
foreign unpack( datastream, size )
foreign pack( datastream, size )
foreign +(v)
foreign -(v)
foreign *(v)
foreign /(v)
foreign %(v)
foreign toString()
foreign static fromString(s)
}
)";
return script;
}
};
}} /// namespace eosio::types
......@@ -7,7 +7,6 @@
/// @file Exists to make including the eos types less toxic. Build error hilarity ensues if you don't include enough of
/// these in the right order.
#include <eos/types/PublicKey.hpp>
#include <eos/types/Asset.hpp>
#include <eos/types/native.hpp>
#include <eos/types/generated.hpp>
typedef Name AccountName
typedef Name PermissionName
typedef Name FuncName
typedef FixedString32 MessageName
typedef FixedString32 TypeName
typedef name account_name
typedef name permission_name
typedef name action_name
typedef FixedString32 Messagename
typedef FixedString32 Typename
# import account type as localtype
struct AccountPermission
account AccountName
permission PermissionName
account account_name
permission permission_name
struct Message
code AccountName # the contract defining the primary code to execute for code/type
type FuncName # the action to be taken
code account_name # the contract defining the primary code to execute for code/type
type action_name # the action to be taken
authorization AccountPermission[] # the accounts and permission levels provided
data Bytes # opaque data processed by code
......@@ -24,15 +24,15 @@ struct Transaction
refBlockNum UInt16
refBlockPrefix UInt32
expiration Time
scope AccountName[] # the data may be accessed while processing this transaction
readscope AccountName[]
scope account_name[] # the data may be accessed while processing this transaction
readscope account_name[]
messages Message[]
struct SignedTransaction inherits Transaction
signatures Signature[]
signatures signature[]
struct KeyPermissionWeight
key PublicKey
key public_key_type
weight UInt16
struct Authority
......@@ -40,7 +40,7 @@ struct Authority
keys KeyPermissionWeight[]
accounts AccountPermissionWeight[]
struct BlockchainConfiguration
struct chain_config
maxBlockSize UInt32
targetBlockSize UInt32
maxStorageSize UInt64
......@@ -54,95 +54,95 @@ struct BlockchainConfiguration
maxInlineMsgSize UInt32
maxGenTrxSize UInt32
struct TypeDef
newTypeName TypeName
type TypeName
struct type_def
newTypename Typename
type Typename
struct Action
action Name
type TypeName
struct action
action name
type Typename
struct Table
table Name # the name of the table
indextype TypeName # the kind of index, i64, i128i128, etc
keynames TypeName[] # names for the keys defined by keytype
keytypes TypeName[] # the meaning / type of key parameters, how to convert binary key to json
type TypeName # the meaning / type of the binary data stored in this table
struct table
table name # the name of the table
indextype Typename # the kind of index, i64, i128i128, etc
keynames Typename[] # names for the keys defined by keytype
keytypes Typename[] # the meaning / type of key parameters, how to convert binary key to json
type Typename # the meaning / type of the binary data stored in this table
struct Abi
types TypeDef[]
structs Struct[]
actions Action[]
tables Table[]
struct abi
types type_def[]
structs meta_struct[]
actions action[]
tables table[]
struct transfer
from AccountName # may not be the message.sender if message.sender has delegated authority by from
to AccountName
from account_name # may not be the message.sender if message.sender has delegated authority by from
to account_name
amount UInt64
memo String
struct lock
from AccountName
to AccountName
from account_name
to account_name
amount ShareType
struct unlock
account AccountName
account account_name
amount ShareType
struct claim
account AccountName
account account_name
amount ShareType
struct newaccount
creator AccountName
name AccountName
creator account_name
name account_name
owner Authority
active Authority
recovery Authority
deposit Asset
struct setcode
account AccountName # the account that is handling the message
account account_name # the account that is handling the message
vmtype UInt8 # the virtual machine type
vmversion UInt8 # the virtual machine version
code Bytes # the apply
abi Abi # the interface description of the code
abi abi # the interface description of the code
struct setproducer
name AccountName
key PublicKey
configuration BlockchainConfiguration
name account_name
key public_key_type
configuration chain_config
# implies message.sender account
struct okproducer
voter AccountName # The account casting a vote
producer AccountName # The producer being voted on
voter account_name # The account casting a vote
producer account_name # The producer being voted on
approve Int8 # 1 to approve, or 0 to disapprove
struct setproxy
stakeholder AccountName # The account with stake to be proxied
proxy AccountName # The account to cast votes with stakeholder's stake weight
stakeholder account_name # The account with stake to be proxied
proxy account_name # The account to cast votes with stakeholder's stake weight
struct updateauth
account AccountName
permission PermissionName
parent PermissionName
account account_name
permission permission_name
parent permission_name
authority Authority
struct deleteauth
account AccountName
permission PermissionName
account account_name
permission permission_name
struct linkauth # Specify a particular required permission for account to approve specified message type
account AccountName # The account to require permissions for
code AccountName # The contract to require permissions to invoke
type FuncName
requirement PermissionName # The permission name to require
account account_name # The account to require permissions for
code account_name # The contract to require permissions to invoke
type action_name
requirement permission_name # The permission name to require
struct unlinkauth
account AccountName # The account to require permissions for
code AccountName # The contract to require permissions to invoke
type FuncName
account account_name # The account to require permissions for
code account_name # The contract to require permissions to invoke
type action_name
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册