Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
fd4652f0
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,发现更多精彩内容 >>
提交
fd4652f0
编写于
11月 20, 2017
作者:
D
Daniel Larimer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fixed unit test with respect to delegated authority
上级
7f6e41b5
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
123 addition
and
122 deletion
+123
-122
libraries/chain/chain_controller.cpp
libraries/chain/chain_controller.cpp
+25
-36
libraries/chain/contracts/eosio_contract.cpp
libraries/chain/contracts/eosio_contract.cpp
+8
-6
libraries/chain/include/eosio/chain/authority_checker.hpp
libraries/chain/include/eosio/chain/authority_checker.hpp
+82
-78
libraries/chain/include/eosio/chain/chain_controller.hpp
libraries/chain/include/eosio/chain/chain_controller.hpp
+1
-0
libraries/chain/include/eosio/chain/config.hpp
libraries/chain/include/eosio/chain/config.hpp
+1
-0
libraries/testing/tester.cpp
libraries/testing/tester.cpp
+1
-0
tests/chain_tests/transfer_tests.cpp
tests/chain_tests/transfer_tests.cpp
+5
-2
未找到文件。
libraries/chain/chain_controller.cpp
浏览文件 @
fd4652f0
...
...
@@ -458,31 +458,12 @@ void chain_controller::_finalize_block( const signed_block& b ) { try {
}
FC_CAPTURE_AND_RETHROW
(
(
b
)
)
}
namespace
{
auto
make_get_permission
(
const
chainbase
::
database
&
db
)
{
return
[
&
db
](
const
permission_level
&
permission
)
{
auto
key
=
boost
::
make_tuple
(
permission
.
actor
,
permission
.
permission
);
return
db
.
get
<
permission_object
,
by_owner
>
(
key
);
};
}
auto
make_authority_checker
(
const
chainbase
::
database
&
db
,
const
flat_set
<
public_key_type
>&
signing_keys
)
{
auto
get_permission
=
make_get_permission
(
db
);
auto
get_authority
=
[
get_permission
](
const
permission_level
&
permission
)
{
return
get_permission
(
permission
).
auth
;
};
auto
depth_limit
=
db
.
get
<
global_property_object
>
().
configuration
.
max_authority_depth
;
wdump
((
depth_limit
));
return
make_auth_checker
(
move
(
get_authority
),
depth_limit
,
signing_keys
);
}
}
flat_set
<
public_key_type
>
chain_controller
::
get_required_keys
(
const
signed_transaction
&
trx
,
const
flat_set
<
public_key_type
>&
candidate_keys
)
const
{
auto
checker
=
make_authority_checker
(
_db
,
candidate_keys
);
auto
checker
=
make_auth_checker
(
[
&
](
auto
p
){
return
get_permission
(
p
).
auth
;
},
get_global_properties
().
configuration
.
max_authority_depth
,
candidate_keys
);
for
(
const
auto
&
act
:
trx
.
actions
)
{
for
(
const
auto
&
declared_auth
:
act
.
authorization
)
{
...
...
@@ -500,23 +481,21 @@ flat_set<public_key_type> chain_controller::get_required_keys(const signed_trans
void
chain_controller
::
check_transaction_authorization
(
const
signed_transaction
&
trx
,
bool
allow_unused_signatures
)
const
{
if
((
_skip_flags
&
skip_transaction_signatures
)
&&
(
_skip_flags
&
skip_authority_check
))
{
//ilog("Skipping auth and sigs checks");
return
;
}
auto
get_permission
=
make_get_permission
(
_db
);
// #warning TODO: Use a real chain_id here (where is this stored? Do we still need it?)
auto
checker
=
make_authority_checker
(
_db
,
trx
.
get_signature_keys
(
chain_id_type
{}));
auto
checker
=
make_auth_checker
(
[
&
](
auto
p
){
return
get_permission
(
p
).
auth
;
},
get_global_properties
().
configuration
.
max_authority_depth
,
trx
.
get_signature_keys
(
chain_id_type
{})
);
for
(
const
auto
&
act
:
trx
.
actions
)
for
(
const
auto
&
declared_auth
:
act
.
authorization
)
{
const
auto
&
min_permission
=
lookup_minimum_permission
(
declared_auth
.
actor
,
act
.
scope
,
act
.
name
);
const
auto
&
min_permission
=
lookup_minimum_permission
(
declared_auth
.
actor
,
act
.
scope
,
act
.
name
);
if
((
_skip_flags
&
skip_authority_check
)
==
false
)
{
const
auto
&
index
=
_db
.
get_index
<
permission_index
>
().
indices
();
EOS_ASSERT
(
get_permission
(
declared_auth
).
satisfies
(
min_permission
,
index
),
tx_irrelevant_auth
,
EOS_ASSERT
(
get_permission
(
declared_auth
).
satisfies
(
min_permission
,
index
),
tx_irrelevant_auth
,
"action declares irrelevant authority '${auth}'; minimum authority is ${min}"
,
(
"auth"
,
declared_auth
)(
"min"
,
min_permission
.
name
));
}
...
...
@@ -529,14 +508,19 @@ void chain_controller::check_transaction_authorization(const signed_transaction&
if
(
!
allow_unused_signatures
&&
(
_skip_flags
&
skip_transaction_signatures
)
==
false
)
EOS_ASSERT
(
checker
.
all_keys_used
(),
tx_irrelevant_sig
,
"transaction bears irrelevant signatures from these keys: ${keys}"
,
(
"keys"
,
checker
.
unused_keys
()));
"transaction bears irrelevant signatures from these keys: ${keys}"
,
(
"keys"
,
checker
.
unused_keys
()));
}
void
chain_controller
::
validate_scope
(
const
transaction
&
trx
)
const
{
for
(
uint32_t
i
=
1
;
i
<
trx
.
read_scope
.
size
();
++
i
)
EOS_ASSERT
(
trx
.
read_scope
[
i
-
1
]
<
trx
.
read_scope
[
i
],
transaction_exception
,
"Scopes must be sorted and unique"
);
for
(
uint32_t
i
=
1
;
i
<
trx
.
write_scope
.
size
();
++
i
)
EOS_ASSERT
(
trx
.
write_scope
[
i
-
1
]
<
trx
.
write_scope
[
i
],
transaction_exception
,
"Scopes must be sorted and unique"
);
for
(
uint32_t
i
=
1
;
i
<
trx
.
read_scope
.
size
();
++
i
)
{
EOS_ASSERT
(
trx
.
read_scope
[
i
-
1
]
<
trx
.
read_scope
[
i
],
transaction_exception
,
"Scopes must be sorted and unique"
);
}
for
(
uint32_t
i
=
1
;
i
<
trx
.
write_scope
.
size
();
++
i
)
{
EOS_ASSERT
(
trx
.
write_scope
[
i
-
1
]
<
trx
.
write_scope
[
i
],
transaction_exception
,
"Scopes must be sorted and unique"
);
}
vector
<
account_name
>
intersection
;
std
::
set_intersection
(
trx
.
read_scope
.
begin
(),
trx
.
read_scope
.
end
(),
...
...
@@ -875,6 +859,11 @@ const producer_object& chain_controller::get_producer(const account_name& owner_
return
_db
.
get
<
producer_object
,
by_owner
>
(
owner_name
);
}
FC_CAPTURE_AND_RETHROW
(
(
owner_name
)
)
}
const
permission_object
&
chain_controller
::
get_permission
(
const
permission_level
&
level
)
const
{
try
{
return
_db
.
get
<
permission_object
,
by_owner
>
(
boost
::
make_tuple
(
level
.
actor
,
level
.
permission
)
);
}
FC_CAPTURE_AND_RETHROW
(
(
level
)
)
}
uint32_t
chain_controller
::
last_irreversible_block_num
()
const
{
return
get_dynamic_global_properties
().
last_irreversible_block_num
;
}
...
...
libraries/chain/contracts/eosio_contract.cpp
浏览文件 @
fd4652f0
...
...
@@ -379,6 +379,8 @@ void apply_eosio_setproxy(apply_context& context) {
}
void
apply_eosio_updateauth
(
apply_context
&
context
)
{
context
.
require_write_scope
(
config
::
eosio_auth_scope
);
auto
update
=
context
.
act
.
as
<
updateauth
>
();
EOS_ASSERT
(
!
update
.
permission
.
empty
(),
action_validate_exception
,
"Cannot create authority with empty name"
);
EOS_ASSERT
(
update
.
permission
!=
update
.
parent
,
action_validate_exception
,
...
...
@@ -407,14 +409,14 @@ void apply_eosio_updateauth(apply_context& context) {
if
(
permission
)
{
EOS_ASSERT
(
parent_id
==
permission
->
parent
,
action_validate_exception
,
"Changing parent authority is not currently supported"
);
if
(
context
.
controller
.
is_applying_block
())
// TODO/QUESTION: If we are updating an existing permission, should we check if the message declared
// permission satisfies the permission we want to modify?
db
.
modify
(
*
permission
,
[
&
update
,
&
parent_id
](
permission_object
&
po
)
{
po
.
auth
=
update
.
authority
;
po
.
parent
=
parent_id
;
});
}
else
if
(
context
.
controller
.
is_applying_block
())
{
db
.
modify
(
*
permission
,
[
&
update
,
&
parent_id
](
permission_object
&
po
)
{
po
.
auth
=
update
.
authority
;
po
.
parent
=
parent_id
;
});
}
else
{
// TODO/QUESTION: If we are creating a new permission, should we check if the message declared
// permission satisfies the parent permission?
db
.
create
<
permission_object
>
([
&
update
,
&
parent_id
](
permission_object
&
po
)
{
...
...
libraries/chain/include/eosio/chain/authority_checker.hpp
浏览文件 @
fd4652f0
...
...
@@ -50,92 +50,96 @@ namespace detail {
* @tparam F A callable which takes a single argument of type @ref AccountPermission and returns the corresponding
* authority
*/
template
<
typename
F
>
template
<
typename
PermissionToAuthorityFunc
>
class
authority_checker
{
F
permission_to_authority
;
uint16_t
recursion_depth_limit
;
vector
<
public_key_type
>
signing_keys
;
vector
<
bool
>
_used_keys
;
struct
weight_tally_visitor
{
using
result_type
=
uint32_t
;
authority_checker
&
checker
;
uint16_t
recursion_depth
;
uint32_t
total_weight
=
0
;
weight_tally_visitor
(
authority_checker
&
checker
,
uint16_t
recursion_depth
)
:
checker
(
checker
),
recursion_depth
(
recursion_depth
)
{}
uint32_t
operator
()(
const
key_weight
&
permission
)
{
auto
itr
=
boost
::
find
(
checker
.
signing_keys
,
permission
.
key
);
if
(
itr
!=
checker
.
signing_keys
.
end
())
{
checker
.
_used_keys
[
itr
-
checker
.
signing_keys
.
begin
()]
=
true
;
total_weight
+=
permission
.
weight
;
private:
PermissionToAuthorityFunc
permission_to_authority
;
uint16_t
recursion_depth_limit
;
vector
<
public_key_type
>
signing_keys
;
vector
<
bool
>
_used_keys
;
struct
weight_tally_visitor
{
using
result_type
=
uint32_t
;
authority_checker
&
checker
;
uint16_t
recursion_depth
;
uint32_t
total_weight
=
0
;
weight_tally_visitor
(
authority_checker
&
checker
,
uint16_t
recursion_depth
)
:
checker
(
checker
),
recursion_depth
(
recursion_depth
)
{}
uint32_t
operator
()(
const
key_weight
&
permission
)
{
auto
itr
=
boost
::
find
(
checker
.
signing_keys
,
permission
.
key
);
if
(
itr
!=
checker
.
signing_keys
.
end
())
{
checker
.
_used_keys
[
itr
-
checker
.
signing_keys
.
begin
()]
=
true
;
total_weight
+=
permission
.
weight
;
}
return
total_weight
;
}
return
total_weight
;
}
uint32_t
operator
()(
const
permission_level_weight
&
permission
)
{
if
(
recursion_depth
<
checker
.
recursion_depth_limit
&&
checker
.
satisfied
(
permission
.
permission
,
recursion_depth
+
1
))
total_weight
+=
permission
.
weight
;
return
total_weight
;
uint32_t
operator
()(
const
permission_level_weight
&
permission
)
{
if
(
recursion_depth
<
checker
.
recursion_depth_limit
)
{
if
(
checker
.
satisfied
(
permission
.
permission
,
recursion_depth
+
1
)
)
total_weight
+=
permission
.
weight
;
}
return
total_weight
;
}
};
public:
authority_checker
(
PermissionToAuthorityFunc
permission_to_authority
,
uint16_t
recursion_depth_limit
,
const
flat_set
<
public_key_type
>&
signing_keys
)
:
permission_to_authority
(
permission_to_authority
),
recursion_depth_limit
(
recursion_depth_limit
),
signing_keys
(
signing_keys
.
begin
(),
signing_keys
.
end
()),
_used_keys
(
signing_keys
.
size
(),
false
)
{}
bool
satisfied
(
const
permission_level
&
permission
,
uint16_t
depth
=
0
)
{
return
satisfied
(
permission_to_authority
(
permission
),
depth
);
}
};
public:
authority_checker
(
F
permission_to_authority
,
uint16_t
recursion_depth_limit
,
const
flat_set
<
public_key_type
>&
signing_keys
)
:
permission_to_authority
(
permission_to_authority
),
recursion_depth_limit
(
recursion_depth_limit
),
signing_keys
(
signing_keys
.
begin
(),
signing_keys
.
end
()),
_used_keys
(
signing_keys
.
size
(),
false
)
{}
bool
satisfied
(
const
permission_level
&
permission
,
uint16_t
depth
=
0
)
{
return
satisfied
(
permission_to_authority
(
permission
),
depth
);
}
template
<
typename
AuthorityType
>
bool
satisfied
(
const
AuthorityType
&
authority
,
uint16_t
depth
=
0
)
{
// This check is redundant, since weight_tally_visitor did it too, but I'll leave it here for future-proofing
if
(
depth
>
recursion_depth_limit
)
template
<
typename
AuthorityType
>
bool
satisfied
(
const
AuthorityType
&
authority
,
uint16_t
depth
=
0
)
{
// This check is redundant, since weight_tally_visitor did it too, but I'll leave it here for future-proofing
if
(
depth
>
recursion_depth_limit
)
return
false
;
// Save the current used keys; if we do not satisfy this authority, the newly used keys aren't actually used
auto
KeyReverter
=
fc
::
make_scoped_exit
([
this
,
keys
=
_used_keys
]
()
mutable
{
_used_keys
=
keys
;
});
// Sort key permissions and account permissions together into a single set of meta_permissions
detail
::
meta_permission_set
permissions
;
permissions
.
insert
(
authority
.
keys
.
begin
(),
authority
.
keys
.
end
());
permissions
.
insert
(
authority
.
accounts
.
begin
(),
authority
.
accounts
.
end
());
// Check all permissions, from highest weight to lowest, seeing if signing_keys satisfies them or not
weight_tally_visitor
visitor
(
*
this
,
depth
);
for
(
const
auto
&
permission
:
permissions
)
// If we've got enough weight, to satisfy the authority, return!
if
(
permission
.
visit
(
visitor
)
>=
authority
.
threshold
)
{
KeyReverter
.
cancel
();
return
true
;
}
return
false
;
}
// Save the current used keys; if we do not satisfy this authority, the newly used keys aren't actually used
auto
KeyReverter
=
fc
::
make_scoped_exit
([
this
,
keys
=
_used_keys
]
()
mutable
{
_used_keys
=
keys
;
});
// Sort key permissions and account permissions together into a single set of meta_permissions
detail
::
meta_permission_set
permissions
;
permissions
.
insert
(
authority
.
keys
.
begin
(),
authority
.
keys
.
end
());
permissions
.
insert
(
authority
.
accounts
.
begin
(),
authority
.
accounts
.
end
());
// Check all permissions, from highest weight to lowest, seeing if signing_keys satisfies them or not
weight_tally_visitor
visitor
(
*
this
,
depth
);
for
(
const
auto
&
permission
:
permissions
)
// If we've got enough weight, to satisfy the authority, return!
if
(
permission
.
visit
(
visitor
)
>=
authority
.
threshold
)
{
KeyReverter
.
cancel
();
return
true
;
}
return
false
;
}
bool
all_keys_used
()
const
{
return
boost
::
algorithm
::
all_of_equal
(
_used_keys
,
true
);
}
bool
all_keys_used
()
const
{
return
boost
::
algorithm
::
all_of_equal
(
_used_keys
,
true
);
}
flat_set
<
public_key_type
>
used_keys
()
const
{
auto
range
=
utilities
::
FilterDataByMarker
(
signing_keys
,
_used_keys
,
true
);
return
{
range
.
begin
(),
range
.
end
()};
}
flat_set
<
public_key_type
>
unused_keys
()
const
{
auto
range
=
utilities
::
FilterDataByMarker
(
signing_keys
,
_used_keys
,
false
);
return
{
range
.
begin
(),
range
.
end
()};
}
flat_set
<
public_key_type
>
used_keys
()
const
{
auto
range
=
utilities
::
FilterDataByMarker
(
signing_keys
,
_used_keys
,
true
);
return
{
range
.
begin
(),
range
.
end
()};
}
flat_set
<
public_key_type
>
unused_keys
()
const
{
auto
range
=
utilities
::
FilterDataByMarker
(
signing_keys
,
_used_keys
,
false
);
return
{
range
.
begin
(),
range
.
end
()};
}
};
/// authority_checker
template
<
typename
F
>
aut
hority_checker
<
F
>
make_auth_checker
(
F
&&
pta
,
uint16_t
recursion_depth_limit
,
const
flat_set
<
public_key_type
>&
signing_keys
)
{
return
authority_checker
<
F
>
(
std
::
forward
<
F
>
(
pta
),
recursion_depth_limit
,
signing_keys
);
template
<
typename
PermissionToAuthorityFunc
>
aut
o
make_auth_checker
(
PermissionToAuthorityFunc
&&
pta
,
uint16_t
recursion_depth_limit
,
const
flat_set
<
public_key_type
>&
signing_keys
)
{
return
authority_checker
<
PermissionToAuthorityFunc
>
(
std
::
forward
<
PermissionToAuthorityFunc
>
(
pta
),
recursion_depth_limit
,
signing_keys
);
}
}
}
// namespace eosio::chain
libraries/chain/include/eosio/chain/chain_controller.hpp
浏览文件 @
fd4652f0
...
...
@@ -255,6 +255,7 @@ 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
account_name
&
ownername
)
const
;
const
permission_object
&
get_permission
(
const
permission_level
&
level
)
const
;
time_point
head_block_time
()
const
;
uint32_t
head_block_num
()
const
;
...
...
libraries/chain/include/eosio/chain/config.hpp
浏览文件 @
fd4652f0
...
...
@@ -49,6 +49,7 @@ const static uint32_t producers_authority_threshold = 14;
const
static
share_type
default_elected_pay
=
asset
(
100
).
amount
;
const
static
share_type
default_min_eos_balance
=
asset
(
100
).
amount
;
const
static
uint16_t
max_recursion_depth
=
6
;
/**
* The number of sequential blocks produced by a single producer
...
...
libraries/testing/tester.cpp
浏览文件 @
fd4652f0
...
...
@@ -81,6 +81,7 @@ namespace eosio { namespace testing {
.
recovery
=
authority
(
get_public_key
(
a
,
"recovery"
)
),
.
deposit
=
initial_balance
});
trx
.
sign
(
get_private_key
(
creator
,
"active"
),
chain_id_type
()
);
control
->
push_transaction
(
trx
);
...
...
tests/chain_tests/transfer_tests.cpp
浏览文件 @
fd4652f0
...
...
@@ -139,7 +139,10 @@ BOOST_AUTO_TEST_CASE( transfer_delegation ) { try {
});
test
.
set_authority
(
N
(
dan
),
config
::
active_name
,
dans_active_auth
);
idump
((
dans_active_auth
));
const
auto
&
danauth
=
test
.
control
->
get_permission
(
permission_level
{
N
(
dan
),
config
::
active_name
}
);
const
auto
&
trustauth
=
test
.
control
->
get_permission
(
permission_level
{
N
(
trust
),
config
::
active_name
}
);
test
.
produce_block
();
...
...
@@ -161,11 +164,11 @@ BOOST_AUTO_TEST_CASE( transfer_delegation ) { try {
test
.
set_tapos
(
trx
);
trx
.
sign
(
test
.
get_private_key
(
N
(
trust
),
"active"
),
chain_id_type
()
);
/// action not provided from authority
test
.
control
->
push_transaction
(
trx
);
}
}
FC_LOG_AND_RETHROW
()
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录