提交 78fa692f 编写于 作者: A arhag

Merge branch 'contracts-use-new-dbapi' into arhag

#pragma once
#include <eosiolib/table.hpp>
#include <eosiolib/multi_index.hpp>
#include <eosiolib/token.hpp>
#include <eosiolib/asset.hpp>
#include <eosiolib/dispatcher.hpp>
......@@ -61,6 +61,8 @@ namespace eosio {
uint64_t symbol = token_type::symbol;
token_type balance;
auto primary_key() const { return symbol; }
EOSLIB_SERIALIZE( account, (symbol)(balance) )
};
......@@ -68,6 +70,8 @@ namespace eosio {
uint64_t symbol = token_type::symbol;
token_type supply;
auto primary_key() const { return symbol; }
EOSLIB_SERIALIZE( currency_stats, (symbol)(supply) )
};
......@@ -75,25 +79,41 @@ namespace eosio {
* Each user stores their balance in the singleton table under the
* scope of their account name.
*/
typedef table64<code, accounts_table_name, code, account> accounts;
typedef table64<code, stats_table_name, code, currency_stats> stats;
typedef eosio::multi_index<accounts_table_name, account> accounts;
typedef eosio::multi_index<stats_table_name, currency_stats> stats;
static token_type get_balance( account_name owner ) {
return accounts::get_or_create( token_type::symbol, owner ).balance;
accounts t( code, owner );
auto ptr = t.find( symbol );
return ptr ? ptr->balance : token_type( asset(0, symbol) );
}
static void set_balance( account_name owner, token_type balance ) {
accounts::set( account{token_type::symbol,balance}, owner );
static void set_balance( account_name owner, token_type balance, account_name create_bill_to, account_name update_bill_to ) {
accounts t( code, owner );
auto f = [&](account& acc) {
acc.symbol = symbol;
acc.balance = balance;
};
auto ptr = t.find( symbol );
if (ptr) {
t.update( *ptr, update_bill_to, f);
} else {
t.emplace( create_bill_to, f);
}
}
static void on( const issue& act ) {
require_auth( code );
auto s = stats::get_or_create(token_type::symbol);
s.supply += act.quantity;
stats::set(s);
stats t( code, code );
auto ptr = t.find( symbol );
if (ptr) {
t.update(*ptr, 0, [&](currency_stats& s) { s.supply += act.quantity; });
} else {
t.emplace(code, [&](currency_stats& s) { s.supply = act.quantity; });
}
set_balance( code, get_balance( code ) + act.quantity );
set_balance( code, get_balance( code ) + act.quantity, code, 0 );
inline_transfer( code, act.to, act.quantity );
}
......@@ -103,8 +123,8 @@ namespace eosio {
require_auth( act.from );
require_recipient(act.to,act.from);
set_balance( act.from, get_balance( act.from ) - act.quantity );
set_balance( act.to, get_balance( act.to ) + act.quantity );
set_balance( act.from, get_balance( act.from ) - act.quantity, act.from, act.from );
set_balance( act.to, get_balance( act.to ) + act.quantity, act.from, 0 );
}
static void inline_transfer( account_name from, account_name to, token_type quantity,
......
......@@ -53,6 +53,7 @@ MAKE_SECONDARY_ITERATOR(idx128, uint128_t)
MAKE_SECONDARY_ITERATOR(idx256, uint256)
template<uint64_t TableName, typename T, typename... Indices>
class multi_index;
......@@ -104,7 +105,6 @@ struct index_by {
}
};
/*
template<int IndexNumber, uint64_t IndexName, typename T, typename Extractor>
auto make_index_by( Extractor&& l ) {
......
......@@ -64,8 +64,12 @@ struct account_permission {
permission_name permission;
};
typedef struct uint256 {
uint64_t words[4];
typedef union {
uint8_t bytes[32];
uint16_t uint16s[16];
uint32_t uint32s[8];
uint64_t uint64s[4];
uint128_t uint128s[2];
} uint256;
#ifdef __cplusplus
......
......@@ -89,5 +89,13 @@ namespace eosio {
};
/// @}
bool operator==( const uint256& a, const uint256& b ) {
return a.uint128s[0] == b.uint128s[0] && a.uint128s[1] == b.uint128s[1];
}
bool operator!=( const uint256& a, const uint256& b ) {
return !(a == b);
}
} // namespace eos
此差异已折叠。
......@@ -104,17 +104,17 @@ namespace multi_index_test {
const auto& entry1 = testtable.emplace( payer, [&]( auto& o ) {
o.id = 1;
o.val = uint256{.words = {0, 0, 0, 42}};
o.val = uint256{.uint64s = {0, 0, 0, 42}};
});
const auto& entry2 = testtable.emplace( payer, [&]( auto& o ) {
o.id = 2;
o.val = uint256{.words = {1, 2, 3, 4}};
o.val = uint256{.uint64s = {1, 2, 3, 4}};
});
const auto& entry3 = testtable.emplace( payer, [&]( auto& o ) {
o.id = 3;
o.val = uint256{.words = {0, 0, 0, 42}};
o.val = uint256{.uint64s = {0, 0, 0, 42}};
});
const auto* e = testtable.find( 2 );
......@@ -126,10 +126,10 @@ namespace multi_index_test {
auto validx = testtable.get_index<N(byval)>();
auto lower1 = validx.lower_bound(uint256{.words = {0, 0, 0, 40}});
auto lower1 = validx.lower_bound(uint256{.uint64s = {0, 0, 0, 40}});
print("First entry with a val of at least 40 has ID=", lower1->id, ".\n");
auto lower2 = validx.lower_bound(uint256{.words = {0, 0, 0, 50}});
auto lower2 = validx.lower_bound(uint256{.uint64s = {0, 0, 0, 50}});
print("First entry with a val of at least 50 has ID=", lower2->id, ".\n");
if( &*lower2 == e ) {
......@@ -142,7 +142,7 @@ namespace multi_index_test {
cout << item.val << "\n";
}
auto upper = validx.upper_bound(uint256{.words={0, 0, 0, 42}});
auto upper = validx.upper_bound(uint256{.uint64s={0, 0, 0, 42}});
print("First entry with a val greater than 42 has ID=", upper->id, ".\n");
......
......@@ -340,7 +340,7 @@ void apply_context::db_update_i64( int iterator, account_name payer, const char*
if( payer == account_name() ) payer = obj.payer;
if( account_name(obj.payer) == payer ) {
update_db_usage( obj.payer, buffer_size + 200 - old_size );
update_db_usage( obj.payer, buffer_size - old_size );
} else {
update_db_usage( obj.payer, -(old_size+200) );
update_db_usage( payer, (buffer_size+200) );
......
......@@ -99,7 +99,7 @@ class apply_context {
++t.count;
});
context.update_db_usage( payer, sizeof(secondary_key_type)+200 );
context.update_db_usage( payer, sizeof(secondary_key_type)+base_row_fee );
itr_cache.cache_table( tab );
return itr_cache.add( obj );
......@@ -107,7 +107,7 @@ class apply_context {
void remove( int iterator ) {
const auto& obj = itr_cache.get( iterator );
context.update_db_usage( obj.payer, -( sizeof(secondary_key_type)+200 ) );
context.update_db_usage( obj.payer, -( sizeof(secondary_key_type)+base_row_fee ) );
const auto& table_obj = itr_cache.get_table( obj.t_id );
context.require_write_lock( table_obj.scope );
......@@ -126,8 +126,8 @@ class apply_context {
if( payer == account_name() ) payer = obj.payer;
if( obj.payer != payer ) {
context.update_db_usage( obj.payer, -(sizeof(secondary_key_type)+200) );
context.update_db_usage( payer, +(sizeof(secondary_key_type)+200) );
context.update_db_usage( obj.payer, -(sizeof(secondary_key_type)+base_row_fee) );
context.update_db_usage( payer, +(sizeof(secondary_key_type)+base_row_fee) );
}
context.mutable_db.modify( obj, [&]( auto& o ) {
......@@ -440,6 +440,8 @@ class apply_context {
generic_index<contracts::index128_object> idx128;
generic_index<contracts::index256_object> idx256;
static constexpr int64_t base_row_fee = 200;
private:
iterator_cache<key_value_object> keyval_cache;
......
......@@ -132,8 +132,8 @@ namespace eosio { namespace chain { namespace contracts {
typedef secondary_index<uint128_t,index128_object_type>::index_object index128_object;
typedef secondary_index<uint128_t,index128_object_type>::index_index index128_index;
typedef secondary_index<uint256,index256_object_type>::index_object index256_object;
typedef secondary_index<uint256,index256_object_type>::index_index index256_index;
typedef secondary_index<fc::sha256,index256_object_type>::index_object index256_object;
typedef secondary_index<fc::sha256,index256_object_type>::index_index index256_index;
/*
struct index64_object : public chainbase::object<index64_object_type, index64_object> {
......
......@@ -610,9 +610,11 @@ class system_api : public context_aware_api {
}
void eosio_assert(bool condition, null_terminated_ptr str) {
std::string message( str );
if( !condition ) edump((message));
FC_ASSERT( condition, "assertion failed: ${s}", ("s",message));
if( !condition ) {
std::string message( str );
edump((message));
FC_ASSERT( condition, "assertion failed: ${s}", ("s",message));
}
}
fc::time_point_sec now() {
......@@ -764,7 +766,7 @@ class database_api : public context_aware_api {
DB_API_METHOD_WRAPPERS(idx64, uint64_t)
DB_API_METHOD_WRAPPERS(idx128, uint128_t)
DB_API_METHOD_WRAPPERS(idx256, uint256)
DB_API_METHOD_WRAPPERS(idx256, sha256)
};
......
......@@ -107,6 +107,7 @@ class sha256
uint64_t hash64(const char* buf, size_t len);
} // fc
namespace std
{
template<>
......@@ -117,6 +118,7 @@ namespace std
return *((size_t*)&s);
}
};
}
namespace boost
......
......@@ -332,7 +332,8 @@ namespace eosio { namespace testing {
if (tbl) {
const auto *obj = db.find<contracts::key_value_object, contracts::by_scope_primary>(boost::make_tuple(tbl->id, asset_symbol.value()));
if (obj) {
fc::datastream<const char *> ds(obj->value.data(), obj->value.size());
//balance is the second field after symbol, so skip the symbol
fc::datastream<const char *> ds(obj->value.data()+sizeof(symbol), obj->value.size()-sizeof(symbol));
fc::raw::unpack(ds, result);
}
}
......
......@@ -192,6 +192,11 @@ public:
memcpy( data.data()+sizeof(uint64_t), obj.value.data(), obj.value.size() );
}
static void copy_inline_row(const chain::contracts::key_value_object& obj, vector<char>& data) {
data.resize( obj.value.size() );
memcpy( data.data(), obj.value.data(), obj.value.size() );
}
static void copy_row(const chain::contracts::keystr_value_object& obj, vector<char>& data) {
data.resize( obj.primary_key.size() + obj.value.size() + 8 );
fc::datastream<char*> ds(data.data(), data.size());
......@@ -215,6 +220,11 @@ public:
memcpy( data.data()+3*sizeof(uint64_t), obj.value.data(), obj.value.size() );
}
static void copy_inline_row(const chain::contracts::key64x64x64_value_object& obj, vector<char>& data) {
data.resize( obj.value.size() );
memcpy( data.data(), obj.value.data(), obj.value.size() );
}
template<typename IndexType, typename Scope, typename Function>
void walk_table(const name& code, const name& scope, const name& table, Function f) const
{
......
......@@ -54,8 +54,8 @@ Usage: ./eosc create account [OPTIONS] creator name OwnerKey ActiveKey
Positionals:
creator TEXT The name of the account creating the new account
name TEXT The name of the new account
OwnerKey TEXT The owner public key for the account
ActiveKey TEXT The active public key for the account
OwnerKey TEXT The owner public key for the new account
ActiveKey TEXT The active public key for the new account
Options:
-s,--skip-signature Specify that unlocked wallet keys should not be used to sign transaction
......@@ -489,8 +489,8 @@ int main( int argc, char** argv ) {
auto createAccount = create->add_subcommand("account", localized("Create a new account on the blockchain"), false);
createAccount->add_option("creator", creator, localized("The name of the account creating the new account"))->required();
createAccount->add_option("name", account_name, localized("The name of the new account"))->required();
createAccount->add_option("OwnerKey", owner_key_str, localized("The owner public key for the account"))->required();
createAccount->add_option("ActiveKey", active_key_str, localized("The active public key for the account"))->required();
createAccount->add_option("OwnerKey", owner_key_str, localized("The owner public key for the new account"))->required();
createAccount->add_option("ActiveKey", active_key_str, localized("The active public key for the new account"))->required();
createAccount->add_flag("-s,--skip-signature", skip_sign, localized("Specify that unlocked wallet keys should not be used to sign transaction"));
add_standard_transaction_options(createAccount);
createAccount->set_callback([&] {
......
......@@ -2,6 +2,7 @@
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio/chain_plugin/chain_plugin.hpp>
#include <chainbase/chainbase.hpp>
#include <identity/identity.wast.hpp>
#include <identity/identity.abi.hpp>
......@@ -47,6 +48,7 @@ public:
abi_ser_test.set_abi(abi_test);
const global_property_object &gpo = control->get_global_properties();
FC_ASSERT(0 < gpo.active_producers.producers.size(), "No producers");
producer_name = (string)gpo.active_producers.producers.front().producer_name;
}
......@@ -112,7 +114,7 @@ public:
BOOST_REQUIRE_EQUAL(idnt, itr->primary_key);
vector<char> data;
read_only::copy_row(*itr, data);
read_only::copy_inline_row(*itr, data);
return abi_ser.binary_to_variant("identrow", data);
}
......@@ -131,17 +133,24 @@ public:
fc::variant get_certrow(uint64_t identity, const string& property, uint64_t trusted, const string& certifier) {
const auto& db = control->get_database();
const auto* t_id = db.find<table_id_object, by_code_scope_table>(boost::make_tuple(N(identity), identity, N(certs)));
const auto* t_id = db.find<table_id_object, by_code_scope_table>(boost::make_tuple(N(identity), identity, N( certs )));
FC_ASSERT(t_id != 0, "certrow not found");
uint64_t prop = string_to_name(property.c_str());
uint64_t cert = string_to_name(certifier.c_str());
const auto& idx = db.get_index<key64x64x64_value_index, by_scope_primary>();
auto itr = idx.lower_bound(boost::make_tuple(t_id->id, prop, trusted, cert));
const auto& idx = db.get_index<index256_index, by_secondary>();
std::array<uint64_t, 4> buf { { string_to_name(property.c_str()), trusted, string_to_name(certifier.c_str()), 0 } };
fc::sha256 key((char*)buf.data(), sizeof(uint64_t)*buf.size());
if (itr != idx.end() && itr->t_id == t_id->id && prop == itr->primary_key && trusted == itr->secondary_key && cert == itr->tertiary_key) {
auto itr = idx.lower_bound(boost::make_tuple(t_id->id, key));
if (itr != idx.end() && itr->t_id == t_id->id && itr->secondary_key == key) {
auto primary_key = itr->primary_key;
const auto& idx = db.get_index<key_value_index, by_scope_primary>();
auto itr = idx.lower_bound(boost::make_tuple(t_id->id, primary_key));
FC_ASSERT( itr != idx.end() && itr->t_id == t_id->id && primary_key == itr->primary_key,
"Record found in secondary index, but not found in primary index."
);
vector<char> data;
read_only::copy_row(*itr, data);
read_only::copy_inline_row(*itr, data);
return abi_ser.binary_to_variant("certrow", data);
} else {
return fc::variant(nullptr);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册