Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
40544bf7
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,发现更多精彩内容 >>
提交
40544bf7
编写于
7月 05, 2017
作者:
D
Daniel Larimer
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of github.com:EOSIO/eos
上级
4b41467b
15898a06
变更
20
展开全部
隐藏空白更改
内联
并排
Showing
20 changed file
with
1326 addition
and
1114 deletion
+1326
-1114
libraries/chain/chain_controller.cpp
libraries/chain/chain_controller.cpp
+10
-1
libraries/chain/include/eos/chain/account_object.hpp
libraries/chain/include/eos/chain/account_object.hpp
+0
-69
libraries/chain/include/eos/chain/action_objects.hpp
libraries/chain/include/eos/chain/action_objects.hpp
+3
-3
libraries/chain/include/eos/chain/authority.hpp
libraries/chain/include/eos/chain/authority.hpp
+93
-18
libraries/chain/include/eos/chain/exceptions.hpp
libraries/chain/include/eos/chain/exceptions.hpp
+1
-3
libraries/chain/include/eos/chain/permission_object.hpp
libraries/chain/include/eos/chain/permission_object.hpp
+73
-0
libraries/chain/transaction.cpp
libraries/chain/transaction.cpp
+11
-17
libraries/native_contract/system_contract.cpp
libraries/native_contract/system_contract.cpp
+4
-3
plugins/net_plugin/include/eos/net_plugin/net_plugin.hpp
plugins/net_plugin/include/eos/net_plugin/net_plugin.hpp
+2
-0
plugins/net_plugin/net_plugin.cpp
plugins/net_plugin/net_plugin.cpp
+75
-54
plugins/producer_plugin/CMakeLists.txt
plugins/producer_plugin/CMakeLists.txt
+1
-1
plugins/producer_plugin/producer_plugin.cpp
plugins/producer_plugin/producer_plugin.cpp
+2
-1
tests/CMakeLists.txt
tests/CMakeLists.txt
+4
-0
tests/common/main.cpp
tests/common/main.cpp
+0
-0
tests/slow_tests/slow_tests.cpp
tests/slow_tests/slow_tests.cpp
+991
-0
tests/slow_tests/wast/simplecoin.cpp
tests/slow_tests/wast/simplecoin.cpp
+0
-0
tests/slow_tests/wast/simplecoin.wast
tests/slow_tests/wast/simplecoin.wast
+0
-0
tests/tests/block_tests.cpp
tests/tests/block_tests.cpp
+0
-878
tests/tests/misc_tests.cpp
tests/tests/misc_tests.cpp
+55
-1
tests/tests/native_contract_tests.cpp
tests/tests/native_contract_tests.cpp
+1
-65
未找到文件。
libraries/chain/chain_controller.cpp
浏览文件 @
40544bf7
...
...
@@ -639,11 +639,20 @@ void chain_controller::apply_message( apply_context& context )
}
FC_CAPTURE_AND_RETHROW
((
context
.
msg
))
}
void
chain_controller
::
_apply_transaction
(
const
SignedTransaction
&
trx
)
{
try
{
validate_transaction
(
trx
);
auto
getAuthority
=
[
&
db
=
_db
](
const
types
::
AccountPermission
&
permission
)
{
auto
key
=
boost
::
make_tuple
(
permission
.
account
,
permission
.
permission
);
return
db
.
get
<
permission_object
,
by_owner
>
(
key
).
auth
;
};
#warning TODO: Use a real chain_id here (where is this stored? Do we still need it?)
auto
checker
=
MakeAuthorityChecker
(
std
::
move
(
getAuthority
),
trx
.
get_signature_keys
(
chain_id_type
{}));
for
(
const
auto
&
requiredAuthority
:
trx
.
authorizations
)
EOS_ASSERT
(
checker
.
satisfied
(
requiredAuthority
),
tx_missing_auth
,
"Transaction is not authorized."
);
for
(
const
auto
&
message
:
trx
.
messages
)
{
process_message
(
message
);
}
...
...
libraries/chain/include/eos/chain/account_object.hpp
浏览文件 @
40544bf7
...
...
@@ -29,33 +29,6 @@
namespace
eos
{
namespace
chain
{
struct
shared_authority
{
shared_authority
(
chainbase
::
allocator
<
char
>
alloc
)
:
accounts
(
alloc
),
keys
(
alloc
)
{}
shared_authority
&
operator
=
(
const
Authority
&
a
)
{
threshold
=
a
.
threshold
;
accounts
=
decltype
(
accounts
)(
a
.
accounts
.
begin
(),
a
.
accounts
.
end
(),
accounts
.
get_allocator
());
keys
=
decltype
(
keys
)(
a
.
keys
.
begin
(),
a
.
keys
.
end
(),
keys
.
get_allocator
());
return
*
this
;
}
shared_authority
&
operator
=
(
Authority
&&
a
)
{
threshold
=
a
.
threshold
;
accounts
.
reserve
(
a
.
accounts
.
size
());
for
(
auto
&
p
:
a
.
accounts
)
accounts
.
emplace_back
(
std
::
move
(
p
));
keys
.
reserve
(
a
.
keys
.
size
());
for
(
auto
&
p
:
a
.
keys
)
keys
.
emplace_back
(
std
::
move
(
p
));
return
*
this
;
}
UInt32
threshold
=
0
;
shared_vector
<
types
::
AccountPermissionWeight
>
accounts
;
shared_vector
<
types
::
KeyPermissionWeight
>
keys
;
};
class
account_object
:
public
chainbase
::
object
<
account_object_type
,
account_object
>
{
OBJECT_CTOR
(
account_object
,(
code
))
...
...
@@ -78,52 +51,10 @@ namespace eos { namespace chain {
>
>
;
class
permission_object
:
public
chainbase
::
object
<
permission_object_type
,
permission_object
>
{
OBJECT_CTOR
(
permission_object
,
(
auth
)
)
id_type
id
;
AccountName
owner
;
///< the account this permission belongs to
id_type
parent
;
///< parent permission
PermissionName
name
;
///< human-readable name for the permission
shared_authority
auth
;
///< authority required to execute this permission
};
struct
by_parent
;
struct
by_owner
;
using
permission_index
=
chainbase
::
shared_multi_index_container
<
permission_object
,
indexed_by
<
ordered_unique
<
tag
<
by_id
>
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
id
>>
,
ordered_unique
<
tag
<
by_parent
>
,
composite_key
<
permission_object
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
parent
>
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
id
>
>
>
,
ordered_unique
<
tag
<
by_owner
>
,
composite_key
<
permission_object
,
member
<
permission_object
,
AccountName
,
&
permission_object
::
owner
>
,
member
<
permission_object
,
PermissionName
,
&
permission_object
::
name
>
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
id
>
>
>
,
ordered_unique
<
tag
<
by_name
>
,
composite_key
<
permission_object
,
member
<
permission_object
,
PermissionName
,
&
permission_object
::
name
>
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
id
>
>
>
>
>
;
}
}
// eos::chain
CHAINBASE_SET_INDEX_TYPE
(
eos
::
chain
::
account_object
,
eos
::
chain
::
account_index
)
CHAINBASE_SET_INDEX_TYPE
(
eos
::
chain
::
permission_object
,
eos
::
chain
::
permission_index
)
FC_REFLECT
(
chainbase
::
oid
<
eos
::
chain
::
permission_object
>
,
(
_id
))
FC_REFLECT
(
chainbase
::
oid
<
eos
::
chain
::
account_object
>
,
(
_id
))
FC_REFLECT
(
eos
::
chain
::
shared_authority
,
(
threshold
)(
accounts
)(
keys
))
FC_REFLECT
(
eos
::
chain
::
account_object
,
(
id
)(
name
)(
vm_type
)(
vm_version
)(
code_version
)(
code
)(
creation_date
))
FC_REFLECT
(
eos
::
chain
::
permission_object
,
(
id
)(
owner
)(
parent
)(
name
)(
auth
))
libraries/chain/include/eos/chain/action_objects.hpp
浏览文件 @
40544bf7
...
...
@@ -23,7 +23,7 @@
*/
#pragma once
#include <eos/chain/types.hpp>
#include <eos/chain/
account
_object.hpp>
#include <eos/chain/
permission
_object.hpp>
#include "multi_index_includes.hpp"
...
...
@@ -57,7 +57,7 @@ namespace eos { namespace chain {
OBJECT_CTOR
(
action_permission_object
)
id_type
id
;
account_id_type
owner
;
///< the account whose permission we seek
AccountName
owner
;
///< the account whose permission we seek
permission_object
::
id_type
scope_permission
;
///< the scope permission defined by the contract for the action
permission_object
::
id_type
owner_permission
;
///< the owner permission that is required
};
...
...
@@ -69,7 +69,7 @@ namespace eos { namespace chain {
ordered_unique
<
tag
<
by_id
>
,
member
<
action_permission_object
,
action_permission_object
::
id_type
,
&
action_permission_object
::
id
>>
,
ordered_unique
<
tag
<
by_owner_scope
>
,
composite_key
<
action_permission_object
,
member
<
action_permission_object
,
account_id_typ
e
,
&
action_permission_object
::
owner
>
,
member
<
action_permission_object
,
AccountNam
e
,
&
action_permission_object
::
owner
>
,
member
<
action_permission_object
,
permission_object
::
id_type
,
&
action_permission_object
::
scope_permission
>
>
>
...
...
libraries/chain/include/eos/chain/authority.hpp
浏览文件 @
40544bf7
...
...
@@ -2,26 +2,101 @@
#include <eos/chain/types.hpp>
#include <eos/types/generated.hpp>
namespace
eos
{
inline
bool
operator
<
(
const
types
::
AccountPermission
&
a
,
const
types
::
AccountPermission
&
b
)
{
return
std
::
tie
(
a
.
account
,
a
.
permission
)
<
std
::
tie
(
b
.
account
,
b
.
permission
);
namespace
eos
{
namespace
chain
{
struct
shared_authority
{
shared_authority
(
chainbase
::
allocator
<
char
>
alloc
)
:
accounts
(
alloc
),
keys
(
alloc
)
{}
shared_authority
&
operator
=
(
const
Authority
&
a
)
{
threshold
=
a
.
threshold
;
accounts
=
decltype
(
accounts
)(
a
.
accounts
.
begin
(),
a
.
accounts
.
end
(),
accounts
.
get_allocator
());
keys
=
decltype
(
keys
)(
a
.
keys
.
begin
(),
a
.
keys
.
end
(),
keys
.
get_allocator
());
return
*
this
;
}
shared_authority
&
operator
=
(
Authority
&&
a
)
{
threshold
=
a
.
threshold
;
accounts
.
reserve
(
a
.
accounts
.
size
());
for
(
auto
&
p
:
a
.
accounts
)
accounts
.
emplace_back
(
std
::
move
(
p
));
keys
.
reserve
(
a
.
keys
.
size
());
for
(
auto
&
p
:
a
.
keys
)
keys
.
emplace_back
(
std
::
move
(
p
));
return
*
this
;
}
/**
* Makes sure all keys are unique and sorted and all account permissions are unique and sorted
*/
inline
bool
validate
(
types
::
Authority
&
auth
)
{
const
types
::
KeyPermissionWeight
*
prev
=
nullptr
;
for
(
const
auto
&
k
:
auth
.
keys
)
{
if
(
!
prev
)
prev
=
&
k
;
else
if
(
prev
->
key
<
k
.
key
)
return
false
;
}
const
types
::
AccountPermissionWeight
*
pa
=
nullptr
;
for
(
const
auto
&
a
:
auth
.
accounts
)
{
if
(
!
pa
)
pa
=
&
a
;
else
if
(
pa
->
permission
<
a
.
permission
)
return
false
;
}
return
true
;
UInt32
threshold
=
0
;
shared_vector
<
types
::
AccountPermissionWeight
>
accounts
;
shared_vector
<
types
::
KeyPermissionWeight
>
keys
;
};
/**
* @brief This class determines whether a set of signing keys are sufficient to satisfy an authority or not
*
* To determine whether an authority is satisfied or not, we first determine which keys have approved of a message, and
* then determine whether that list of keys is sufficient to satisfy the authority. This class takes a list of keys and
* provides the @ref satisfied method to determine whether that list of keys satisfies a provided authority.
*
* @tparam F A callable which takes a single argument of type @ref AccountPermission and returns the corresponding
* authority
*/
template
<
typename
F
>
class
AuthorityChecker
{
F
PermissionToAuthority
;
const
flat_set
<
public_key_type
>&
signingKeys
;
public:
AuthorityChecker
(
F
PermissionToAuthority
,
const
flat_set
<
public_key_type
>&
signingKeys
)
:
PermissionToAuthority
(
PermissionToAuthority
),
signingKeys
(
signingKeys
)
{}
bool
satisfied
(
const
types
::
AccountPermission
&
permission
)
const
{
return
satisfied
(
PermissionToAuthority
(
permission
));
}
template
<
typename
AuthorityType
>
bool
satisfied
(
const
AuthorityType
&
authority
)
const
{
UInt32
weight
=
0
;
for
(
const
auto
&
kpw
:
authority
.
keys
)
if
(
signingKeys
.
count
(
kpw
.
key
))
{
weight
+=
kpw
.
weight
;
if
(
weight
>=
authority
.
threshold
)
return
true
;
}
for
(
const
auto
&
apw
:
authority
.
accounts
)
#warning TODO: Recursion limit?
if
(
satisfied
(
apw
.
permission
))
{
weight
+=
apw
.
weight
;
if
(
weight
>=
authority
.
threshold
)
return
true
;
}
return
false
;
}
};
inline
bool
operator
<
(
const
types
::
AccountPermission
&
a
,
const
types
::
AccountPermission
&
b
)
{
return
std
::
tie
(
a
.
account
,
a
.
permission
)
<
std
::
tie
(
b
.
account
,
b
.
permission
);
}
template
<
typename
F
>
AuthorityChecker
<
F
>
MakeAuthorityChecker
(
F
&&
pta
,
const
flat_set
<
public_key_type
>&
signingKeys
)
{
return
AuthorityChecker
<
F
>
(
std
::
forward
<
F
>
(
pta
),
signingKeys
);
}
/**
* Makes sure all keys are unique and sorted and all account permissions are unique and sorted
*/
inline
bool
validate
(
types
::
Authority
&
auth
)
{
const
types
::
KeyPermissionWeight
*
prev
=
nullptr
;
for
(
const
auto
&
k
:
auth
.
keys
)
{
if
(
!
prev
)
prev
=
&
k
;
else
if
(
prev
->
key
<
k
.
key
)
return
false
;
}
const
types
::
AccountPermissionWeight
*
pa
=
nullptr
;
for
(
const
auto
&
a
:
auth
.
accounts
)
{
if
(
!
pa
)
pa
=
&
a
;
else
if
(
pa
->
permission
<
a
.
permission
)
return
false
;
}
return
true
;
}
}
}
// namespace eos::chain
FC_REFLECT
(
eos
::
chain
::
shared_authority
,
(
threshold
)(
accounts
)(
keys
))
libraries/chain/include/eos/chain/exceptions.hpp
浏览文件 @
40544bf7
...
...
@@ -42,9 +42,7 @@ namespace eos { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION
(
black_swan_exception
,
eos
::
chain
::
chain_exception
,
3100000
,
"black swan"
)
FC_DECLARE_DERIVED_EXCEPTION
(
unknown_block_exception
,
eos
::
chain
::
chain_exception
,
3110000
,
"unknown block"
)
FC_DECLARE_DERIVED_EXCEPTION
(
tx_missing_active_auth
,
eos
::
chain
::
transaction_exception
,
3030001
,
"missing required active authority"
)
FC_DECLARE_DERIVED_EXCEPTION
(
tx_missing_owner_auth
,
eos
::
chain
::
transaction_exception
,
3030002
,
"missing required owner authority"
)
FC_DECLARE_DERIVED_EXCEPTION
(
tx_missing_other_auth
,
eos
::
chain
::
transaction_exception
,
3030003
,
"missing required other authority"
)
FC_DECLARE_DERIVED_EXCEPTION
(
tx_missing_auth
,
eos
::
chain
::
transaction_exception
,
3030001
,
"missing required authority"
)
FC_DECLARE_DERIVED_EXCEPTION
(
tx_irrelevant_sig
,
eos
::
chain
::
transaction_exception
,
3030004
,
"irrelevant signature included"
)
FC_DECLARE_DERIVED_EXCEPTION
(
tx_duplicate_sig
,
eos
::
chain
::
transaction_exception
,
3030005
,
"duplicate signature included"
)
FC_DECLARE_DERIVED_EXCEPTION
(
invalid_committee_approval
,
eos
::
chain
::
transaction_exception
,
3030006
,
"committee account cannot directly approve transaction"
)
...
...
libraries/chain/include/eos/chain/permission_object.hpp
0 → 100644
浏览文件 @
40544bf7
/*
* Copyright (c) 2017, Respective Authors.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <eos/chain/authority.hpp>
#include "multi_index_includes.hpp"
namespace
eos
{
namespace
chain
{
class
permission_object
:
public
chainbase
::
object
<
permission_object_type
,
permission_object
>
{
OBJECT_CTOR
(
permission_object
,
(
auth
)
)
id_type
id
;
AccountName
owner
;
///< the account this permission belongs to
id_type
parent
;
///< parent permission
PermissionName
name
;
///< human-readable name for the permission
shared_authority
auth
;
///< authority required to execute this permission
};
struct
by_parent
;
struct
by_owner
;
struct
by_name
;
using
permission_index
=
chainbase
::
shared_multi_index_container
<
permission_object
,
indexed_by
<
ordered_unique
<
tag
<
by_id
>
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
id
>>
,
ordered_unique
<
tag
<
by_parent
>
,
composite_key
<
permission_object
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
parent
>
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
id
>
>
>
,
ordered_unique
<
tag
<
by_owner
>
,
composite_key
<
permission_object
,
member
<
permission_object
,
AccountName
,
&
permission_object
::
owner
>
,
member
<
permission_object
,
PermissionName
,
&
permission_object
::
name
>
>
>
,
ordered_unique
<
tag
<
by_name
>
,
composite_key
<
permission_object
,
member
<
permission_object
,
PermissionName
,
&
permission_object
::
name
>
,
member
<
permission_object
,
permission_object
::
id_type
,
&
permission_object
::
id
>
>
>
>
>
;
}
}
// eos::chain
CHAINBASE_SET_INDEX_TYPE
(
eos
::
chain
::
permission_object
,
eos
::
chain
::
permission_index
)
FC_REFLECT
(
chainbase
::
oid
<
eos
::
chain
::
permission_object
>
,
(
_id
))
FC_REFLECT
(
eos
::
chain
::
permission_object
,
(
id
)(
owner
)(
parent
)(
name
)(
auth
))
libraries/chain/transaction.cpp
浏览文件 @
40544bf7
...
...
@@ -27,6 +27,8 @@
#include <fc/smart_ref_impl.hpp>
#include <algorithm>
#include <boost/range/adaptor/transformed.hpp>
namespace
eos
{
namespace
chain
{
digest_type
SignedTransaction
::
digest
()
const
{
...
...
@@ -50,16 +52,12 @@ eos::chain::transaction_id_type SignedTransaction::id() const {
}
const
signature_type
&
eos
::
chain
::
SignedTransaction
::
sign
(
const
private_key_type
&
key
,
const
chain_id_type
&
chain_id
)
{
digest_type
h
=
sig_digest
(
chain_id
);
signatures
.
push_back
(
key
.
sign_compact
(
h
));
signatures
.
push_back
(
key
.
sign_compact
(
sig_digest
(
chain_id
)));
return
signatures
.
back
();
}
signature_type
eos
::
chain
::
SignedTransaction
::
sign
(
const
private_key_type
&
key
,
const
chain_id_type
&
chain_id
)
const
{
digest_type
::
encoder
enc
;
fc
::
raw
::
pack
(
enc
,
chain_id
);
fc
::
raw
::
pack
(
enc
,
static_cast
<
const
types
::
Transaction
&>
(
*
this
)
);
return
key
.
sign_compact
(
enc
.
result
());
return
key
.
sign_compact
(
sig_digest
(
chain_id
));
}
void
SignedTransaction
::
set_reference_block
(
const
block_id_type
&
reference_block
)
{
...
...
@@ -74,17 +72,13 @@ bool SignedTransaction::verify_reference_block(const block_id_type& reference_bl
flat_set
<
public_key_type
>
SignedTransaction
::
get_signature_keys
(
const
chain_id_type
&
chain_id
)
const
{
try
{
auto
d
=
sig_digest
(
chain_id
);
flat_set
<
public_key_type
>
result
;
for
(
const
auto
&
sig
:
signatures
)
{
EOS_ASSERT
(
result
.
insert
(
fc
::
ecc
::
public_key
(
sig
,
d
)
).
second
,
tx_duplicate_sig
,
"Duplicate Signature detected"
);
}
return
result
;
}
FC_CAPTURE_AND_RETHROW
()
}
using
boost
::
adaptors
::
transformed
;
auto
SigToKey
=
transformed
([
digest
=
sig_digest
(
chain_id
)](
const
fc
::
ecc
::
compact_signature
&
signature
)
{
return
public_key_type
(
fc
::
ecc
::
public_key
(
signature
,
digest
));
});
auto
keyRange
=
signatures
|
SigToKey
;
return
{
keyRange
.
begin
(),
keyRange
.
end
()};
}
FC_CAPTURE_AND_RETHROW
()
}
eos
::
chain
::
digest_type
SignedTransaction
::
merkle_digest
()
const
{
digest_type
::
encoder
enc
;
...
...
libraries/native_contract/system_contract.cpp
浏览文件 @
40544bf7
#include <eos/native_contract/system_contract.hpp>
#include <eos/chain/message_handling_contexts.hpp>
#include <eos/chain/permission_object.hpp>
#include <eos/chain/account_object.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/chain/global_property_object.hpp>
...
...
@@ -50,9 +51,9 @@ void validate_system_newaccount(message_validate_context& context) {
EOS_ASSERT
(
context
.
msg
.
has_notify
(
config
::
StakedBalanceContractName
),
message_validate_exception
,
"Must notify Staked Balance Contract (${name})"
,
(
"name"
,
config
::
StakedBalanceContractName
));
EOS_ASSERT
(
eos
::
validate
(
create
.
owner
),
message_validate_exception
,
"Invalid owner authority"
);
EOS_ASSERT
(
eos
::
validate
(
create
.
active
),
message_validate_exception
,
"Invalid active authority"
);
EOS_ASSERT
(
eos
::
validate
(
create
.
recovery
),
message_validate_exception
,
"Invalid recovery authority"
);
EOS_ASSERT
(
validate
(
create
.
owner
),
message_validate_exception
,
"Invalid owner authority"
);
EOS_ASSERT
(
validate
(
create
.
active
),
message_validate_exception
,
"Invalid active authority"
);
EOS_ASSERT
(
validate
(
create
.
recovery
),
message_validate_exception
,
"Invalid recovery authority"
);
}
void
precondition_system_newaccount
(
precondition_validate_context
&
context
)
{
...
...
plugins/net_plugin/include/eos/net_plugin/net_plugin.hpp
浏览文件 @
40544bf7
...
...
@@ -18,6 +18,8 @@ namespace eos {
void
plugin_startup
();
void
plugin_shutdown
();
void
broadcast_block
(
const
chain
::
signed_block
&
sb
);
private:
std
::
unique_ptr
<
class
net_plugin_impl
>
my
;
};
...
...
plugins/net_plugin/net_plugin.cpp
浏览文件 @
40544bf7
...
...
@@ -3,6 +3,7 @@
#include <eos/net_plugin/net_plugin.hpp>
#include <eos/net_plugin/protocol.hpp>
#include <eos/chain/chain_controller.hpp>
#include <eos/chain/exceptions.hpp>
#include <fc/network/ip.hpp>
#include <fc/io/raw.hpp>
...
...
@@ -42,7 +43,7 @@ struct node_transaction_state {
struct
transaction_state
{
transaction_id_type
id
;
bool
is_known_by_peer
=
false
;
///< true if we sent or received this trx to this peer or received notice from peer
bool
is_noticed_to_peer
=
false
;
///< have we sent peer no
itce we know it (true if we re
eive from this peer)
bool
is_noticed_to_peer
=
false
;
///< have we sent peer no
tice we know it (true if we rec
eive from this peer)
uint32_t
block_num
=
-
1
;
///< the block number the transaction was included in
time_point
validated_time
;
///< infinity for unvalidated
time_point
requested_time
;
/// incase we fetch large trx
...
...
@@ -119,8 +120,12 @@ public:
out_queue
.
push_back
(
m
);
if
(
out_queue
.
size
()
==
1
)
send_next_message
();
else
{
dlog
(
"send: out_queue size = ${s}"
,
(
"s"
,
out_queue
.
size
()));
}
}
void
send_next_message
()
{
if
(
!
out_queue
.
size
()
)
{
if
(
out_sync_state
.
size
()
>
0
)
{
...
...
@@ -140,7 +145,6 @@ public:
boost
::
asio
::
async_write
(
*
socket
,
boost
::
asio
::
buffer
(
buffer
.
data
(),
buffer
.
size
()
),
[
this
,
buf
=
std
::
move
(
buffer
)](
boost
::
system
::
error_code
ec
,
std
::
size_t
bytes_transferred
)
{
ilog
(
"write message handler..."
);
if
(
ec
)
{
elog
(
"Error sending message: ${msg}"
,
(
"msg"
,
ec
.
message
()
)
);
}
else
{
...
...
@@ -152,7 +156,6 @@ public:
void
write_block_backlog
(
)
{
try
{
ilog
(
"write loop sending backlog "
);
if
(
out_sync_state
.
size
()
>
0
)
{
chain_controller
&
cc
=
app
().
find_plugin
<
chain_plugin
>
()
->
chain
();
auto
ss
=
out_sync_state
.
begin
();
...
...
@@ -160,6 +163,7 @@ public:
num
<=
ss
->
end_block
;
num
++
)
{
fc
::
optional
<
signed_block
>
sb
=
cc
.
fetch_block_by_number
(
num
);
if
(
sb
)
{
dlog
(
"write backlog, block #${num}"
,(
"num"
,
num
));
send
(
*
sb
);
}
ss
.
get_node
()
->
value
().
last
=
num
;
...
...
@@ -194,19 +198,20 @@ class net_plugin_impl {
chain_plugin
*
chain_plug
;
void
connect
(
const
string
&
ep
)
{
auto
host
=
ep
.
substr
(
0
,
ep
.
find
(
':'
)
);
auto
port
=
ep
.
substr
(
host
.
size
()
+
1
,
host
.
size
()
);
void
connect
(
const
string
&
peer_addr
)
{
auto
host
=
peer_addr
.
substr
(
0
,
peer_addr
.
find
(
':'
)
);
auto
port
=
peer_addr
.
substr
(
host
.
size
()
+
1
,
host
.
size
()
);
idump
((
host
)(
port
));
auto
resolver
=
std
::
make_shared
<
tcp
::
resolver
>
(
std
::
ref
(
app
().
get_io_service
()
)
);
tcp
::
resolver
::
query
query
(
tcp
::
v4
(),
host
.
c_str
(),
port
.
c_str
()
);
// Note: need to add support for IPv6 too
resolver
->
async_resolve
(
query
,
[
resolver
,
ep
,
this
](
const
boost
::
system
::
error_code
&
err
,
tcp
::
resolver
::
iterator
endpoint_itr
){
[
resolver
,
peer_addr
,
this
](
const
boost
::
system
::
error_code
&
err
,
tcp
::
resolver
::
iterator
endpoint_itr
){
if
(
!
err
)
{
connect
(
resolver
,
endpoint_itr
);
}
else
{
elog
(
"Unable to resolve ${
ep}: ${error}"
,
(
"ep"
,
ep
)(
"error"
,
err
.
message
()
)
);
elog
(
"Unable to resolve ${
peer_addr}: ${error}"
,
(
"peer_addr"
,
peer_addr
)(
"error"
,
err
.
message
()
)
);
}
});
}
...
...
@@ -271,12 +276,21 @@ class net_plugin_impl {
hello
->
os
=
"other"
;
#endif
hello
->
agent
=
user_agent_name
;
update_handshake
();
}
void
update_handshake
()
{
hello
->
last_irreversible_block_id
=
chain_plug
->
chain
().
get_block_id_for_num
(
hello
->
last_irreversible_block_num
=
chain_plug
->
chain
().
last_irreversible_block_num
());
try
{
hello
->
last_irreversible_block_id
=
chain_plug
->
chain
().
get_block_id_for_num
(
hello
->
last_irreversible_block_num
=
chain_plug
->
chain
().
last_irreversible_block_num
());
ilog
(
"update_handshake my libnum = ${n}"
,(
"n"
,
hello
->
last_irreversible_block_num
));
}
catch
(
const
unknown_block_exception
&
ex
)
{
hello
->
last_irreversible_block_id
=
fc
::
sha256
::
hash
(
0
);
hello
->
last_irreversible_block_num
=
0
;
ilog
(
"update_handshake my libnum = ${n}"
,(
"n"
,
hello
->
last_irreversible_block_num
));
}
}
void
start_session
(
connection
*
con
)
{
...
...
@@ -327,7 +341,14 @@ class net_plugin_impl {
);
}
void
handle_message
(
connection
&
c
,
handshake_message
&
msg
)
{
template
<
typename
T
>
void
send_all
(
const
T
&
msg
)
{
for
(
auto
&
c
:
connections
)
{
c
->
send
(
msg
);
}
}
void
handle_message
(
connection
&
c
,
const
handshake_message
&
msg
)
{
if
(
!
hello
)
{
init_handshake
();
}
...
...
@@ -349,6 +370,7 @@ class net_plugin_impl {
}
chain_controller
&
cc
=
chain_plug
->
chain
();
uint32_t
head
=
cc
.
head_block_num
();
ilog
(
"My head block = ${h} their lib = ${lib}"
,
(
"h"
,
head
)(
"lib"
,
msg
.
last_irreversible_block_num
));
if
(
msg
.
last_irreversible_block_num
>
head
)
{
uint32_t
delta
=
msg
.
last_irreversible_block_num
-
head
;
uint32_t
count
=
connections
.
size
();
...
...
@@ -373,47 +395,68 @@ class net_plugin_impl {
}
void
handle_message
(
connection
&
c
,
peer_message
&
msg
)
{
void
handle_message
(
connection
&
c
,
const
peer_message
&
msg
)
{
ilog
(
"got a peer message"
);
}
void
handle_message
(
connection
&
c
,
notice_message
&
msg
)
{
void
handle_message
(
connection
&
c
,
const
notice_message
&
msg
)
{
ilog
(
"got a notice message"
);
}
void
handle_message
(
connection
&
c
,
sync_request_message
&
msg
)
{
void
handle_message
(
connection
&
c
,
const
sync_request_message
&
msg
)
{
ilog
(
"got a sync request message for blocks ${s} to ${e}"
,
(
"s"
,
msg
.
start_block
)(
"e"
,
msg
.
end_block
));
sync_state
req
=
{
msg
.
start_block
,
msg
.
end_block
,
0
,
time_point
::
now
()};
c
.
out_sync_state
.
insert
(
req
);
c
.
write_block_backlog
();
}
void
handle_message
(
connection
&
c
,
block_summary_message
&
msg
)
{
void
handle_message
(
connection
&
c
,
const
block_summary_message
&
msg
)
{
ilog
(
"got a block summary message"
);
}
void
handle_message
(
connection
&
c
,
SignedTransaction
&
msg
)
{
void
handle_message
(
connection
&
c
,
const
SignedTransaction
&
msg
)
{
ilog
(
"got a SignedTransacton"
);
chain_plug
->
accept_transaction
(
msg
);
}
void
handle_message
(
connection
&
c
,
signed_block
&
msg
)
{
void
handle_message
(
connection
&
c
,
const
signed_block
&
msg
)
{
uint32_t
bn
=
msg
.
block_num
();
i
log
(
"got a signed_block, num = ${n}"
,
(
"n"
,
bn
));
d
log
(
"got a signed_block, num = ${n}"
,
(
"n"
,
bn
));
chain_controller
&
cc
=
chain_plug
->
chain
();
if
(
cc
.
is_known_block
(
msg
.
id
()))
{
i
log
(
"block id ${id} is known"
,
(
"id"
,
msg
.
id
())
);
d
log
(
"block id ${id} is known"
,
(
"id"
,
msg
.
id
())
);
return
;
}
uint32_t
num
=
msg
.
block_num
();
bool
syncing
=
false
;
for
(
auto
&
ss
:
c
.
in_sync_state
)
{
if
(
num
>=
ss
.
end_block
)
{
continue
;
}
const_cast
<
sync_state
&>
(
ss
).
last
=
num
;
syncing
=
true
;
break
;
}
// TODO: add block to global state
if
(
!
syncing
)
{
try
{
block_id_type
id
=
cc
.
get_block_id_for_num
(
num
-
1
);
dlog
(
"got the prevous block id = ${id}"
,(
"id"
,
id
));
}
catch
(
const
unknown_block_exception
&
ex
)
{
uint32_t
head
=
cc
.
head_block_num
();
dlog
(
"block num ${n} is not known, head = ${h}"
,(
"n"
,(
num
-
1
))(
"h"
,
head
));
sync_state
req
=
{
head
+
1
,
num
-
1
,
0
,
time_point
::
now
()
};
c
.
in_sync_state
.
insert
(
req
);
sync_request_message
srm
=
{
req
.
start_block
,
req
.
end_block
};
c
.
send
(
srm
);
syncing
=
true
;
}
}
chain_plug
->
accept_block
(
msg
,
syncing
);
}
...
...
@@ -422,37 +465,8 @@ class net_plugin_impl {
connection
&
c
;
msgHandler
(
net_plugin_impl
&
imp
,
connection
&
conn
)
:
impl
(
imp
),
c
(
conn
)
{}
void
operator
()(
handshake_message
&
msg
)
{
impl
.
handle_message
(
c
,
msg
);
}
void
operator
()(
peer_message
&
msg
)
{
impl
.
handle_message
(
c
,
msg
);
}
void
operator
()(
notice_message
&
msg
)
{
impl
.
handle_message
(
c
,
msg
);
}
void
operator
()(
sync_request_message
&
msg
)
{
impl
.
handle_message
(
c
,
msg
);
}
void
operator
()(
block_summary_message
&
msg
)
{
impl
.
handle_message
(
c
,
msg
);
}
void
operator
()(
SignedTransaction
&
msg
)
{
impl
.
handle_message
(
c
,
msg
);
}
void
operator
()(
signed_block
&
msg
)
template
<
typename
T
>
void
operator
()(
const
T
&
msg
)
const
{
impl
.
handle_message
(
c
,
msg
);
}
...
...
@@ -507,6 +521,7 @@ void net_plugin::set_program_options( options_description& cli, options_descript
(
"listen-endpoint"
,
bpo
::
value
<
string
>
()
->
default_value
(
"127.0.0.1:9876"
),
"The local IP address and port to listen for incoming connections."
)
(
"remote-endpoint"
,
bpo
::
value
<
vector
<
string
>
>
()
->
composing
(),
"The IP address and port of a remote peer to sync with."
)
(
"public-endpoint"
,
bpo
::
value
<
string
>
()
->
default_value
(
"0.0.0.0:9876"
),
"The public IP address and port that should be advertized to peers."
)
(
"agent-name"
,
bpo
::
value
<
string
>
()
->
default_value
(
"EOS Test Agent"
),
"The name supplied to identify this node amongst the peers."
)
;
}
...
...
@@ -524,14 +539,16 @@ void net_plugin::plugin_initialize( const variables_map& options ) {
if
(
options
.
count
(
"remote-endpoint"
)
)
{
my
->
seed_nodes
=
options
.
at
(
"remote-endpoint"
).
as
<
vector
<
string
>
>
();
}
my
->
user_agent_name
=
"EOS Test Agent"
;
if
(
options
.
count
(
"agent-name"
))
{
my
->
user_agent_name
=
options
.
at
(
"agent-name"
).
as
<
string
>
();
}
my
->
chain_plug
=
app
().
find_plugin
<
chain_plugin
>
();
}
void
net_plugin
::
plugin_startup
()
{
// boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
if
(
my
->
acceptor
)
{
my
->
acceptor
->
open
(
my
->
listen_endpoint
.
protocol
());
my
->
acceptor
->
set_option
(
tcp
::
acceptor
::
reuse_address
(
true
));
my
->
acceptor
->
bind
(
my
->
listen_endpoint
);
...
...
@@ -569,4 +586,8 @@ try {
ilog
(
"exit shutdown"
);
}
FC_CAPTURE_AND_RETHROW
()
}
void
net_plugin
::
broadcast_block
(
const
chain
::
signed_block
&
sb
)
{
my
->
send_all
(
sb
);
}
}
plugins/producer_plugin/CMakeLists.txt
浏览文件 @
40544bf7
...
...
@@ -5,7 +5,7 @@ add_library( producer_plugin
${
HEADERS
}
)
target_link_libraries
(
producer_plugin chain_plugin appbase eos_chain eos_utilities
)
target_link_libraries
(
producer_plugin
net_plugin
chain_plugin appbase eos_chain eos_utilities
)
target_include_directories
(
producer_plugin
PUBLIC
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include"
)
...
...
plugins/producer_plugin/producer_plugin.cpp
浏览文件 @
40544bf7
...
...
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include <eos/producer_plugin/producer_plugin.hpp>
#include <eos/net_plugin/net_plugin.hpp>
#include <eos/chain/producer_object.hpp>
...
...
@@ -304,7 +305,7 @@ block_production_condition::block_production_condition_enum producer_plugin_impl
);
capture
(
"n"
,
block
.
block_num
())(
"t"
,
block
.
timestamp
)(
"c"
,
now
);
// app().get_plugin<p2p
_plugin>().broadcast_block(block);
app
().
get_plugin
<
net
_plugin
>
().
broadcast_block
(
block
);
return
block_production_condition
::
produced
;
}
...
...
tests/CMakeLists.txt
浏览文件 @
40544bf7
...
...
@@ -9,3 +9,7 @@ endif()
file
(
GLOB UNIT_TESTS
"tests/*.cpp"
)
add_executable
(
chain_test
${
UNIT_TESTS
}
${
COMMON_SOURCES
}
)
target_link_libraries
(
chain_test eos_native_contract eos_chain chainbase eos_utilities eos_egenesis_none fc
${
PLATFORM_SPECIFIC_LIBS
}
)
file
(
GLOB SLOW_TESTS
"slow_tests/*.cpp"
)
add_executable
(
slow_test
${
SLOW_TESTS
}
${
COMMON_SOURCES
}
)
target_link_libraries
(
slow_test eos_native_contract eos_chain chainbase eos_utilities eos_egenesis_none fc
${
PLATFORM_SPECIFIC_LIBS
}
)
tests/
tests
/main.cpp
→
tests/
common
/main.cpp
浏览文件 @
40544bf7
文件已移动
tests/slow_tests/slow_tests.cpp
0 → 100644
浏览文件 @
40544bf7
此差异已折叠。
点击以展开。
tests/tests/wast/simplecoin.cpp
→
tests/
slow_
tests/wast/simplecoin.cpp
浏览文件 @
40544bf7
文件已移动
tests/tests/wast/simplecoin.wast
→
tests/
slow_
tests/wast/simplecoin.wast
浏览文件 @
40544bf7
文件已移动
tests/tests/block_tests.cpp
浏览文件 @
40544bf7
此差异已折叠。
点击以展开。
tests/tests/misc_tests.cpp
浏览文件 @
40544bf7
#include <eos/chain/BlockchainConfiguration.hpp>
#include <eos/chain/authority.hpp>
#include <eos/utilities/rand.hpp>
...
...
@@ -72,9 +73,62 @@ BOOST_AUTO_TEST_CASE(deterministic_distributions)
rng
.
shuffle
(
nums
);
std
::
vector
<
int
>
c
{
1
,
0
,
2
};
BOOST_CHECK
(
std
::
equal
(
nums
.
begin
(),
nums
.
end
(),
c
.
begin
()));
}
FC_LOG_AND_RETHROW
()
}
BOOST_AUTO_TEST_CASE
(
authority_checker
)
{
try
{
#define KEY(x) auto x = fc::ecc::private_key::regenerate(fc::sha256::hash(#x)).get_public_key()
KEY
(
a
);
KEY
(
b
);
KEY
(
c
);
auto
GetNullAuthority
=
[](
auto
){
return
Authority
();};
Authority
A
(
2
,
{{
a
,
1
},
{
b
,
1
}},
{});
BOOST_CHECK
(
MakeAuthorityChecker
(
GetNullAuthority
,
{
a
,
b
}).
satisfied
(
A
));
BOOST_CHECK
(
MakeAuthorityChecker
(
GetNullAuthority
,
{
a
,
b
,
c
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetNullAuthority
,
{
a
,
c
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetNullAuthority
,
{
b
,
c
}).
satisfied
(
A
));
A
=
Authority
(
3
,
{{
a
,
1
},{
b
,
1
},{
c
,
1
}},
{});
BOOST_CHECK
(
MakeAuthorityChecker
(
GetNullAuthority
,
{
c
,
b
,
a
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetNullAuthority
,
{
a
,
b
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetNullAuthority
,
{
a
,
c
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetNullAuthority
,
{
b
,
c
}).
satisfied
(
A
));
A
=
Authority
(
1
,
{{
a
,
1
},
{
b
,
1
}},
{});
BOOST_CHECK
(
MakeAuthorityChecker
(
GetNullAuthority
,
{
a
}).
satisfied
(
A
));
BOOST_CHECK
(
MakeAuthorityChecker
(
GetNullAuthority
,
{
b
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetNullAuthority
,
{
c
}).
satisfied
(
A
));
A
=
Authority
(
1
,
{{
a
,
2
},
{
b
,
1
}},
{});
BOOST_CHECK
(
MakeAuthorityChecker
(
GetNullAuthority
,
{
a
}).
satisfied
(
A
));
BOOST_CHECK
(
MakeAuthorityChecker
(
GetNullAuthority
,
{
b
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetNullAuthority
,
{
c
}).
satisfied
(
A
));
auto
GetCAuthority
=
[
c
](
auto
){
return
Authority
(
1
,
{{
c
,
1
}},
{});};
A
=
Authority
(
2
,
{{
a
,
2
},
{
b
,
1
}},
{{{
"hello"
,
"world"
},
1
}});
BOOST_CHECK
(
MakeAuthorityChecker
(
GetCAuthority
,
{
a
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetCAuthority
,
{
b
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetCAuthority
,
{
c
}).
satisfied
(
A
));
BOOST_CHECK
(
MakeAuthorityChecker
(
GetCAuthority
,
{
b
,
c
}).
satisfied
(
A
));
A
=
Authority
(
2
,
{{
a
,
1
},
{
b
,
1
}},
{{{
"hello"
,
"world"
},
1
}});
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetCAuthority
,
{
a
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetCAuthority
,
{
b
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetCAuthority
,
{
c
}).
satisfied
(
A
));
BOOST_CHECK
(
MakeAuthorityChecker
(
GetCAuthority
,
{
a
,
b
}).
satisfied
(
A
));
BOOST_CHECK
(
MakeAuthorityChecker
(
GetCAuthority
,
{
b
,
c
}).
satisfied
(
A
));
BOOST_CHECK
(
MakeAuthorityChecker
(
GetCAuthority
,
{
a
,
c
}).
satisfied
(
A
));
A
=
Authority
(
2
,
{{
a
,
1
},
{
b
,
1
}},
{{{
"hello"
,
"world"
},
2
}});
BOOST_CHECK
(
MakeAuthorityChecker
(
GetCAuthority
,
{
a
,
b
}).
satisfied
(
A
));
BOOST_CHECK
(
MakeAuthorityChecker
(
GetCAuthority
,
{
c
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetCAuthority
,
{
a
}).
satisfied
(
A
));
BOOST_CHECK
(
!
MakeAuthorityChecker
(
GetCAuthority
,
{
b
}).
satisfied
(
A
));
}
FC_LOG_AND_RETHROW
()
}
BOOST_AUTO_TEST_SUITE_END
()
...
...
tests/tests/native_contract_tests.cpp
浏览文件 @
40544bf7
...
...
@@ -2,7 +2,7 @@
#include <eos/chain/chain_controller.hpp>
#include <eos/chain/exceptions.hpp>
#include <eos/chain/
account
_object.hpp>
#include <eos/chain/
permission
_object.hpp>
#include <eos/chain/key_value_object.hpp>
#include <eos/native_contract/producer_objects.hpp>
...
...
@@ -76,70 +76,6 @@ BOOST_FIXTURE_TEST_CASE(create_account, testing_fixture)
}
}
FC_LOG_AND_RETHROW
()
}
// Verify that staking and unstaking works
BOOST_FIXTURE_TEST_CASE
(
stake
,
testing_fixture
)
{
try
{
// Create account sam with default balance of 100, and stake 55 of it
Make_Blockchain
(
chain
);
Make_Account
(
chain
,
sam
);
Transfer_Asset
(
chain
,
inita
,
sam
,
Asset
(
55
)
);
// MakeAccount should start sam out with some staked balance
BOOST_REQUIRE_EQUAL
(
chain
.
get_staked_balance
(
"sam"
),
Asset
(
100
).
amount
);
Stake_Asset
(
chain
,
sam
,
Asset
(
55
).
amount
);
// Check balances
BOOST_CHECK_EQUAL
(
chain
.
get_staked_balance
(
"sam"
),
Asset
(
155
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_unstaking_balance
(
"sam"
),
Asset
(
0
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_liquid_balance
(
"sam"
),
Asset
(
0
).
amount
);
chain
.
produce_blocks
();
// Start unstaking 20, check balances
BOOST_CHECK_THROW
(
Begin_Unstake_Asset
(
chain
,
sam
,
Asset
(
156
).
amount
),
chain
::
message_precondition_exception
);
Begin_Unstake_Asset
(
chain
,
sam
,
Asset
(
20
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_staked_balance
(
"sam"
),
Asset
(
135
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_unstaking_balance
(
"sam"
),
Asset
(
20
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_liquid_balance
(
"sam"
),
Asset
(
0
).
amount
);
// Make sure we can't liquidate early
BOOST_CHECK_THROW
(
Finish_Unstake_Asset
(
chain
,
sam
,
Asset
(
10
).
amount
),
chain
::
message_precondition_exception
);
// Fast forward to when we can liquidate
wlog
(
"Hang on, this will take a minute..."
);
chain
.
produce_blocks
(
config
::
StakedBalanceCooldownSeconds
/
config
::
BlockIntervalSeconds
+
1
);
BOOST_CHECK_THROW
(
Finish_Unstake_Asset
(
chain
,
sam
,
Asset
(
21
).
amount
),
chain
::
message_precondition_exception
);
BOOST_CHECK_EQUAL
(
chain
.
get_staked_balance
(
"sam"
),
Asset
(
135
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_unstaking_balance
(
"sam"
),
Asset
(
20
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_liquid_balance
(
"sam"
),
Asset
(
0
).
amount
);
// Liquidate 10 of the 20 unstaking and check balances
Finish_Unstake_Asset
(
chain
,
sam
,
Asset
(
10
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_staked_balance
(
"sam"
),
Asset
(
135
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_unstaking_balance
(
"sam"
),
Asset
(
10
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_liquid_balance
(
"sam"
),
Asset
(
10
).
amount
);
// Liquidate 2 of the 10 left unstaking and check balances
Finish_Unstake_Asset
(
chain
,
sam
,
Asset
(
2
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_staked_balance
(
"sam"
),
Asset
(
135
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_unstaking_balance
(
"sam"
),
Asset
(
8
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_liquid_balance
(
"sam"
),
Asset
(
12
).
amount
);
// Ignore the 8 left in unstaking, and begin unstaking 5, which should restake the 8, and start over unstaking 5
Begin_Unstake_Asset
(
chain
,
sam
,
Asset
(
5
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_staked_balance
(
"sam"
),
Asset
(
138
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_unstaking_balance
(
"sam"
),
Asset
(
5
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_liquid_balance
(
"sam"
),
Asset
(
12
).
amount
);
// Begin unstaking 20, which should only deduct 15 from staked, since 5 was already in unstaking
Begin_Unstake_Asset
(
chain
,
sam
,
Asset
(
20
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_staked_balance
(
"sam"
),
Asset
(
123
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_unstaking_balance
(
"sam"
),
Asset
(
20
).
amount
);
BOOST_CHECK_EQUAL
(
chain
.
get_liquid_balance
(
"sam"
),
Asset
(
12
).
amount
);
}
FC_LOG_AND_RETHROW
()
}
// Simple test to verify a simple transfer transaction works
BOOST_FIXTURE_TEST_CASE
(
transfer
,
testing_fixture
)
{
try
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录