Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
e3dc3082
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e3dc3082
编写于
2月 19, 2018
作者:
C
Ciju John
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'upstream/master' into improveTestingFixture-stat576
上级
fed461e2
e734fef2
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
548 addition
and
548 deletion
+548
-548
contracts/eosio.system/eosio.system.abi
contracts/eosio.system/eosio.system.abi
+22
-1
contracts/eosio.system/eosio.system.cpp
contracts/eosio.system/eosio.system.cpp
+1
-0
contracts/eosio.system/eosio.system.hpp
contracts/eosio.system/eosio.system.hpp
+244
-18
contracts/eosio/eosio.cpp
contracts/eosio/eosio.cpp
+0
-119
contracts/eosiolib/generic_currency.hpp
contracts/eosiolib/generic_currency.hpp
+1
-1
contracts/eosiolib/multi_index.hpp
contracts/eosiolib/multi_index.hpp
+134
-53
contracts/eosiolib/multiindex.hpp
contracts/eosiolib/multiindex.hpp
+0
-341
contracts/multi_index_test/multi_index_test.cpp
contracts/multi_index_test/multi_index_test.cpp
+2
-2
eosio_build.sh
eosio_build.sh
+2
-2
libraries/appbase
libraries/appbase
+1
-1
libraries/chain/apply_context.cpp
libraries/chain/apply_context.cpp
+1
-0
libraries/chain/include/eosio/chain/account_object.hpp
libraries/chain/include/eosio/chain/account_object.hpp
+7
-0
libraries/chainbase
libraries/chainbase
+1
-1
libraries/testing/include/eosio/testing/tester.hpp
libraries/testing/include/eosio/testing/tester.hpp
+5
-1
libraries/testing/tester.cpp
libraries/testing/tester.cpp
+26
-2
scripts/eosio_build_darwin.sh
scripts/eosio_build_darwin.sh
+6
-6
tests/wasm_tests/eosio.system_tests.cpp
tests/wasm_tests/eosio.system_tests.cpp
+95
-0
未找到文件。
contracts/eosio.system/eosio.system.abi
浏览文件 @
e3dc3082
...
...
@@ -29,7 +29,22 @@
"fields": [
{"name":"value", "type":"string"}
]
},{
"name": "regproducer",
"base": "",
"fields": [
{"name":"producer", "type":"account_name"}
{"name":"producer_key", "type":"bytes"}
]
},{
"name": "stakevote",
"base": "",
"fields": [
{"name":"voter", "type":"account_name"}
{"name":"amount", "type":"asset"}
]
}
],
"actions": [{
"name": "transfer",
...
...
@@ -40,6 +55,12 @@
},{
"name": "nonce",
"type": "nonce"
},{
"name": "regproducer",
"type": "regproducer"
},{
"name": "stakevote",
"type": "stakevote"
}
],
"tables": [{
...
...
@@ -50,4 +71,4 @@
"key_types" : ["name"]
}
]
}
\ No newline at end of file
}
contracts/eosio.system/eosio.system.cpp
浏览文件 @
e3dc3082
...
...
@@ -11,6 +11,7 @@ extern "C" {
/// The apply method implements the dispatch of events to this contract
void
apply
(
uint64_t
code
,
uint64_t
act
)
{
print
(
eosio
::
name
(
code
),
"::"
,
eosio
::
name
(
act
)
);
eosiosystem
::
contract
<
N
(
eosio
)
>::
apply
(
code
,
act
);
}
}
contracts/eosio.system/eosio.system.hpp
浏览文件 @
e3dc3082
...
...
@@ -14,13 +14,59 @@
#include <eosiolib/multi_index.hpp>
#include <eosiolib/privileged.h>
#include <algorithm>
#include <map>
namespace
eosiosystem
{
using
eosio
::
indexed_by
;
using
eosio
::
const_mem_fun
;
using
eosio
::
bytes
;
using
std
::
map
;
using
std
::
pair
;
using
eosio
::
print
;
template
<
account_name
SystemAccount
>
class
contract
{
public:
static
const
account_name
system_account
=
SystemAccount
;
typedef
eosio
::
generic_currency
<
eosio
::
token
<
system_account
,
S
(
4
,
EOS
)
>
>
currency
;
typedef
typename
currency
::
token_type
system_token_type
;
struct
producer_votes
{
account_name
owner
;
uint128_t
total_votes
;
uint64_t
primary_key
()
const
{
return
owner
;
}
uint128_t
by_votes
()
const
{
return
total_votes
;
}
EOSLIB_SERIALIZE
(
producer_votes
,
(
owner
)(
total_votes
)
);
};
typedef
eosio
::
multi_index
<
N
(
producervote
),
producer_votes
,
indexed_by
<
N
(
prototalvote
),
const_mem_fun
<
producer_votes
,
uint128_t
,
&
producer_votes
::
by_votes
>
>
>
producer_votes_index_type
;
struct
account_votes
{
account_name
owner
;
account_name
proxy
;
uint32_t
last_update
;
system_token_type
staked
;
std
::
vector
<
account_name
>
producers
;
uint64_t
primary_key
()
const
{
return
owner
;
}
EOSLIB_SERIALIZE
(
account_votes
,
(
owner
)(
proxy
)(
last_update
)(
staked
)(
producers
)
);
};
typedef
eosio
::
multi_index
<
N
(
accountvotes
),
account_votes
>
account_votes_index_type
;
struct
producer_config
{
account_name
owner
;
eosio
::
bytes
packed_key
;
/// a packed public key object
uint64_t
primary_key
()
const
{
return
owner
;
}
EOSLIB_SERIALIZE
(
producer_config
,
(
owner
)(
packed_key
)
);
};
typedef
eosio
::
multi_index
<
N
(
producercfg
),
producer_config
>
producer_config_index_type
;
struct
total_resources
{
account_name
owner
;
...
...
@@ -34,7 +80,6 @@ namespace eosiosystem {
};
/**
* Every user 'from' has a scope/table that uses every receipient 'to' as the primary key.
*/
...
...
@@ -72,9 +117,10 @@ namespace eosiosystem {
};
ACTION
(
SystemAccount
,
regproducer
)
{
account_name
producer_to_register
;
account_name
producer
;
bytes
producer_key
;
EOSLIB_SERIALIZE
(
regproducer
,
(
producer
_to_register
)
);
EOSLIB_SERIALIZE
(
regproducer
,
(
producer
)(
producer_key
)
);
};
ACTION
(
SystemAccount
,
regproxy
)
{
...
...
@@ -83,21 +129,23 @@ namespace eosiosystem {
EOSLIB_SERIALIZE
(
regproxy
,
(
proxy_to_register
)
);
};
ACTION
(
SystemAccount
,
del
net
bw
)
{
ACTION
(
SystemAccount
,
del
egate
bw
)
{
account_name
from
;
account_name
receiver
;
typename
currency
::
token_type
stake_quantity
;
typename
currency
::
token_type
stake_net_quantity
;
typename
currency
::
token_type
stake_cpu_quantity
;
EOSLIB_SERIALIZE
(
del
netbw
,
(
from
)(
receiver
)(
stake
_quantity
)
)
EOSLIB_SERIALIZE
(
del
egatebw
,
(
from
)(
receiver
)(
stake_net_quantity
)(
stake_cpu
_quantity
)
)
};
ACTION
(
SystemAccount
,
undel
net
bw
)
{
ACTION
(
SystemAccount
,
undel
egate
bw
)
{
account_name
from
;
account_name
receiver
;
typename
currency
::
token_type
stake_quantity
;
typename
currency
::
token_type
unstake_net_quantity
;
typename
currency
::
token_type
unstake_cpu_quantity
;
EOSLIB_SERIALIZE
(
delnetbw
,
(
delegator
)(
receiver
)(
stake
_quantity
)
)
EOSLIB_SERIALIZE
(
undelegatebw
,
(
from
)(
receiver
)(
unstake_net_quantity
)(
unstake_cpu
_quantity
)
)
};
ACTION
(
SystemAccount
,
nonce
)
{
...
...
@@ -110,7 +158,14 @@ namespace eosiosystem {
// 1. hash + collision
// 2. incrementing count (key=> tablename
static
void
on
(
const
delnetbw
&
del
)
{
static
void
on
(
const
delegatebw
&
del
)
{
eosio_assert
(
del
.
stake_cpu_quantity
.
quantity
>=
0
,
"must stake a positive amount"
);
eosio_assert
(
del
.
stake_net_quantity
.
quantity
>=
0
,
"must stake a positive amount"
);
auto
total_stake
=
del
.
stake_cpu_quantity
+
del
.
stake_net_quantity
;
eosio_assert
(
total_stake
.
quantity
>=
0
,
"must stake a positive amount"
);
require_auth
(
del
.
from
);
del_bandwidth_index_type
del_index
(
SystemAccount
,
del
.
from
);
...
...
@@ -123,12 +178,14 @@ namespace eosiosystem {
del_index
.
emplace
(
del
.
from
,
[
&
](
auto
&
dbo
){
dbo
.
from
=
del
.
from
;
dbo
.
to
=
del
.
receiver
;
dbo
.
net_weight
=
del
.
stake_quantity
;
dbo
.
net_weight
=
del
.
stake_net_quantity
;
dbo
.
cpu_weight
=
del
.
stake_cpu_quantity
;
});
}
else
{
del_index
.
update
(
*
itr
,
del
.
from
,
[
&
](
auto
&
dbo
){
dbo
.
net_weight
=
del
.
stake_quantity
;
dbo
.
net_weight
=
del
.
stake_net_quantity
;
dbo
.
cpu_weight
=
del
.
stake_cpu_quantity
;
});
}
...
...
@@ -136,25 +193,190 @@ namespace eosiosystem {
if
(
tot_itr
==
nullptr
)
{
tot_itr
=
&
total_index
.
emplace
(
del
.
from
,
[
&
](
auto
&
tot
)
{
tot
.
owner
=
del
.
receiver
;
tot
.
total_net_weight
+=
del
.
stake_quantity
;
tot
.
total_net_weight
+=
del
.
stake_net_quantity
;
tot
.
total_cpu_weight
+=
del
.
stake_cpu_quantity
;
});
}
else
{
total_index
.
update
(
*
tot_itr
,
0
,
[
&
](
auto
&
tot
)
{
tot
.
total_net_weight
+=
del
.
stake_quantity
;
tot
.
total_net_weight
+=
del
.
stake_net_quantity
;
tot
.
total_cpu_weight
+=
del
.
stake_cpu_quantity
;
});
}
set_resource_limits
(
tot_itr
->
owner
,
tot_itr
->
total_ram
,
tot_itr
->
total_net_weight
.
quantity
,
tot_itr
->
total_cpu_weight
.
quantity
,
0
);
currency
::
inline_transfer
(
del
.
from
,
SystemAccount
,
del
.
stake_quantity
,
"stake bandwidth"
);
}
// delnetbw
currency
::
inline_transfer
(
del
.
from
,
SystemAccount
,
total_stake
,
"stake bandwidth"
);
}
// delegatebw
static
void
on
(
const
undelegatebw
&
del
)
{
eosio_assert
(
del
.
unstake_cpu_quantity
.
quantity
>=
0
,
"must stake a positive amount"
);
eosio_assert
(
del
.
unstake_net_quantity
.
quantity
>=
0
,
"must stake a positive amount"
);
auto
total_stake
=
del
.
unstake_cpu_quantity
+
del
.
unstake_net_quantity
;
eosio_assert
(
total_stake
.
quantity
>=
0
,
"must stake a positive amount"
);
require_auth
(
del
.
from
);
del_bandwidth_index_type
del_index
(
SystemAccount
,
del
.
from
);
total_resources_index_type
total_index
(
SystemAccount
,
del
.
receiver
);
//eosio_assert( is_account( del.receiver ), "can only delegate resources to an existing account" );
const
auto
&
dbw
=
del_index
.
get
(
del
.
receiver
);
eosio_assert
(
dbw
.
net_weight
>=
del
.
unstake_net_quantity
,
"insufficient staked net bandwidth"
);
eosio_assert
(
dbw
.
cpu_weight
>=
del
.
unstake_cpu_quantity
,
"insufficient staked cpu bandwidth"
);
del_index
.
update
(
dbw
,
del
.
from
,
[
&
](
auto
&
dbo
){
dbo
.
net_weight
-=
del
.
unstake_net_quantity
;
dbo
.
cpu_weight
-=
del
.
unstake_cpu_quantity
;
});
const
auto
&
totals
=
total_index
.
get
(
del
.
receiver
);
total_index
.
update
(
totals
,
0
,
[
&
](
auto
&
tot
)
{
tot
.
total_net_weight
-=
del
.
unstake_net_quantity
;
tot
.
total_cpu_weight
-=
del
.
unstake_cpu_quantity
;
});
set_resource_limits
(
totals
.
owner
,
totals
.
total_ram
,
totals
.
total_net_weight
.
quantity
,
totals
.
total_cpu_weight
.
quantity
,
0
);
/// TODO: implement / enforce time delays on withdrawing
currency
::
inline_transfer
(
SystemAccount
,
del
.
from
,
total_stake
,
"unstake bandwidth"
);
}
// undelegatebw
/**
* This method will create a producr_config and producer_votes object for 'producer'
*
* @pre producer is not already registered
* @pre producer to register is an account
* @pre authority of producer to register
*
*/
static
void
on
(
const
regproducer
&
reg
)
{
require_auth
(
reg
.
producer_to_register
);
auto
producer
=
reg
.
producer
;
require_auth
(
producer
);
producer_votes_index_type
votes
(
SystemAccount
,
SystemAccount
);
const
auto
*
existing
=
votes
.
find
(
producer
);
eosio_assert
(
!
existing
,
"producer already registered"
);
votes
.
emplace
(
producer
,
[
&
](
auto
&
pv
){
pv
.
owner
=
producer
;
pv
.
total_votes
=
0
;
});
producer_config_index_type
proconfig
(
SystemAccount
,
SystemAccount
);
proconfig
.
emplace
(
producer
,
[
&
](
auto
&
pc
)
{
pc
.
owner
=
producer
;
pc
.
packed_key
=
reg
.
producer_key
;
});
}
ACTION
(
SystemAccount
,
stakevote
)
{
account_name
voter
;
system_token_type
amount
;
EOSLIB_SERIALIZE
(
stakevote
,
(
voter
)(
amount
)
)
};
static
void
on
(
const
stakevote
&
sv
)
{
print
(
"on stake vote
\n
"
);
eosio_assert
(
sv
.
amount
.
quantity
>
0
,
"must stake some tokens"
);
require_auth
(
sv
.
voter
);
account_votes_index_type
avotes
(
SystemAccount
,
SystemAccount
);
const
auto
*
acv
=
avotes
.
find
(
sv
.
voter
);
if
(
!
acv
)
{
acv
=
&
avotes
.
emplace
(
sv
.
voter
,
[
&
](
auto
&
av
)
{
av
.
owner
=
sv
.
voter
;
av
.
last_update
=
now
();
av
.
proxy
=
0
;
});
}
uint128_t
old_weight
=
acv
->
staked
.
quantity
;
uint128_t
new_weight
=
old_weight
+
sv
.
amount
.
quantity
;
producer_votes_index_type
votes
(
SystemAccount
,
SystemAccount
);
for
(
auto
p
:
acv
->
producers
)
{
votes
.
update
(
votes
.
get
(
p
),
0
,
[
&
](
auto
&
v
)
{
v
.
total_votes
-=
old_weight
;
v
.
total_votes
+=
new_weight
;
});
}
avotes
.
update
(
*
acv
,
0
,
[
&
](
auto
av
)
{
av
.
last_update
=
now
();
av
.
staked
+=
sv
.
amount
;
});
currency
::
inline_transfer
(
sv
.
voter
,
SystemAccount
,
sv
.
amount
,
"stake for voting"
);
};
ACTION
(
SystemAccount
,
voteproducer
)
{
account_name
voter
;
account_name
proxy
;
std
::
vector
<
account_name
>
producers
;
EOSLIB_SERIALIZE
(
voteproducer
,
(
voter
)(
proxy
)(
producers
)
)
};
/**
* @pre vp.producers must be sorted from lowest to highest
* @pre if proxy is set then no producers can be voted for
* @pre every listed producer or proxy must have been previously registered
* @pre vp.voter must authorize this action
* @pre voter must have previously staked some EOS for voting
*/
static
void
on
(
const
voteproducer
&
vp
)
{
eosio_assert
(
std
::
is_sorted
(
vp
.
producers
.
begin
(),
vp
.
producers
.
end
()
),
"producer votes must be sorted"
);
eosio_assert
(
vp
.
producers
.
size
()
<=
30
,
"attempt to vote for too many producers"
);
if
(
vp
.
proxy
!=
0
)
eosio_assert
(
vp
.
producers
.
size
()
==
0
,
"cannot vote for producers and proxy at same time"
);
require_auth
(
vp
.
voter
);
account_votes_index_type
avotes
(
SystemAccount
,
SystemAccount
);
const
auto
&
existing
=
avotes
.
get
(
vp
.
voter
);
std
::
map
<
account_name
,
pair
<
uint128_t
,
uint128_t
>
>
producer_vote_changes
;
uint128_t
old_weight
=
existing
.
staked
.
quantity
;
/// old time
uint128_t
new_weight
=
old_weight
;
/// TODO: update for current weight
for
(
const
auto
&
p
:
existing
.
producers
)
producer_vote_changes
[
p
].
first
=
old_weight
;
for
(
const
auto
&
p
:
vp
.
producers
)
producer_vote_changes
[
p
].
second
=
new_weight
;
producer_votes_index_type
votes
(
SystemAccount
,
SystemAccount
);
for
(
const
auto
&
delta
:
producer_vote_changes
)
{
if
(
delta
.
second
.
first
!=
delta
.
second
.
second
)
{
const
auto
&
provote
=
votes
.
get
(
delta
.
first
);
votes
.
update
(
provote
,
0
,
[
&
](
auto
&
pv
){
pv
.
total_votes
-=
delta
.
second
.
first
;
pv
.
total_votes
+=
delta
.
second
.
second
;
});
}
}
avotes
.
update
(
existing
,
0
,
[
&
](
auto
&
av
)
{
av
.
proxy
=
vp
.
proxy
;
av
.
last_update
=
now
();
av
.
producers
=
vp
.
producers
;
});
}
static
void
on
(
const
regproxy
&
reg
)
{
require_auth
(
reg
.
proxy_to_register
);
}
static
void
on
(
const
nonce
&
)
{
...
...
@@ -162,7 +384,11 @@ namespace eosiosystem {
static
void
apply
(
account_name
code
,
action_name
act
)
{
if
(
!
eosio
::
dispatch
<
contract
,
regproducer
,
regproxy
,
delnetbw
,
nonce
>
(
code
,
act
)
)
{
if
(
!
eosio
::
dispatch
<
contract
,
regproducer
,
regproxy
,
delegatebw
,
undelegatebw
,
regproducer
,
voteproducer
,
stakevote
,
nonce
>
(
code
,
act
)
)
{
if
(
!
eosio
::
dispatch
<
currency
,
typename
currency
::
transfer
,
typename
currency
::
issue
>
(
code
,
act
)
)
{
eosio
::
print
(
"Unexpected action: "
,
eosio
::
name
(
act
),
"
\n
"
);
eosio_assert
(
false
,
"received unexpected action"
);
...
...
contracts/eosio/eosio.cpp
已删除
100644 → 0
浏览文件 @
fed461e2
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
namespace
native
{
/**
@defgroup eoscontract EOS Contract
@brief Documents the interface to the EOS currency contract
@ingroup contracts
@{
*/
/**
* @ingroup contracts
* @brief Defines the base class for all contracts
*/
struct
contract
{
/**
* @brief updates the code that will be executed for this contract
*
* <h3> Required Authority </h3>
*
* Requires authority of *this* contract.
*
* <h3> Required Scope </h3>
*
* Requires scope of *this* contract.
*
* @note the change in code does not take effect until the start of the next block
*/
void
setcode
(
Bytes
code
,
Abi
abi
,
uint8_t
vm
=
0
,
uint8_t
vm_version
=
0
)
final
;
/**
* @brief updates the authority required for a named permission
*
* <h3> Required Authority </h3>
*
* Requires authority of *this* contract.
*
* <h3> Required Scope </h3>
*
* Requires scope of *this* contract.
*/
void
setauth
(
Name
permission
,
///< the name for the permission being set
Name
parent
,
///< the parent permission to this permission
Authority
auth
///< the set of keys/accounts and threshold );
)
final
;
/**
* @brief set the local named permission required for `this` account/contract to
* call `con::act(...)`
*
* <h3> Required Authority </h3>
*
* Requires authority of *this* contract.
*
* <h3> Required Scope </h3>
*
* Requires scope of *this* contract.
*
* @pre myperm must be defined by prior call to @ref setauth
*
* @param con - the name of the contract this permission applies
* @param act - the name of the action on @ref con this permission applies to
* @param myperm - the name of a permission set by @ref setauth on `this` contract
*/
void
setperm
(
Name
con
,
Name
act
,
Name
myperm
);
};
/**
* @class eos
* @brief A *native* currency contract implemented with account named `eos`
* @ingroup contracts
*
* @details The EOS contract is a *native* currency contract implemented with account named `eos`. This contract enables
* users to transfer EOS tokens to each other. This contract is designed to work the @ref stakedcontract and
* @ref systemcontract when creating new accounts, claiming staked EOS.
*/
struct
eos
:
public
contract
{
/**
@brief This action will transfer funds from one account to another.
@pre `from`'s balance must be greaterthan or equal to `amount` transferred.
@pre The amount transferred must be greater than 0
@pre `to` and `from` may not be the same account.
<h3> Required Authority </h3>
This action requires the authority of the `from` account.
<h3>Required Scope </h3>
This action requires access to `from` and `to` account scopes. It does not require
access to the `eos` scope which means that multiple transfers can execute in parallel
as long as they don't have any overlapping scopes.
<h3> Required Recipients </h3>
This action requires that the accounts `from` and `to` are listed in the required recipients. This ensures
other contracts are notified anytime EOS tokens are transferred.
*/
void
transfer
(
account_name
from
,
///< account from which EOS will be withdrawn
account_name
to
,
///< account to receive EOS, may not be same as `from`
uint64_t
amount
///< must be greater than 0 and less or equal to `from`'s balance
);
};
/// class EOS
/// @}
}
contracts/eosiolib/generic_currency.hpp
浏览文件 @
e3dc3082
...
...
@@ -110,7 +110,7 @@ namespace eosio {
static
void
inline_transfer
(
account_name
from
,
account_name
to
,
token_type
quantity
,
string
memo
=
string
()
)
{
action
act
(
permission_level
(
code
,
N
(
active
)),
transfer_memo
(
from
,
to
,
asset
(
quantity
),
move
(
memo
)
));
action
act
(
permission_level
(
from
,
N
(
active
)),
transfer_memo
(
from
,
to
,
asset
(
quantity
),
move
(
memo
)
));
act
.
send
();
}
...
...
contracts/eosiolib/multi_index.hpp
浏览文件 @
e3dc3082
...
...
@@ -29,6 +29,9 @@ struct secondary_iterator<uint64_t> {
static
int
db_idx_next
(
int
iterator
,
uint64_t
*
primary
)
{
return
db_idx64_next
(
iterator
,
primary
);
}
static
int
db_idx_prev
(
int
iterator
,
uint64_t
*
primary
)
{
return
db_idx64_previous
(
iterator
,
primary
);
}
static
void
db_idx_remove
(
int
iterator
)
{
db_idx64_remove
(
iterator
);
}
static
int
db_idx_find_primary
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
table
,
uint64_t
primary
,
uint64_t
&
secondary
)
{
return
db_idx64_find_primary
(
code
,
scope
,
table
,
&
secondary
,
primary
);
}
};
template
<
>
...
...
@@ -36,8 +39,19 @@ struct secondary_iterator<uint128_t> {
static
int
db_idx_next
(
int
iterator
,
uint64_t
*
primary
)
{
return
db_idx128_next
(
iterator
,
primary
);
}
static
int
db_idx_prev
(
int
iterator
,
uint64_t
*
primary
)
{
return
db_idx128_previous
(
iterator
,
primary
);
}
static
void
db_idx_remove
(
int
iterator
)
{
db_idx128_remove
(
iterator
);
}
static
int
db_idx_find_primary
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
table
,
uint64_t
primary
,
uint128_t
&
secondary
)
{
return
db_idx128_find_primary
(
code
,
scope
,
table
,
&
secondary
,
primary
);
}
};
int
db_idx_store
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
payer
,
uint64_t
primary
,
const
uint64_t
&
secondary
)
{
return
db_idx64_store
(
scope
,
table
,
payer
,
primary
,
&
secondary
);
}
int
db_idx_store
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
payer
,
uint64_t
primary
,
const
uint128_t
&
secondary
)
{
return
db_idx128_store
(
scope
,
table
,
payer
,
primary
,
&
secondary
);
}
void
db_idx_update
(
int
iterator
,
uint64_t
payer
,
const
uint64_t
&
secondary
)
{
db_idx64_update
(
iterator
,
payer
,
&
secondary
);
}
...
...
@@ -77,67 +91,73 @@ int db_idx_upperbound( uint64_t code, uint64_t scope, uint64_t table, uint128_t&
template
<
uint64_t
TableName
,
typename
T
,
typename
...
Indicies
>
class
multi_index
;
template
<
uint64_t
IndexName
,
typename
Extractor
>
struct
indexed_by
{
enum
constants
{
index_name
=
IndexName
};
typedef
Extractor
secondary_extractor_type
;
typedef
decltype
(
Extractor
()(
nullptr
)
)
secondary_type
;
};
template
<
int
IndexNumber
,
uint64_t
IndexName
,
typename
T
,
typename
Extractor
>
template
<
uint64_t
IndexName
,
typename
T
,
typename
Extractor
,
int
N
=
0
>
struct
index_by
{
//typedef typename std::decay<decltype( (Extractor())( *((const T*)(nullptr)) ) )>::type value_type;
typedef
Extractor
extractor_secondary_type
;
typedef
decltype
(
Extractor
()(
nullptr
)
)
secondary_type
;
typedef
Extractor
extractor_secondary_type
;
typedef
typename
std
::
decay
<
decltype
(
Extractor
()(
nullptr
)
)
>::
type
secondary_type
;
index_by
(){}
static
const
int
index_number
=
IndexNumber
;
static
const
uint64_t
index_name
=
IndexName
;
enum
constants
{
index_name
=
IndexName
,
index_number
=
N
};
constexpr
static
int
number
()
{
return
N
;
}
constexpr
static
uint64_t
name
()
{
return
IndexName
;
}
private:
template
<
uint64_t
,
typename
,
typename
...
>
friend
class
multi_index
;
Extractor
extract_secondary_key
;
static
auto
extract_secondary_key
(
const
T
&
obj
)
{
return
extractor_secondary_type
()(
obj
);
}
int
store
(
uint64_t
scope
,
uint64_t
payer
,
const
T
&
obj
)
{
// fetch primary key and secondary key here..
return
-
1
;
static
int
store
(
uint64_t
scope
,
uint64_t
payer
,
const
T
&
obj
)
{
return
db_idx_store
(
scope
,
IndexName
,
payer
,
obj
.
primary_key
(),
extract_secondary_key
(
obj
)
);
}
void
update
(
int
iterator
,
uint64_t
payer
,
const
secondary_type
&
secondary
)
{
static
void
update
(
int
iterator
,
uint64_t
payer
,
const
secondary_type
&
secondary
)
{
db_idx_update
(
iterator
,
payer
,
secondary
);
}
int
find_primary
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
primary
,
secondary_type
&
secondary
)
const
{
static
int
find_primary
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
primary
,
secondary_type
&
secondary
)
{
return
db_idx_find_primary
(
code
,
scope
,
IndexName
,
secondary
,
primary
);
}
void
remove
(
int
itr
)
{
static
void
remove
(
int
itr
)
{
secondary_iterator
<
secondary_type
>::
db_idx_remove
(
itr
);
}
int
find_secondary
(
uint64_t
code
,
uint64_t
scope
,
secondary_type
&
secondary
,
uint64_t
&
primary
)
const
{
static
int
find_secondary
(
uint64_t
code
,
uint64_t
scope
,
secondary_type
&
secondary
,
uint64_t
&
primary
)
{
return
db_idx_find_secondary
(
code
,
scope
,
IndexName
,
secondary
,
primary
);
}
int
lower_bound
(
uint64_t
code
,
uint64_t
scope
,
secondary_type
&
secondary
,
uint64_t
&
primary
)
const
{
static
int
lower_bound
(
uint64_t
code
,
uint64_t
scope
,
secondary_type
&
secondary
,
uint64_t
&
primary
)
{
return
db_idx_lowerbound
(
code
,
scope
,
IndexName
,
secondary
,
primary
);
}
int
upper_bound
(
uint64_t
code
,
uint64_t
scope
,
secondary_type
&
secondary
,
uint64_t
&
primary
)
const
{
static
int
upper_bound
(
uint64_t
code
,
uint64_t
scope
,
secondary_type
&
secondary
,
uint64_t
&
primary
)
{
return
db_idx_upperbound
(
code
,
scope
,
IndexName
,
secondary
,
primary
);
}
};
/*
template<int IndexNumber, uint64_t IndexName, typename T, typename Extractor>
auto make_index_by( Extractor&& l ) {
return index_by<IndexNumber, IndexName, T, Extractor>{ std::forward<Extractor>(l) };
}
*/
namespace
hana
=
boost
::
hana
;
template
<
uint64_t
TableName
,
typename
T
,
typename
...
Indicies
>
class
multi_index
{
private:
struct
item
:
public
T
{
template
<
typename
Constructor
>
...
...
@@ -154,8 +174,28 @@ class multi_index
uint64_t
_code
;
uint64_t
_scope
;
boost
::
hana
::
tuple
<
Indicies
...
>
_indicies
;
template
<
uint64_t
I
>
struct
intc
{
enum
e
{
value
=
I
};
operator
uint64_t
()
const
{
return
I
;
}
};
static
constexpr
auto
transform_indicies
(
)
{
typedef
decltype
(
hana
::
zip_shortest
(
hana
::
make_tuple
(
intc
<
0
>
(),
intc
<
1
>
(),
intc
<
2
>
(),
intc
<
3
>
(),
intc
<
4
>
(),
intc
<
5
>
()
),
hana
::
tuple
<
Indicies
...
>
()
)
)
indicies_input_type
;
return
hana
::
transform
(
indicies_input_type
(),
[
&
](
auto
&&
idx
){
typedef
typename
std
::
decay
<
decltype
(
hana
::
at_c
<
0
>
(
idx
))
>::
type
num_type
;
typedef
typename
std
::
decay
<
decltype
(
hana
::
at_c
<
1
>
(
idx
))
>::
type
idx_type
;
return
index_by
<
idx_type
::
index_name
,
T
,
typename
idx_type
::
secondary_extractor_type
,
num_type
::
e
::
value
>
();
});
}
typedef
decltype
(
multi_index
::
transform_indicies
()
)
indicies_type
;
indicies_type
_indicies
;
struct
by_primary_key
;
struct
by_primary_itr
;
...
...
@@ -167,9 +207,6 @@ class multi_index
>
>
_items_index
;
// mutable std::map<uint64_t, item*> _items; /// by_primary_key
// mutable std::map<int, item*> _items_by_itr;
const
item
&
load_object_by_primary_iterator
(
int
itr
)
const
{
const
auto
&
by_pitr
=
_items_index
.
template
get
<
by_primary_itr
>();
auto
cacheitr
=
by_pitr
.
find
(
itr
);
...
...
@@ -188,7 +225,7 @@ class multi_index
i
.
__primary_itr
=
itr
;
boost
::
hana
::
for_each
(
_indicies
,
[
&
](
auto
&
idx
)
{
i
.
__iters
[
idx
.
index_number
]
=
-
1
;
i
.
__iters
[
idx
.
number
()
]
=
-
1
;
});
});
...
...
@@ -202,18 +239,21 @@ class multi_index
public:
multi_index
(
uint64_t
code
,
uint64_t
scope
)
:
_code
(
code
),
_scope
(
scope
){}
~
multi_index
()
{
}
~
multi_index
()
{
}
template
<
typename
MultiIndexType
,
typename
IndexType
>
uint64_t
get_code
()
const
{
return
_code
;
}
uint64_t
get_scope
()
const
{
return
_scope
;
}
template
<
typename
MultiIndexType
,
typename
IndexType
,
uint64_t
Number
>
struct
index
{
private:
typedef
typename
MultiIndexType
::
item
item_type
;
typedef
typename
IndexType
::
secondary_type
secondary_key_type
;
public:
static
constexpr
uint64_t
name
()
{
return
IndexType
::
name
();
}
struct
const_iterator
{
private:
public:
friend
bool
operator
==
(
const
const_iterator
&
a
,
const
const_iterator
&
b
)
{
return
a
.
_item
==
b
.
_item
;
...
...
@@ -231,8 +271,20 @@ class multi_index
}
const_iterator
&
operator
++
()
{
if
(
!
_item
)
return
*
this
;
if
(
_item
->
__iters
[
Number
]
==
-
1
)
{
/// TODO: lookup iter for this item in this index
secondary_key_type
temp_secondary_key
;
auto
idxitr
=
secondary_iterator
<
secondary_key_type
>::
db_idx_find_primary
(
_idx
.
get_code
(),
_idx
.
get_scope
(),
_idx
.
name
(),
_item
->
primary_key
(),
temp_secondary_key
);
}
uint64_t
next_pk
=
0
;
auto
next_itr
=
secondary_iterator
<
secondary_key_type
>::
db_idx_next
(
_item
->
__iters
[
IndexType
::
index_n
umber
],
&
next_pk
);
auto
next_itr
=
secondary_iterator
<
secondary_key_type
>::
db_idx_next
(
_item
->
__iters
[
N
umber
],
&
next_pk
);
if
(
next_itr
==
-
1
)
{
_item
=
nullptr
;
return
*
this
;
...
...
@@ -240,15 +292,18 @@ class multi_index
const
T
&
obj
=
*
_idx
.
_multidx
.
find
(
next_pk
);
auto
&
mi
=
const_cast
<
item_type
&>
(
static_cast
<
const
item_type
&>
(
obj
)
);
mi
.
__iters
[
IndexType
::
index_n
umber
]
=
next_itr
;
mi
.
__iters
[
N
umber
]
=
next_itr
;
_item
=
&
mi
;
return
*
this
;
}
const_iterator
&
operator
--
()
{
if
(
!
_item
)
{
}
uint64_t
prev_pk
=
0
;
auto
prev_itr
=
secondary_iterator
<
secondary_key_type
>::
db_idx_prev
(
_item
->
__iters
[
IndexType
::
index_n
umber
],
&
prev_pk
);
auto
prev_itr
=
secondary_iterator
<
secondary_key_type
>::
db_idx_prev
(
_item
->
__iters
[
N
umber
],
&
prev_pk
);
if
(
prev_itr
==
-
1
)
{
_item
=
nullptr
;
return
*
this
;
...
...
@@ -256,7 +311,7 @@ class multi_index
const
T
&
obj
=
*
_idx
.
_multidx
.
find
(
prev_pk
);
auto
&
mi
=
const_cast
<
item_type
&>
(
static_cast
<
const
item_type
&>
(
obj
)
);
mi
.
__iters
[
IndexType
::
index_n
umber
]
=
prev_itr
;
mi
.
__iters
[
N
umber
]
=
prev_itr
;
_item
=
&
mi
;
return
*
this
;
...
...
@@ -281,24 +336,25 @@ class multi_index
}
const_iterator
lower_bound
(
typename
IndexType
::
secondary_type
&
secondary
)
{
uint64_t
primary
=
0
;
auto
itr
=
_idx
.
lower_bound
(
_multidx
.
_code
,
_multidx
.
_scope
,
secondary
,
primary
);
auto
itr
=
IndexType
::
lower_bound
(
_multidx
.
_code
,
_multidx
.
_scope
,
secondary
,
primary
);
if
(
itr
==
-
1
)
return
end
();
const
T
&
obj
=
*
_multidx
.
find
(
primary
);
auto
&
mi
=
const_cast
<
item_type
&>
(
static_cast
<
const
item_type
&>
(
obj
)
);
mi
.
__iters
[
IndexType
::
index_n
umber
]
=
itr
;
mi
.
__iters
[
N
umber
]
=
itr
;
return
const_iterator
(
*
this
,
&
mi
);
}
uint64_t
get_code
()
const
{
return
_multidx
.
get_code
();
}
uint64_t
get_scope
()
const
{
return
_multidx
.
get_scope
();
}
private:
friend
class
multi_index
;
index
(
const
MultiIndexType
&
midx
,
const
IndexType
&
idx
)
:
_multidx
(
midx
)
,
_idx
(
idx
)
{}
index
(
const
MultiIndexType
&
midx
)
//
, const IndexType& idx )
:
_multidx
(
midx
){}
const
MultiIndexType
_multidx
;
const
IndexType
&
_idx
;
};
...
...
@@ -323,14 +379,20 @@ class multi_index
//eosio_assert( _item, "null ptr" );
uint64_t
pk
;
auto
next_itr
=
db_next_i64
(
_item
->
__primary_itr
,
&
pk
);
_item
=
&
_multidx
.
load_object_by_primary_iterator
(
next_itr
);
if
(
next_itr
==
-
1
)
_item
=
nullptr
;
else
_item
=
&
_multidx
.
load_object_by_primary_iterator
(
next_itr
);
return
*
this
;
}
const_iterator
&
operator
--
()
{
//eosio_assert( _item, "null ptr" );
uint64_t
pk
;
auto
next_itr
=
db_previous_i64
(
_item
->
__primary_itr
,
&
pk
);
_item
=
&
_multidx
.
load_object_by_primary_iterator
(
next_itr
);
if
(
next_itr
==
-
1
)
_item
=
nullptr
;
else
_item
=
&
_multidx
.
load_object_by_primary_iterator
(
next_itr
);
return
*
this
;
}
...
...
@@ -372,9 +434,21 @@ class multi_index
}
template
<
uint64_t
IndexName
>
auto
get_index
()
const
{
const
auto
&
idx
=
boost
::
hana
::
find_if
(
_indicies
,
[](
auto
x
){
return
std
::
integral_constant
<
bool
,(
decltype
(
x
)
::
index_name
==
IndexName
)
>
();
}
).
value
();
return
index
<
multi_index
,
typename
std
::
decay
<
decltype
(
idx
)
>::
type
>
(
*
this
,
idx
);
auto
idx
=
boost
::
hana
::
find_if
(
_indicies
,
[](
auto
&&
in
){
/*
auto& x = hana::at_c<1>(idxp);
return std::integral_constant<bool,(std::decay<decltype(x)>::type::index_name == IndexName)>();
*/
return
std
::
integral_constant
<
bool
,
std
::
decay
<
decltype
(
in
)
>::
type
::
index_name
==
IndexName
>
();
}
).
value
();
return
index
<
multi_index
,
decltype
(
idx
),
idx
.
number
()
>
(
*
this
);
/*
typedef typename std::decay<decltype(hana::at_c<0>(idx))>::type num_type;
return index<multi_index, typename std::decay<decltype(hana::at_c<1>(idx))>::type, num_type::value >( *this, hana::at_c<1>(idx) );
*/
}
template
<
typename
Lambda
>
...
...
@@ -391,7 +465,7 @@ class multi_index
i
.
__primary_itr
=
db_store_i64
(
_scope
,
TableName
,
payer
,
pk
,
tmp
,
sizeof
(
tmp
)
);
boost
::
hana
::
for_each
(
_indicies
,
[
&
](
auto
&
idx
)
{
i
.
__iters
[
idx
.
index_number
]
=
idx
.
store
(
_scope
,
payer
,
obj
);
i
.
__iters
[
idx
.
number
()
]
=
idx
.
store
(
_scope
,
payer
,
obj
);
});
});
...
...
@@ -406,7 +480,7 @@ class multi_index
// eosio_assert( &objitem.__idx == this, "invalid object" );
auto
secondary_keys
=
boost
::
hana
::
transform
(
_indicies
,
[
&
](
auto
&
idx
)
{
auto
secondary_keys
=
boost
::
hana
::
transform
(
_indicies
,
[
&
](
auto
&
&
idx
)
{
return
idx
.
extract_secondary_key
(
obj
);
});
...
...
@@ -421,18 +495,25 @@ class multi_index
db_update_i64
(
objitem
.
__primary_itr
,
payer
,
tmp
,
sizeof
(
tmp
)
);
boost
::
hana
::
for_each
(
_indicies
,
[
&
](
auto
&
idx
)
{
typedef
typename
std
::
decay
<
decltype
(
idx
)
>::
type
index_type
;
auto
secondary
=
idx
.
extract_secondary_key
(
mutableobj
);
if
(
boost
::
hana
::
at_c
<
std
::
decay
<
decltype
(
idx
)
>::
type
::
index_number
>
(
secondary_keys
)
!=
secondary
)
{
auto
indexitr
=
mutableitem
.
__iters
[
idx
.
index_number
];
if
(
hana
::
at_c
<
index_
type
::
index_number
>
(
secondary_keys
)
!=
secondary
)
{
auto
indexitr
=
mutableitem
.
__iters
[
idx
.
number
()
];
if
(
indexitr
==
-
1
)
indexitr
=
mutableitem
.
__iters
[
idx
.
index_number
]
=
idx
.
find_primary
(
_code
,
_scope
,
pk
,
secondary
);
indexitr
=
mutableitem
.
__iters
[
idx
.
number
()
]
=
idx
.
find_primary
(
_code
,
_scope
,
pk
,
secondary
);
idx
.
update
(
indexitr
,
payer
,
secondary
);
}
});
}
const
T
&
get
(
uint64_t
primary
)
const
{
auto
result
=
find
(
primary
);
eosio_assert
(
result
!=
nullptr
,
"unable to find key"
);
return
*
result
;
}
const
T
*
find
(
uint64_t
primary
)
const
{
auto
cacheitr
=
_items_index
.
find
(
primary
);
if
(
cacheitr
!=
_items_index
.
end
()
)
...
...
@@ -453,7 +534,7 @@ class multi_index
db_remove_i64
(
objitem
.
__primary_itr
);
boost
::
hana
::
for_each
(
_indicies
,
[
&
](
auto
&
idx
)
{
auto
i
=
objitem
.
__iters
[
idx
.
index_number
];
auto
i
=
objitem
.
__iters
[
idx
.
number
()
];
if
(
i
==
-
1
)
{
typename
std
::
decay
<
decltype
(
idx
)
>::
type
::
secondary_type
second
;
i
=
idx
.
find_primary
(
_code
,
_scope
,
objitem
.
primary_key
(),
second
);
...
...
contracts/eosiolib/multiindex.hpp
已删除
100644 → 0
浏览文件 @
fed461e2
extern
"C"
{
/**
*
* @return an ID that serves as an iterator to the object stored, -1 for error
*/
int
db_store_i64
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
payer
,
uint64_t
id
,
char
*
buffer
,
size_t
buffer_size
);
int
db_update_i64
(
int
iterator
,
char
*
buffer
,
size_t
buffer_size
);
/**
* max_buffer_size should start out with the space reserved for buffer, but is set to the actual size of buffer
*
* if max_buffer_size is greater than actual buffer size, then buffer will be filled with contents, otherwise not
*
* @return an ID that serves as an iterator to the object stored, -1 for error/not found
*/
int
db_find_i64
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
table
,
uint64_t
id
,
char
*
buffer
,
size_t
*
max_buffer_size
);
int
db_lower_bound_i64
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
table
,
uint64_t
id
,
char
*
buffer
,
size_t
*
max_buffer_size
);
int
db_upper_bound_i64
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
table
,
uint64_t
id
,
char
*
buffer
,
size_t
*
max_buffer_size
);
/** return an iterator to the next item after @param iterator and optionally fetch data if buffer is not null */
int
db_next
(
int
iterator
,
uint64_t
*
id
,
char
*
buffer
,
size_t
*
max_buffer_size
);
/** return an iterator to the prev item after @param iterator and optionally fetch data if buffer is not null */
int
db_prev
(
int
iterator
,
uint64_t
*
id
,
char
*
buffer
,
size_t
*
max_buffer_size
);
/**
* @return the number of elements in the table stored at code/scope/table
*/
int
db_count_i64
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
table
);
void
db_remove_i64
(
int
iterator
);
int
db_find_primary_index64
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
primary
,
uint64_t
*
secondary
);
int
db_find_secondary_index64
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
*
primary
,
uint64_t
secondary
);
int
db_upper_bound_primary_index64
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
primary
,
uint64_t
*
secondary
);
int
db_upper_bound_secondary_index64
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
*
primary
,
uint64_t
secondary
);
int
db_lower_bound_primary_index64
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
primary
,
uint64_t
*
secondary
);
int
db_lower_bound_secondary_index64
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
*
primary
,
uint64_t
secondary
);
int
db_update_index64
(
int
iterator
,
uint64_t
payer
,
uint64_t
id
,
uint64_t
indexvalue
);
int
db_remove_index64
(
int
iterator
);
int
db_next_index64
(
int
iterator
,
uint64_t
*
value
);
int
db_prev_index64
(
int
iterator
,
uint64_t
*
value
);
int
db_find_primary_index128
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
primary
,
uint128_t
*
secondary
);
int
db_find_secondary_index128
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
*
primary
,
const
uint128_t
*
secondary
);
int
db_upper_bound_primary_index128
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
primary
,
uint128_t
*
secondary
);
int
db_upper_bound_secondary_index128
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
*
primary
,
const
uint128_t
*
secondary
);
int
db_lower_bound_primary_index128
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
primary
,
uint128_t
*
secondary
);
int
db_lower_bound_secondary_index128
(
uint64_t
scope
,
uint64_t
table
,
uint64_t
*
primary
,
const
uint128_t
*
secondary
);
int
db_update_index128
(
int
iterator
,
uint64_t
payer
,
uint64_t
id
,
const
uint128_t
*
secondary
);
int
db_remove_index128
(
int
iterator
);
int
db_next_index128
(
int
iterator
,
uint128_t
*
value
);
int
db_prev_index128
(
int
iterator
,
uint128_t
*
value
);
}
/// extern "C"
namespace
eosio
{
namespace
detail
{
template
<
typename
T
>
struct
id_for
{};
}
struct
limit_order
{
uint64_t
id
;
uint128_t
price
;
uint64_t
expiration
;
account_name
owner
;
uint128_t
by_owner_id
()
const
{
uint128_t
result
(
owner
);
result
<<
64
;
result
|=
id
;
return
result
;
}
uint128_t
by_price
()
const
{
return
price
;
}
uint64_t
by_expiration
()
const
{
return
expiration
;
}
EOSLIB_SERIALIZE
(
(
id
)(
price
)(
expiration
)(
owner
)
)
};
template
<
uint64_t
Number
,
uint64_t
IndexName
,
typename
Extractor
>
class
index_by
{
typedef
std
::
decay
<
decltype
(
ex
(
*
((
const
T
*
)(
nullptr
))
)
)
>::
type
value_type
static
const
uint64_t
index_name
=
IndexName
;
static
const
uint64_t
number
=
Number
;
Extractor
ex
;
};
template
<
typename
T
,
typename
IndexTuple
>
class
multi_index
{
auto
indicies
=
make_tuple
(
make_index
(
N
(
byorderid
),
[](
const
T
&
obj
){
return
obj
.
id
;
}),
make_index
(
N
(
byexpiration
),
[](
const
T
&
obj
)
{
return
obj
.
by_expiration
();
}
)
make_index
(
N
(
byprice
),
[](
const
T
&
obj
)
{
return
obj
.
by_price
();
}
)
);
mutable
map
<
uint64_t
,
item
*>
_items
;
public:
template
<
uint64_t
IndexName
,
typename
Key
>
const
T
*
find
(
const
Key
&
k
)
const
{
}
template
<
typename
Existing
>
auto
get_keys
(
const
T
&
obj
)
{
return
get_keys
<
1
>
(
std
::
make_tuple
(
}
template
<
int
I
,
typename
Existing
,
std
::
enable_if
<
I
==
std
::
tuple_size
(
IndexTuple
)
-
1
>
=
0
>
auto
get_keys
(
Existing
&&
e
,
const
T
&
obj
)
{
return
std
::
tuple_cat
(
std
::
forward
<
Existing
>
(
e
),
std
::
get
<
I
>
(
indicies
).
extract
(
obj
)
);
}
template
<
int
I
,
typename
Existing
,
std
::
enable_if
<
(
I
<
std
::
tuple_size
(
IndexTuple
)
-
1
)
>
=
0
>
auto
get_keys
(
Existing
&&
e
,
const
T
&
obj
)
{
return
get_keys
<
I
+
1
>
(
std
::
tuple_cat
(
std
::
forward
<
Existing
>
(
e
),
std
::
get
<
I
>
(
indicies
).
extract
(
obj
)
),
obj
);
}
template
<
typename
Lambda
>
const
T
&
create
(
Lambda
&&
constructor
,
uint64_t
payer
)
{
auto
i
=
new
item
(
*
this
);
constructor
(
static_cast
<
T
&>
(
*
i
)
);
const
T
&
obj
=
static_cast
<
const
T
&>
(
*
i
);
char
tmp
[
pack_size
(
obj
)
];
datastream
<
char
*>
ds
(
tmp
,
sizeof
(
tmp
)
);
pack
(
ds
,
obj
);
auto
pk
=
obj
.
primary_key
();
i
->
__itrs
[
0
]
=
db_store_i64
(
_code
,
_scope
,
_tables
[
0
],
payer
,
pk
,
tmp
,
sizeof
(
tmp
)
);
for_each
(
indicies
,
[
&
](
auto
&
idx
)
{
i
->
__itrs
[
idx
.
number
]
=
idx
.
store
(
_code
,
_scope
,
idx
.
index_name
,
payer
,
pk
,
idx
.
extract
(
obj
)
);
});
items
[
pk
]
=
i
;
return
obj
;
}
template
<
typename
Lambda
>
void
update
(
const
T
&
obj
,
uint64_t
payer
,
Lambda
&&
updater
)
{
T
&
mobj
=
const_cast
<
T
&>
(
obj
);
item
&
i
=
static_cast
<
item
&>
(
mobj
);
auto
pk
=
mobj
.
primary_key
();
eosio_assert
(
&
i
.
__mutli_idx
==
this
);
auto
old_idx
=
std
::
make_tuple
(
obj
.
primary_key
(),
obj
.
expiration
(),
obj
.
by_owner_id
(),
obj
.
by_price
()
);
updater
(
mobj
);
char
tmp
[
pack_size
(
mobj
)
];
datastream
<
char
*>
ds
(
tmp
,
sizeof
(
tmp
)
);
pack
(
ds
,
mobj
);
db_update_i64
(
i
.
__itrs
[
0
],
payer
,
tmp
,
sizeof
(
tmp
)
);
auto
new_idx
=
std
::
make_tuple
(
obj
.
primary_key
(),
obj
.
expiration
(),
obj
.
by_owner_id
(),
obj
.
by_price
()
);
if
(
std
::
get
<
1
>
(
old_idx
)
!=
std
::
get
<
1
>
(
new_idx
)
)
{
if
(
i
.
__itrs
[
1
]
==
-
2
)
i
.
__itrs
[
1
]
=
db_idx64_find_primary
(
pk
);
db_idx64_update
(
i
.
__itrs
[
1
],
payer
,
std
::
get
<
1
>
(
new_idx
)
);
}
if
(
std
::
get
<
2
>
(
old_idx
)
!=
std
::
get
<
2
>
(
new_idx
)
)
{
if
(
i
.
__itrs
[
2
]
==
-
2
)
i
.
__itrs
[
2
]
=
db_idx64_find_primary
(
pk
);
db_idx64_update
(
i
.
__itrs
[
2
],
payer
,
std
::
get
<
2
>
(
new_idx
)
);
}
if
(
std
::
get
<
3
>
(
old_idx
)
!=
std
::
get
<
3
>
(
new_idx
)
)
{
if
(
i
.
__itrs
[
3
]
==
-
2
)
i
.
__itrs
[
3
]
=
db_idx64_find_primary
(
pk
);
db_idx64_update
(
i
.
__itrs
[
3
],
payer
,
std
::
get
<
3
>
(
new_idx
)
);
}
}
private:
struct
item
:
public
T
{
item
(
multi_index
&
o
)
:
__mutli_idx
(
o
)
{
}
multi_index
&
__multi_idx
;
int
__itrs
[
3
];
};
};
/*
multi_index< N(limitorders), limit_order,
index< N(ownerid), &limit_order::by_owner_id >,
index< N(byprice), &limit_order::by_price >,
index< N(byexpire), &limit_order::by_expiration>
> orderbook;
*/
/*
template
<
uint64_t
Code
,
uint64_t
TableName
,
typename
ObjectType
>
class
multi_index
{
public:
struct
cache_object
:
public
ObjectType
{
int
primary_itr
;
};
const
cache_object
*
find
(
uint64_t
primary
)
{
auto
itr
=
_cache
.
find
(
primary
);
if
(
itr
!=
cache
.
end
()
)
return
itr
->
second
;
db_find_i64
(
Code
,
_scope
,
TableName
,
primary
);
}
private:
std
::
map
<
uint64_t
,
cache_object
*>
_cache
;
};
auto
order
=
orderbook
.
begin
();
auto
end
=
orderbook
.
end
();
while
(
order
!=
end
)
{
auto
cur
=
order
;
++
order
;
orderbook
.
remove
(
cur
);
}
const
limit_order
&
order
=
*
orderbook
.
begin
();
/// Options:
// 1. maintain a wasm-side cache of all dereferenced objects
// a. keeps pointers valid
// b. minimizes temporary copies
// c. eliminates redundant deserialization losses
// d. will utilize more heap memory than necessary, potentially hitting sbrk
//
// 2. keep API light and return a copy
template
<
typename
ObjectType
,
typename
SecondaryKeyType
>
class
index
{
public:
index
(
uint64_t
code
,
uint64_t
scope
,
uint64_t
table
);
struct
iterator
{
iterator
(
index
&
idx
,
int
itr
)
:
_idx
(
idx
),
_itr
(
itr
){
if
(
itr
>=
0
)
db_index
<
SecondaryKeyType
>::
get
(
itr
,
_primary
,
_secondary
);
}
uint64_t
primary
()
const
{
return
_primary
;
}
const
SecondaryKeyType
&
secondary
()
const
{
return
_secondary
;
}
private:
uint64_t
_primary
;
SecondaryKeyType
_secondary
;
index
&
_idx
;
int
_itr
;
};
iterator
lower_bound
(
const
SecondaryKeyType
&
lb
)
{
return
iterator
(
db_index
<
SecondaryKeyType
>::
secondary_lower_bound
(
_code
,
_scope
,
_table
,
lb
)
);
}
private:
uint64_t
_code
;
uint64_t
_scope
;
uint64_t
_table
;
};
template
<
typename
T
,
typename
Indices
>
class
multi_index
{
public:
struct
iterator
{
private:
int
primary_itr
;
};
multi_index
(
code_name
code
,
scope_name
scope
,
table_name
table
)
:
_code
(
code
),
_scope
(
scope
),
_table
(
table
){}
void
insert
(
const
T
&
obj
,
account_name
payer
)
{
uint64_t
id
=
id_for
<
T
>::
get
(
obj
);
auto
buf
=
pack
(
obj
);
store_i64
(
_scope
,
_table
,
payer
,
id
,
buf
.
data
(),
buf
.
size
()
);
Indices
::
insert
(
_code
,
_scope
,
_table
,
payer
,
obj
);
}
template
<
typename
Constructor
>
void
emplace
(
Constructor
&&
c
)
{
T
tmp
;
id_for
<
T
>::
get
(
tmp
)
=
allocate_id
();
c
(
tmp
);
insert
(
tmp
);
}
template
<
typename
Lambda
>
void
modify
(
const
T
&
obj
,
account_name
payer
,
Lambda
&&
update
)
{
update
(
tmp
);
uint64_t
id
=
id_for
<
T
>::
get
(
value
);
auto
buf
=
pack
(
tmp
);
store_i64
(
_code
,
_scope
,
_table
,
payer
,
id
,
buf
.
data
(),
buf
.
size
()
);
Indices
::
update
(
_code
,
_scope
,
_table
,
payer
,
obj
);
}
private:
};
}
// namespace eosio
contracts/multi_index_test/multi_index_test.cpp
浏览文件 @
e3dc3082
...
...
@@ -20,8 +20,8 @@ extern "C" {
/// The apply method implements the dispatch of events to this contract
void
apply
(
uint64_t
code
,
uint64_t
action
)
{
eosio
::
multi_index
<
N
(
orders
),
limit_order
,
index
_by
<
0
,
N
(
byexp
),
limit_order
,
const_mem_fun
<
limit_order
,
uint64_t
,
&
limit_order
::
get_expiration
>
>
,
index
_by
<
1
,
N
(
byprice
),
limit_order
,
const_mem_fun
<
limit_order
,
uint128_t
,
&
limit_order
::
get_price
>
>
index
ed_by
<
N
(
byexp
)
,
const_mem_fun
<
limit_order
,
uint64_t
,
&
limit_order
::
get_expiration
>
>
,
index
ed_by
<
N
(
byprice
)
,
const_mem_fun
<
limit_order
,
uint128_t
,
&
limit_order
::
get_price
>
>
>
orders
(
N
(
exchange
),
N
(
exchange
)
);
auto
payer
=
code
;
...
...
eosio_build.sh
浏览文件 @
e3dc3082
...
...
@@ -91,8 +91,8 @@
fi
if
[
$ARCH
==
"Darwin"
]
;
then
OPENSSL_ROOT_DIR
=
/usr/local/opt/openssl
@1.1
OPENSSL_LIBRARIES
=
/usr/local/opt/openssl
@1.1
/lib
OPENSSL_ROOT_DIR
=
/usr/local/opt/openssl
OPENSSL_LIBRARIES
=
/usr/local/opt/openssl/lib
BINARYEN_BIN
=
/usr/local/binaryen/bin/
WASM_LLVM_CONFIG
=
/usr/local/wasm/bin/llvm-config
CXX_COMPILER
=
clang++
...
...
appbase
@
a0cf75ad
比较
ef2b0c8d
...
a0cf75ad
Subproject commit
ef2b0c8d64f770d80ce537ec04d0de4bdc4d3585
Subproject commit
a0cf75ad7c39137ebf03b0f3b0b4e5b7f731296b
libraries/chain/apply_context.cpp
浏览文件 @
e3dc3082
...
...
@@ -116,6 +116,7 @@ bool apply_context::is_account( const account_name& account )const {
void
apply_context
::
require_authorization
(
const
account_name
&
account
)
const
{
for
(
const
auto
&
auth
:
act
.
authorization
)
if
(
auth
.
actor
==
account
)
return
;
wdump
((
act
));
EOS_ASSERT
(
false
,
tx_missing_auth
,
"missing authority of ${account}"
,
(
"account"
,
account
));
}
void
apply_context
::
require_authorization
(
const
account_name
&
account
,
...
...
libraries/chain/include/eosio/chain/account_object.hpp
浏览文件 @
e3dc3082
...
...
@@ -36,6 +36,13 @@ namespace eosio { namespace chain {
fc
::
datastream
<
char
*>
ds
(
abi
.
data
(),
abi
.
size
()
);
fc
::
raw
::
pack
(
ds
,
a
);
}
eosio
::
chain
::
contracts
::
abi_def
get_abi
()
const
{
eosio
::
chain
::
contracts
::
abi_def
a
;
fc
::
datastream
<
const
char
*>
ds
(
abi
.
data
(),
abi
.
size
()
);
fc
::
raw
::
unpack
(
ds
,
a
);
return
a
;
}
};
using
account_id_type
=
account_object
::
id_type
;
...
...
chainbase
@
d48ebabf
比较
664fdd9e
...
d48ebabf
Subproject commit
664fdd9e79263a894794f96959612ec2d1d013d0
Subproject commit
d48ebabf56b4115753fcabb7648a0ffcf3b0f5e9
libraries/testing/include/eosio/testing/tester.hpp
浏览文件 @
e3dc3082
...
...
@@ -27,7 +27,11 @@ namespace eosio { namespace testing {
transaction_trace
push_transaction
(
packed_transaction
&
trx
);
transaction_trace
push_transaction
(
signed_transaction
&
trx
);
action_result
push_action
(
action
&&
cert_act
,
uint64_t
authorizer
);
action_result
push_action
(
action
&&
cert_act
,
uint64_t
authorizer
);
transaction_trace
push_action
(
const
account_name
&
code
,
const
action_name
&
act
,
const
account_name
&
signer
,
const
variant_object
&
data
);
void
set_tapos
(
signed_transaction
&
trx
)
const
;
void
create_accounts
(
vector
<
account_name
>
names
,
bool
multisig
=
false
)
{
...
...
libraries/testing/tester.cpp
浏览文件 @
e3dc3082
...
...
@@ -133,6 +133,32 @@ namespace eosio { namespace testing {
return
success
();
}
transaction_trace
base_tester
::
push_action
(
const
account_name
&
code
,
const
action_name
&
acttype
,
const
account_name
&
actor
,
const
variant_object
&
data
)
{
try
{
chain
::
contracts
::
abi_serializer
abis
(
control
->
get_database
().
get
<
account_object
,
by_name
>
(
code
).
get_abi
()
);
string
action_type_name
=
abis
.
get_action_type
(
acttype
);
action
act
;
act
.
account
=
code
;
act
.
name
=
acttype
;
act
.
authorization
=
vector
<
permission_level
>
{{
actor
,
config
::
active_name
}};
act
.
data
=
abis
.
variant_to_binary
(
action_type_name
,
data
);
wdump
((
act
));
signed_transaction
trx
;
trx
.
actions
.
emplace_back
(
std
::
move
(
act
));
set_tapos
(
trx
);
trx
.
sign
(
get_private_key
(
actor
,
"active"
),
chain_id_type
());
wdump
((
get_public_key
(
actor
,
"active"
)));;
return
push_transaction
(
trx
);
}
FC_CAPTURE_AND_RETHROW
(
(
code
)(
acttype
)(
actor
)
)
}
transaction_trace
base_tester
::
push_reqauth
(
account_name
from
,
const
vector
<
permission_level
>&
auths
,
const
vector
<
private_key_type
>&
keys
)
{
variant
pretty_trx
=
fc
::
mutable_variant_object
()
(
"actions"
,
fc
::
variants
({
...
...
@@ -367,6 +393,4 @@ namespace eosio { namespace testing {
set_abi
(
config
::
system_account_name
,
test_system_abi
);
}
}
}
/// eosio::test
scripts/eosio_build_darwin.sh
浏览文件 @
e3dc3082
...
...
@@ -20,20 +20,20 @@
printf
"
\t
Disk space available:
${
DISK_AVAIL
}
G
\n\n
"
if
[
$MEM_GIG
-lt
8
]
;
then
printf
"
\t
Your system must have 8 or more Gigabytes of physical memory installed.
\n
"
printf
"
\t
Exiting now.
\n
"
echo
"Your system must have 8 or more Gigabytes of physical memory installed.
"
echo
"Exiting now.
"
exit
1
fi
if
[
$OS_MIN
-lt
12
]
;
then
printf
"
\t
You must be running Mac OS 10.12.x or higher to install EOSIO.
\n
"
printf
"
\t
Exiting now.
\n
"
echo
"You must be running Mac OS 10.12.x or higher to install EOSIO.
"
echo
"Exiting now.
"
exit
1
fi
if
[
$DISK_AVAIL
-lt
100
]
;
then
printf
"
\t
You must have at least 100GB of available storage to install EOSIO.
\n
"
printf
"
\t
Exiting now.
\n
"
echo
"You must have at least 100GB of available storage to install EOSIO.
"
echo
"Exiting now.
"
exit
1
fi
...
...
tests/wasm_tests/eosio.system_tests.cpp
0 → 100644
浏览文件 @
e3dc3082
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio/chain_plugin/chain_plugin.hpp>
#include <eosio.system/eosio.system.wast.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <Runtime/Runtime.h>
#include <fc/variant_object.hpp>
using
namespace
eosio
::
testing
;
using
mvo
=
fc
::
mutable_variant_object
;
BOOST_AUTO_TEST_SUITE
(
eosio_system_tests
)
BOOST_FIXTURE_TEST_CASE
(
eosio_system_load
,
tester
)
try
{
produce_block
();
edump
((
name
(
config
::
system_account_name
)));
set_code
(
config
::
system_account_name
,
eosio_system_wast
);
set_abi
(
config
::
system_account_name
,
eosio_system_abi
);
produce_block
();
create_accounts
(
{
N
(
dan
),
N
(
brendan
)}
);
push_action
(
N
(
eosio
),
N
(
issue
),
N
(
eosio
),
mvo
()
(
"to"
,
"eosio"
)
(
"quantity"
,
"1000000.0000 EOS"
)
);
push_action
(
N
(
eosio
),
N
(
transfer
),
N
(
eosio
),
mvo
()
(
"from"
,
"eosio"
)
(
"to"
,
"dan"
)
(
"quantity"
,
"100.0000 EOS"
)
(
"memo"
,
"hi"
)
);
push_action
(
N
(
eosio
),
N
(
transfer
),
N
(
dan
),
mvo
()
(
"from"
,
"dan"
)
(
"to"
,
"brendan"
)
(
"quantity"
,
"50.0000 EOS"
)
(
"memo"
,
"hi"
)
);
wlog
(
"reg producer"
);
auto
regtrace
=
push_action
(
N
(
eosio
),
N
(
regproducer
),
N
(
dan
),
mvo
()
(
"producer"
,
"dan"
)
(
"producer_key"
,
""
)
);
wdump
((
regtrace
));
produce_block
();
wlog
(
"transfer"
);
push_action
(
N
(
eosio
),
N
(
transfer
),
N
(
dan
),
mvo
()
(
"from"
,
"dan"
)
(
"to"
,
"brendan"
)
(
"quantity"
,
"5.0000 EOS"
)
(
"memo"
,
"hi"
)
);
/*
permission_level_weight plw{ permission_level{N(eosio),N(active)}, 1};;
set_authority( N(dan), N(active),
authority( 1,
vector<key_weight>({ {get_public_key(N(dan),"active"),1 } }),
vector<permission_level_weight>({plw}) ) );
*/
wlog
(
"stake vote"
);
auto
trace
=
push_action
(
N
(
eosio
),
N
(
stakevote
),
N
(
dan
),
mvo
()
(
"voter"
,
"dan"
)
(
"amount"
,
"5.0000 EOS"
)
);
wdump
((
trace
));
/*
produce_blocks(2);
create_accounts( {N(multitest)} );
produce_blocks(2);
set_code( N(multitest), eosio_system_test_wast );
set_abi( N(multitest), eosio_system_test_abi );
produce_blocks(1);
*/
}
FC_LOG_AND_RETHROW
()
BOOST_AUTO_TEST_SUITE_END
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录