Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
98faba45
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,发现更多精彩内容 >>
提交
98faba45
编写于
2月 22, 2018
作者:
A
Anton Perkov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
producers register desired system parameters, unstaking requests, proxy voting #1455
上级
5a3ff040
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
257 addition
and
82 deletion
+257
-82
contracts/eosio.system/eosio.system.hpp
contracts/eosio.system/eosio.system.hpp
+2
-2
contracts/eosio.system/producers_election.hpp
contracts/eosio.system/producers_election.hpp
+254
-80
contracts/eosiolib/multi_index.hpp
contracts/eosiolib/multi_index.hpp
+1
-0
未找到文件。
contracts/eosio.system/eosio.system.hpp
浏览文件 @
98faba45
...
...
@@ -34,8 +34,8 @@ namespace eosiosystem {
static
void
apply
(
account_name
code
,
action_name
act
)
{
if
(
!
eosio
::
dispatch
<
contract
,
typename
delegate_bandwith
<
SystemAccount
>::
delegatebw
,
typename
delegate_bandwith
<
SystemAccount
>::
undelegatebw
,
typename
producers_election
<
SystemAccount
>::
regproxy
,
typename
producers_election
<
SystemAccount
>::
regproducer
,
typename
producers_election
<
SystemAccount
>::
reg
ister_
proxy
,
typename
producers_election
<
SystemAccount
>::
reg
ister_
producer
,
typename
producers_election
<
SystemAccount
>::
voteproducer
,
typename
producers_election
<
SystemAccount
>::
stakevote
,
nonce
>
(
code
,
act
)
)
{
...
...
contracts/eosio.system/producers_election.hpp
浏览文件 @
98faba45
...
...
@@ -11,14 +11,17 @@
#include <eosiolib/datastream.hpp>
#include <eosiolib/serialize.hpp>
#include <eosiolib/multi_index.hpp>
#include <eosiolib/transaction.hpp>
#include <map>
namespace
eosiosystem
{
using
eosio
::
indexed_by
;
using
eosio
::
const_mem_fun
;
using
eosio
::
member
;
using
eosio
::
bytes
;
using
eosio
::
print
;
using
eosio
::
transaction
;
using
std
::
map
;
using
std
::
pair
;
...
...
@@ -29,79 +32,151 @@ namespace eosiosystem {
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
;
uint64_t
padding
=
0
;
uint128_t
total_votes
;
static
constexpr
uint32_t
max_unstake_requests
=
10
;
static
constexpr
uint32_t
voting_stake_freez_time
=
180
*
24
*
3600
;
uint64_t
primary_key
()
const
{
return
owner
;
}
uint128_t
by_votes
()
const
{
return
total_votes
;
}
struct
producer_preferences
{
uint32_t
max_blk_size
;
uint32_t
target_blk_size
;
EOSLIB_SERIALIZE
(
producer_votes
,
(
owner
)(
total_votes
)
)
uint64_t
max_storage_size
;
uint64_t
rescource_window_size
;
uint32_t
max_blk_cpu
;
uint32_t
target_blk_cpu
;
uint16_t
inflation_rate
;
// inflation in percents * 10000;
uint32_t
max_trx_lifetime
;
uint16_t
max_transaction_recursion
;
producer_preferences
()
{
bzero
(
this
,
sizeof
(
*
this
));
}
EOSLIB_SERIALIZE
(
producer_preferences
,
(
max_blk_size
)(
target_blk_size
)(
max_storage_size
)(
rescource_window_size
)
(
max_blk_cpu
)(
target_blk_cpu
)(
inflation_rate
)(
max_trx_lifetime
)(
max_transaction_recursion
)
)
};
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
producer_info
{
account_name
owner
;
uint64_t
padding
=
0
;
uint128_t
total_votes
;
producer_preferences
prefs
;
uint64_t
primary_key
()
const
{
return
owner
;
}
uint128_t
by_votes
()
const
{
return
total_votes
;
}
EOSLIB_SERIALIZE
(
producer_info
,
(
owner
)(
total_votes
)(
prefs
)
)
};
typedef
eosio
::
multi_index
<
N
(
producervote
),
producer_info
,
indexed_by
<
N
(
prototalvote
),
const_mem_fun
<
producer_info
,
uint128_t
,
&
producer_info
::
by_votes
>
>
>
producer_info_index_type
;
struct
account_votes
{
account_name
owner
;
account_name
proxy
;
uint32_t
last_update
;
system_token_type
staked
;
std
::
vector
<
account_name
>
producers
;
account_name
owner
;
account_name
proxy
;
uint32_t
last_update
;
uint32_t
i_am_proxy
;
uint128_t
proxied_votes
;
system_token_type
staked
;
std
::
vector
<
account_name
>
producers
;
uint64_t
primary_key
()
const
{
return
owner
;
}
uint64_t
primary_key
()
const
{
return
owner
;
}
EOSLIB_SERIALIZE
(
account_votes
,
(
owner
)(
proxy
)(
last_update
)(
staked
)(
producers
)
)
EOSLIB_SERIALIZE
(
account_votes
,
(
owner
)(
proxy
)(
last_update
)(
i_am_proxy
)(
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
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
)
)
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
;
ACTION
(
SystemAccount
,
regproducer
)
{
struct
unstake_request
{
uint64_t
id
;
account_name
account
;
system_token_type
amount
;
time
refund_time
;
uint64_t
primary_key
()
const
{
return
id
;
}
EOSLIB_SERIALIZE
(
unstake_request
,
(
id
)(
account
)(
amount
)(
refund_time
)
)
};
typedef
eosio
::
multi_index
<
N
(
unstakerequests
),
unstake_request
,
indexed_by
<
N
(
byaccount
),
member
<
unstake_request
,
account_name
,
&
unstake_request
::
account
>
>
,
indexed_by
<
N
(
bytime
),
member
<
unstake_request
,
time
,
&
unstake_request
::
refund_time
>
>
>
unstake_requests_table
;
struct
unstake_requests_count
{
account_name
account
;
uint16_t
count
;
uint64_t
primary_key
()
const
{
return
account
;
}
EOSLIB_SERIALIZE
(
unstake_requests_count
,
(
account
)(
count
)
)
};
typedef
eosio
::
multi_index
<
N
(
unstakecount
),
unstake_requests_count
>
unstake_requests_counts_table
;
ACTION
(
SystemAccount
,
register_producer
)
{
account_name
producer
;
bytes
producer_key
;
producer_preferences
prefs
;
EOSLIB_SERIALIZE
(
reg
producer
,
(
producer
)(
producer_key
)
)
EOSLIB_SERIALIZE
(
reg
ister_producer
,
(
producer
)(
producer_key
)(
prefs
)
)
};
/**
* This method will create a producer_config and producer_
votes
object for 'producer'
* This method will create a producer_config and producer_
info
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
)
{
auto
producer
=
reg
.
producer
;
require_auth
(
producer
);
static
void
on
(
const
register_producer
&
reg
)
{
require_auth
(
reg
.
producer
);
producer_
votes_index_type
vote
s
(
SystemAccount
,
SystemAccount
);
const
auto
*
existing
=
votes
.
find
(
producer
);
producer_
info_index_type
producer
s
(
SystemAccount
,
SystemAccount
);
const
auto
*
existing
=
producers
.
find
(
reg
.
producer
);
eosio_assert
(
!
existing
,
"producer already registered"
);
votes
.
emplace
(
producer
,
[
&
](
auto
&
pv
){
pv
.
owner
=
producer
;
pv
.
total_votes
=
0
;
producers
.
emplace
(
reg
.
producer
,
[
&
](
producer_info
&
info
){
info
.
owner
=
reg
.
producer
;
info
.
total_votes
=
0
;
info
.
prefs
=
reg
.
prefs
;
});
producer_config_index_type
proconfig
(
SystemAccount
,
SystemAccount
);
proconfig
.
emplace
(
producer
,
[
&
](
auto
&
pc
)
{
pc
.
owner
=
producer
;
proconfig
.
emplace
(
reg
.
producer
,
[
&
](
auto
&
pc
)
{
pc
.
owner
=
reg
.
producer
;
pc
.
packed_key
=
reg
.
producer_key
;
});
}
ACTION
(
SystemAccount
,
change_producer_preferences
)
{
account_name
producer
;
bytes
producer_key
;
producer_preferences
prefs
;
EOSLIB_SERIALIZE
(
register_producer
,
(
producer
)(
producer_key
)(
prefs
)
)
};
static
void
on
(
const
change_producer_preferences
&
change
)
{
require_auth
(
change
.
producer
);
producer_info_index_type
producers
(
SystemAccount
,
SystemAccount
);
const
auto
*
ptr
=
producers
.
find
(
change
.
producer
);
eosio_assert
(
bool
(
ptr
),
"producer is not registered"
);
producers
.
update
(
*
ptr
,
change
.
producer
,
[
&
](
producer_info
&
info
){
info
.
prefs
=
change
.
prefs
;
});
}
ACTION
(
SystemAccount
,
stakevote
)
{
account_name
voter
;
system_token_type
amount
;
...
...
@@ -110,7 +185,6 @@ namespace eosiosystem {
};
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
);
...
...
@@ -118,40 +192,94 @@ namespace eosiosystem {
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
;
acv
=
&
avotes
.
emplace
(
sv
.
voter
,
[
&
](
account_votes
&
a
)
{
a
.
owner
=
sv
.
voter
;
a
.
last_update
=
now
();
a
.
proxy
=
0
;
a
.
i_am_proxy
=
0
;
a
.
proxied_votes
=
0
;
a
.
staked
.
quantity
=
0
;
});
}
uint128_t
old_weight
=
acv
->
staked
.
quantity
;
uint128_t
new_weight
=
old_weight
+
sv
.
amount
.
quantity
;
producer_votes_index_type
votes
(
SystemAccount
,
SystemAccount
);
producer_info_index_type
producers
(
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
;
producers
.
update
(
producers
.
get
(
p
),
0
,
[
&
](
auto
&
v
)
{
v
.
total_votes
+=
sv
.
amount
.
quantity
;
});
}
avotes
.
update
(
*
acv
,
0
,
[
&
](
auto
av
)
{
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
,
unstakevote
)
{
account_name
voter
;
system_token_type
amount
;
EOSLIB_SERIALIZE
(
unstakevote
,
(
voter
)(
amount
)
)
};
static
void
on
(
const
unstakevote
&
usv
)
{
eosio_assert
(
usv
.
amount
.
quantity
>
0
,
"unstake amount should be > 0"
);
require_auth
(
usv
.
voter
);
unstake_requests_counts_table
counts
(
SystemAccount
,
SystemAccount
);
auto
ptr
=
counts
.
find
(
usv
.
voter
);
eosio_assert
(
!
ptr
||
ptr
->
count
<
max_unstake_requests
,
"unstake requests limit exceeded"
);
if
(
ptr
)
{
counts
.
update
(
*
ptr
,
usv
.
voter
,
[
&
](
auto
&
r
)
{
++
r
.
count
;
});
}
else
{
counts
.
emplace
(
usv
.
voter
,
[
&
](
auto
&
r
)
{
r
.
count
=
1
;
});
}
unstake_requests_table
requests
(
SystemAccount
,
SystemAccount
);
auto
pk
=
requests
.
available_primary_key
();
requests
.
emplace
(
usv
.
voter
,
[
&
](
unstake_request
&
r
)
{
r
.
id
=
pk
;
r
.
account
=
usv
.
voter
;
r
.
transfer_time
=
now
()
+
voting_stake_freez_time
;
});
account_votes_index_type
avotes
(
SystemAccount
,
SystemAccount
);
const
auto
*
acv
=
avotes
.
find
(
usv
.
voter
);
eosio_assert
(
bool
(
acv
),
"stake not found"
);
eosio_assert
(
acv
->
staked
.
quantity
<
usv
.
amount
.
quantity
,
"attempt to unstake more than total stake amount"
);
producer_info_index_type
producers
(
SystemAccount
,
SystemAccount
);
for
(
auto
p
:
acv
->
producers
)
{
producers
.
update
(
producers
.
get
(
p
),
0
,
[
&
](
auto
&
v
)
{
v
.
total_votes
-=
usv
.
amount
.
quantity
;
});
}
if
(
usv
.
amount
.
quantity
<
acv
->
staked
)
{
avotes
.
update
(
*
acv
,
0
,
[
&
](
auto
&
av
)
{
av
.
last_update
=
now
();
av
.
staked
-=
usv
.
amount
.
quantity
;
});
}
else
{
eos_assert
(
usv
.
amount
.
quantity
==
acv
->
staked
,
"unstaking more than is at staked"
);
avotes
.
remove
(
*
acv
);
}
}
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
...
...
@@ -161,52 +289,98 @@ namespace eosiosystem {
* @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
);
//validate input
if
(
vp
.
proxy
)
{
eosio_assert
(
vp
.
producers
.
size
()
==
0
,
"cannot vote for producers and proxy at same time"
);
}
else
{
eosio_assert
(
vp
.
producers
.
size
()
<=
30
,
"attempt to vote for too many producers"
);
eosio_assert
(
std
::
is_sorted
(
vp
.
producers
.
begin
(),
vp
.
producers
.
end
()
),
"producer votes must be sorted"
);
}
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
;
});
auto
ptr
=
avotes
.
find
(
vp
.
voter
);
eosio_assert
(
bool
(
ptr
),
"no stake to vote"
);
if
(
ptr
->
i_am_proxy
)
{
eosio_assert
(
vp
.
proxy
==
0
,
"accounts elected to be proxy are not allowed to use another proxy"
);
}
//find old producers, update old proxy if needed
const
std
::
vector
<
account_name
>*
old_producers
=
nullptr
;
if
(
ptr
->
proxy
)
{
if
(
ptr
->
proxy
==
vp
.
proxy
)
{
return
;
// nothing changed
}
auto
old_proxy
=
avotes
.
find
(
ptr
->
proxy
);
avotes
.
update
(
*
old_proxy
,
0
,
[
&
](
auto
&
a
)
{
a
.
proxied_votes
-=
ptr
->
staked
.
quantity
;
}
);
old_producers
=
&
old_proxy
->
producers
;
}
else
{
old_producers
=
&
ptr
->
producers
;
}
avotes
.
update
(
existing
,
0
,
[
&
](
auto
&
av
)
{
av
.
proxy
=
vp
.
proxy
;
av
.
last_update
=
now
();
av
.
producers
=
vp
.
producers
;
//find new producers, update new proxy if needed
const
std
::
vector
<
account_name
>*
new_producers
=
nullptr
;
if
(
vp
.
proxy
)
{
auto
new_proxy
=
avotes
.
find
(
ptr
->
proxy
);
avotes
.
update
(
*
new_proxy
,
0
,
[
&
](
auto
&
a
)
{
a
.
proxied_votes
+=
ptr
->
staked
.
quantity
;
}
);
new_producers
=
&
new_proxy
->
producers
;
}
else
{
new_producers
=
&
vp
.
producers
;
}
producer_info_index_type
producers
(
SystemAccount
,
SystemAccount
);
//revoke prower only from no longer elected
std
::
vector
<
account_name
>
revoked
(
old_producers
->
size
()
);
auto
end_it
=
std
::
set_difference
(
old_producers
->
begin
(),
old_producers
->
end
(),
new_producers
->
begin
(),
new_producers
->
end
(),
revoked
.
begin
()
);
for
(
auto
it
=
revoked
.
begin
();
it
!=
end_it
;
++
it
)
{
producers
.
update
(
producers
.
get
(
*
it
),
0
,
[
&
](
auto
&
pi
)
{
pi
.
total_votes
-=
ptr
->
staked
.
quantity
;
});
}
//update newly elected
std
::
vector
<
account_name
>
elected
(
new_producers
->
size
()
);
end_it
=
std
::
set_difference
(
new_producers
->
begin
(),
new_producers
->
end
(),
old_producers
->
begin
(),
old_producers
->
end
(),
elected
.
begin
()
);
for
(
auto
it
=
elected
.
begin
();
it
!=
end_it
;
++
it
)
{
producers
.
update
(
producers
.
get
(
*
it
),
0
,
[
&
](
auto
&
pi
)
{
pi
.
total_votes
+=
ptr
->
staked
.
quantity
;
});
}
// save new values to the account itself
avotes
.
update
(
*
ptr
,
0
,
[
&
](
account_votes
&
a
)
{
a
.
proxy
=
vp
.
proxy
;
a
.
last_update
=
now
();
a
.
producers
=
vp
.
producers
;
});
}
ACTION
(
SystemAccount
,
regproxy
)
{
ACTION
(
SystemAccount
,
reg
ister_
proxy
)
{
account_name
proxy_to_register
;
EOSLIB_SERIALIZE
(
regproxy
,
(
proxy_to_register
)
)
EOSLIB_SERIALIZE
(
reg
ister_
proxy
,
(
proxy_to_register
)
)
};
static
void
on
(
const
regproxy
&
reg
)
{
static
void
on
(
const
reg
ister_
proxy
&
reg
)
{
require_auth
(
reg
.
proxy_to_register
);
account_votes_index_type
avotes
(
SystemAccount
,
SystemAccount
);
auto
ptr
=
avotes
.
find
(
reg
.
proxy_to_register
);
if
(
ptr
)
{
eosio_assert
(
ptr
->
i_am_proxy
==
0
,
"account is already a proxy"
);
eosio_assert
(
ptr
->
proxy
==
0
,
"account that uses another proxy is not allowed to become a proxy"
);
avotes
.
update
(
*
ptr
,
0
,
[
&
](
account_votes
&
a
)
{
a
.
i_am_proxy
=
1
;
});
}
else
{
avotes
.
emplace
(
reg
.
proxy_to_register
,
[
&
](
account_votes
&
a
)
{
a
.
owner
=
reg
.
proxy_to_register
;
a
.
last_update
=
now
();
a
.
proxy
=
0
;
a
.
i_am_proxy
=
1
;
a
.
proxied_votes
=
0
;
a
.
staked
.
quantity
=
0
;
});
}
}
};
}
contracts/eosiolib/multi_index.hpp
浏览文件 @
98faba45
...
...
@@ -20,6 +20,7 @@ namespace eosio {
namespace
bmi
=
boost
::
multi_index
;
using
boost
::
multi_index
::
const_mem_fun
;
using
boost
::
multi_index
::
member
;
template
<
typename
T
>
struct
secondary_iterator
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录