Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
82cde96d
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,发现更多精彩内容 >>
提交
82cde96d
编写于
4月 04, 2018
作者:
A
arhag
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into enforce-new-transaction-header-parameters
上级
82ce671c
266accd8
变更
27
显示空白变更内容
内联
并排
Showing
27 changed file
with
283 addition
and
67 deletion
+283
-67
.gitignore
.gitignore
+0
-1
contracts/eosio.system/native.hpp
contracts/eosio.system/native.hpp
+3
-3
contracts/eosiolib/types.h
contracts/eosiolib/types.h
+2
-0
libraries/chain/apply_context.cpp
libraries/chain/apply_context.cpp
+1
-19
libraries/chain/chain_controller.cpp
libraries/chain/chain_controller.cpp
+7
-1
libraries/chain/contracts/abi_serializer.cpp
libraries/chain/contracts/abi_serializer.cpp
+1
-0
libraries/chain/contracts/chain_initializer.cpp
libraries/chain/contracts/chain_initializer.cpp
+2
-2
libraries/chain/contracts/eosio_contract.cpp
libraries/chain/contracts/eosio_contract.cpp
+16
-15
libraries/chain/include/eosio/chain/apply_context.hpp
libraries/chain/include/eosio/chain/apply_context.hpp
+1
-3
libraries/chain/include/eosio/chain/chain_controller.hpp
libraries/chain/include/eosio/chain/chain_controller.hpp
+2
-1
libraries/chain/include/eosio/chain/contracts/types.hpp
libraries/chain/include/eosio/chain/contracts/types.hpp
+2
-2
libraries/chain/include/eosio/chain/name.hpp
libraries/chain/include/eosio/chain/name.hpp
+1
-0
libraries/chain/include/eosio/chain/transaction.hpp
libraries/chain/include/eosio/chain/transaction.hpp
+3
-4
libraries/chain/wasm_interface.cpp
libraries/chain/wasm_interface.cpp
+4
-4
libraries/utilities/CMakeLists.txt
libraries/utilities/CMakeLists.txt
+1
-1
plugins/chain_api_plugin/CMakeLists.txt
plugins/chain_api_plugin/CMakeLists.txt
+1
-1
plugins/chain_plugin/CMakeLists.txt
plugins/chain_plugin/CMakeLists.txt
+1
-1
plugins/eosio-make_new_plugin.sh
plugins/eosio-make_new_plugin.sh
+1
-1
plugins/http_plugin/CMakeLists.txt
plugins/http_plugin/CMakeLists.txt
+1
-1
plugins/producer_plugin/CMakeLists.txt
plugins/producer_plugin/CMakeLists.txt
+1
-1
plugins/wallet_api_plugin/CMakeLists.txt
plugins/wallet_api_plugin/CMakeLists.txt
+1
-1
plugins/wallet_plugin/CMakeLists.txt
plugins/wallet_plugin/CMakeLists.txt
+1
-1
tests/CMakeLists.txt
tests/CMakeLists.txt
+1
-1
tests/chain_tests/delay_tests.cpp
tests/chain_tests/delay_tests.cpp
+8
-3
tests/tests/special_accounts_tests.cpp
tests/tests/special_accounts_tests.cpp
+82
-0
tests/wasm_tests/test_softfloat_wasts.hpp
tests/wasm_tests/test_softfloat_wasts.hpp
+35
-0
tests/wasm_tests/wasm_tests.cpp
tests/wasm_tests/wasm_tests.cpp
+104
-0
未找到文件。
.gitignore
浏览文件 @
82cde96d
...
...
@@ -29,7 +29,6 @@ libraries/egenesis/egenesis_full.cpp
libraries/egenesis/embed_genesis
libraries/types/type_generator
libraries/types/types_test
libraries/types/include/eos/types/generated.hpp
libraries/wallet/Doxyfile
libraries/wallet/api_documentation.cpp
...
...
contracts/eosio.system/native.hpp
浏览文件 @
82cde96d
...
...
@@ -190,9 +190,9 @@ namespace eosiosystem {
}
ACTION
(
SystemAccount
,
canceldelay
)
{
uint32_t
sender
_id
;
transaction_id_type
trx
_id
;
EOSLIB_SERIALIZE
(
canceldelay
,
(
sender
_id
)
)
EOSLIB_SERIALIZE
(
canceldelay
,
(
trx
_id
)
)
};
static
void
on
(
const
canceldelay
&
)
{
...
...
contracts/eosiolib/types.h
浏览文件 @
82cde96d
...
...
@@ -59,6 +59,8 @@ struct fixed_string16 {
char
str
[
16
];
};
typedef
struct
checksum256
transaction_id_type
;
typedef
struct
fixed_string16
field_name
;
struct
fixed_string32
{
...
...
libraries/chain/apply_context.cpp
浏览文件 @
82cde96d
...
...
@@ -303,7 +303,7 @@ void apply_context::execute_deferred( deferred_transaction&& trx ) {
}
FC_CAPTURE_AND_RETHROW
((
trx
));
}
void
apply_context
::
cancel_deferred
(
uint128_t
sender_id
)
{
void
apply_context
::
cancel_deferred
(
const
uint128_t
&
sender_id
)
{
results
.
deferred_transaction_requests
.
push_back
(
deferred_reference
(
receiver
,
sender_id
));
}
...
...
@@ -428,24 +428,6 @@ int apply_context::get_context_free_data( uint32_t index, char* buffer, size_t b
return
s
;
}
uint32_t
apply_context
::
get_next_sender_id
()
{
const
uint64_t
id
=
N
(
config
::
eosio_auth_scope
);
const
auto
table
=
N
(
deferred
.
seq
);
const
auto
payer
=
config
::
system_account_name
;
const
auto
iter
=
db_find_i64
(
config
::
system_account_name
,
config
::
eosio_auth_scope
,
table
,
id
);
if
(
iter
==
-
1
)
{
const
uint32_t
next_serial
=
1
;
db_store_i64
(
config
::
system_account_name
,
config
::
eosio_auth_scope
,
table
,
payer
,
id
,
(
const
char
*
)
&
next_serial
,
sizeof
(
next_serial
));
return
0
;
}
uint32_t
next_serial
=
0
;
db_get_i64
(
iter
,
(
char
*
)
&
next_serial
,
sizeof
(
next_serial
));
const
auto
result
=
next_serial
++
;
db_update_i64
(
iter
,
payer
,
(
const
char
*
)
&
next_serial
,
sizeof
(
next_serial
));
return
result
;
}
int
apply_context
::
db_store_i64
(
uint64_t
scope
,
uint64_t
table
,
const
account_name
&
payer
,
uint64_t
id
,
const
char
*
buffer
,
size_t
buffer_size
)
{
return
db_store_i64
(
receiver
,
scope
,
table
,
payer
,
id
,
buffer
,
buffer_size
);
}
...
...
libraries/chain/chain_controller.cpp
浏览文件 @
82cde96d
...
...
@@ -311,6 +311,7 @@ transaction_trace chain_controller::_push_transaction(const packed_transaction&
if
(
mtrx
.
delay
.
count
()
==
0
)
{
result
=
_push_transaction
(
std
::
move
(
mtrx
)
);
}
else
{
result
=
wrap_transaction_processing
(
std
::
move
(
mtrx
),
[
this
](
transaction_metadata
&
meta
)
{
return
delayed_transaction_processing
(
meta
);
}
);
}
...
...
@@ -350,6 +351,11 @@ transaction_trace chain_controller::_push_transaction( transaction_metadata&& da
return
wrap_transaction_processing
(
move
(
data
),
process_apply_transaction
);
}
FC_CAPTURE_AND_RETHROW
(
)
}
uint128_t
chain_controller
::
transaction_id_to_sender_id
(
const
transaction_id_type
&
tid
)
const
{
fc
::
uint128_t
_id
(
tid
.
_hash
[
3
],
tid
.
_hash
[
2
]);
return
(
unsigned
__int128
)
_id
;
}
transaction_trace
chain_controller
::
delayed_transaction_processing
(
const
transaction_metadata
&
mtrx
)
{
try
{
transaction_trace
result
(
mtrx
.
id
);
...
...
@@ -386,7 +392,7 @@ transaction_trace chain_controller::delayed_transaction_processing( const transa
FC_ASSERT
(
!
payer
.
empty
(),
"Failed to find a payer for delayed transaction!"
);
deferred_transaction
dtrx
(
context
.
get_next_sender_id
(
),
config
::
system_account_name
,
payer
,
execute_after
,
trx
);
deferred_transaction
dtrx
(
transaction_id_to_sender_id
(
trx
.
id
()
),
config
::
system_account_name
,
payer
,
execute_after
,
trx
);
FC_ASSERT
(
dtrx
.
execute_after
<
dtrx
.
expiration
,
"transaction expires before it can execute"
);
result
.
deferred_transaction_requests
.
push_back
(
std
::
move
(
dtrx
));
...
...
libraries/chain/contracts/abi_serializer.cpp
浏览文件 @
82cde96d
...
...
@@ -71,6 +71,7 @@ namespace eosio { namespace chain { namespace contracts {
built_in_types
.
emplace
(
"checksum160"
,
pack_unpack
<
checksum160_type
>
());
built_in_types
.
emplace
(
"checksum256"
,
pack_unpack
<
checksum256_type
>
());
built_in_types
.
emplace
(
"checksum512"
,
pack_unpack
<
checksum512_type
>
());
built_in_types
.
emplace
(
"transaction_id_type"
,
pack_unpack
<
checksum256_type
>
());
built_in_types
.
emplace
(
"field_name"
,
pack_unpack
<
field_name
>
());
built_in_types
.
emplace
(
"fixed_string32"
,
pack_unpack
<
fixed_string32
>
());
built_in_types
.
emplace
(
"fixed_string16"
,
pack_unpack
<
fixed_string16
>
());
...
...
libraries/chain/contracts/chain_initializer.cpp
浏览文件 @
82cde96d
...
...
@@ -160,7 +160,7 @@ abi_def chain_initializer::eos_contract_abi(const abi_def& eosio_system_abi)
eos_abi
.
structs
.
emplace_back
(
struct_def
{
"canceldelay"
,
""
,
{
{
"
sender_id"
,
"uint32
"
},
{
"
trx_id"
,
"transaction_id_type
"
},
}
});
...
...
@@ -169,7 +169,7 @@ abi_def chain_initializer::eos_contract_abi(const abi_def& eosio_system_abi)
eos_abi
.
structs
.
emplace_back
(
struct_def
{
"pending_recovery"
,
""
,
{
{
"account"
,
"name"
},
{
"request_id"
,
"uint
32
"
},
{
"request_id"
,
"uint
128
"
},
{
"update"
,
"updateauth"
},
{
"memo"
,
"string"
}
}
...
...
libraries/chain/contracts/eosio_contract.cpp
浏览文件 @
82cde96d
...
...
@@ -481,8 +481,7 @@ void apply_eosio_postrecovery(apply_context& context) {
.
data
=
recover_act
.
data
},
update
);
uint32_t
request_id
=
context
.
get_next_sender_id
();
const
uint128_t
request_id
=
context
.
controller
.
transaction_id_to_sender_id
(
context
.
trx_meta
.
id
);
auto
record_data
=
mutable_variant_object
()
(
"account"
,
account
)
(
"request_id"
,
request_id
)
...
...
@@ -502,11 +501,11 @@ void apply_eosio_postrecovery(apply_context& context) {
context
.
execute_deferred
(
std
::
move
(
dtrx
));
auto
data
=
get_abi_serializer
().
variant_to_binary
(
"pending_recovery"
,
record_data
);
const
uint64_t
id
=
account
;
const
uint64_t
table
=
N
(
recovery
);
const
auto
payer
=
account
;
const
auto
iter
=
context
.
db_find_i64
(
config
::
system_account_name
,
account
,
table
,
id
);
if
(
iter
==
-
1
)
{
context
.
db_store_i64
(
account
,
table
,
payer
,
id
,
(
const
char
*
)
data
.
data
(),
data
.
size
());
...
...
@@ -543,7 +542,7 @@ void apply_eosio_passrecovery(apply_context& context) {
context
.
execute_inline
(
move
(
act
));
remove_pending_recovery
(
context
,
account
);
context
.
console_append_formatted
(
"Account ${account} successfully recoverd!
\n
"
,
mutable_variant_object
()(
"account"
,
account
));
context
.
console_append_formatted
(
"Account ${account} successfully recover
e
d!
\n
"
,
mutable_variant_object
()(
"account"
,
account
));
}
void
apply_eosio_vetorecovery
(
apply_context
&
context
)
{
...
...
@@ -556,7 +555,7 @@ void apply_eosio_vetorecovery(apply_context& context) {
FC_ASSERT
(
maybe_recovery
,
"No pending recovery found for account ${account}"
,
(
"account"
,
account
));
auto
recovery
=
*
maybe_recovery
;
context
.
cancel_deferred
(
recovery
[
"request_id"
].
as
<
uint
32
_t
>
());
context
.
cancel_deferred
(
recovery
[
"request_id"
].
as
<
uint
128
_t
>
());
remove_pending_recovery
(
context
,
account
);
context
.
console_append_formatted
(
"Recovery for account ${account} vetoed!
\n
"
,
mutable_variant_object
()(
"account"
,
account
));
...
...
@@ -564,12 +563,13 @@ void apply_eosio_vetorecovery(apply_context& context) {
void
apply_eosio_canceldelay
(
apply_context
&
context
)
{
auto
cancel
=
context
.
act
.
data_as
<
canceldelay
>
();
const
auto
sender_id
=
cancel
.
sender_id
;
const
auto
&
trx_id
=
cancel
.
trx_id
;
const
auto
&
generated_transaction_idx
=
context
.
controller
.
get_database
().
get_index
<
generated_transaction_multi_index
>
();
const
auto
&
generated_index
=
generated_transaction_idx
.
indices
().
get
<
by_
sender
_id
>
();
const
auto
&
itr
=
generated_index
.
lower_bound
(
boost
::
make_tuple
(
config
::
system_account_name
,
sender_id
)
);
FC_ASSERT
(
itr
!=
generated_index
.
end
()
&&
itr
->
sender
==
config
::
system_account_name
&&
itr
->
sender_id
==
sender
_id
,
"cannot cancel
sender_id=${sid}, there is no deferred transaction with that sender_id"
,(
"sid"
,
sender
_id
));
const
auto
&
generated_index
=
generated_transaction_idx
.
indices
().
get
<
by_
trx
_id
>
();
const
auto
&
itr
=
generated_index
.
lower_bound
(
trx_id
);
FC_ASSERT
(
itr
!=
generated_index
.
end
()
&&
itr
->
sender
==
config
::
system_account_name
&&
itr
->
trx_id
==
trx
_id
,
"cannot cancel
trx_id=${tid}, there is no deferred transaction with that transaction id"
,(
"tid"
,
trx
_id
));
auto
dtrx
=
fc
::
raw
::
unpack
<
deferred_transaction
>
(
itr
->
packed_trx
.
data
(),
itr
->
packed_trx
.
size
());
set
<
account_name
>
accounts
;
...
...
@@ -589,7 +589,8 @@ void apply_eosio_canceldelay(apply_context& context) {
FC_ASSERT
(
found
,
"canceldelay action must be signed with the
\"
active
\"
permission for one of the actors"
" provided in the authorizations on the original transaction"
);
context
.
cancel_deferred
(
sender_id
);
context
.
cancel_deferred
(
context
.
controller
.
transaction_id_to_sender_id
(
trx_id
));
}
}
}
}
// namespace eosio::chain::contracts
libraries/chain/include/eosio/chain/apply_context.hpp
浏览文件 @
82cde96d
...
...
@@ -471,7 +471,7 @@ class apply_context {
void
execute_inline
(
action
&&
a
);
void
execute_context_free_inline
(
action
&&
a
);
void
execute_deferred
(
deferred_transaction
&&
trx
);
void
cancel_deferred
(
uint128_t
sender_id
);
void
cancel_deferred
(
const
uint128_t
&
sender_id
);
/**
* @brief Require @ref account to have approved of this message
...
...
@@ -511,8 +511,6 @@ class apply_context {
const
bytes
&
get_packed_transaction
();
uint32_t
get_next_sender_id
();
const
chain_controller
&
controller
;
const
chainbase
::
database
&
db
;
///< database where state is stored
const
action
&
act
;
///< message being applied
...
...
libraries/chain/include/eosio/chain/chain_controller.hpp
浏览文件 @
82cde96d
...
...
@@ -92,6 +92,7 @@ namespace eosio { namespace chain {
transaction_trace
push_transaction
(
const
packed_transaction
&
trx
,
uint32_t
skip
=
skip_nothing
);
vector
<
transaction_trace
>
push_deferred_transactions
(
bool
flush
=
false
,
uint32_t
skip
=
skip_nothing
);
uint128_t
transaction_id_to_sender_id
(
const
transaction_id_type
&
tid
)
const
;
/**
* This signal is emitted after all operations and virtual operation for a
...
...
libraries/chain/include/eosio/chain/contracts/types.hpp
浏览文件 @
82cde96d
...
...
@@ -270,7 +270,7 @@ struct vetorecovery {
};
struct
canceldelay
{
uint128_t
sender
_id
;
transaction_id_type
trx
_id
;
static
account_name
get_account
()
{
return
config
::
system_account_name
;
...
...
@@ -300,4 +300,4 @@ FC_REFLECT( eosio::chain::contracts::unlinkauth , (account
FC_REFLECT
(
eosio
::
chain
::
contracts
::
postrecovery
,
(
account
)(
data
)(
memo
)
)
FC_REFLECT
(
eosio
::
chain
::
contracts
::
passrecovery
,
(
account
)
)
FC_REFLECT
(
eosio
::
chain
::
contracts
::
vetorecovery
,
(
account
)
)
FC_REFLECT
(
eosio
::
chain
::
contracts
::
canceldelay
,
(
sender
_id
)
)
FC_REFLECT
(
eosio
::
chain
::
contracts
::
canceldelay
,
(
trx
_id
)
)
libraries/chain/include/eosio/chain/name.hpp
浏览文件 @
82cde96d
...
...
@@ -90,6 +90,7 @@ namespace eosio { namespace chain {
operator
bool
()
const
{
return
value
;
}
operator
uint64_t
()
const
{
return
value
;
}
operator
unsigned
__int128
()
const
{
return
value
;
}
};
...
...
libraries/chain/include/eosio/chain/transaction.hpp
浏览文件 @
82cde96d
...
...
@@ -4,7 +4,6 @@
*/
#pragma once
#include <eosio/chain/types.hpp>
#include <numeric>
namespace
eosio
{
namespace
chain
{
...
...
@@ -229,7 +228,7 @@ namespace eosio { namespace chain {
uint128_t
sender_id
;
/// ID assigned by sender of generated, accessible via WASM api when executing normal or error
account_name
sender
;
/// receives error handler callback
account_name
payer
;
time_point_sec
execute_after
;
/// delayed exe
uc
tion
time_point_sec
execute_after
;
/// delayed exe
cu
tion
deferred_transaction
()
=
default
;
...
...
@@ -244,7 +243,7 @@ namespace eosio { namespace chain {
struct
deferred_reference
{
deferred_reference
(){}
deferred_reference
(
const
account_name
&
sender
,
uint128_t
sender_id
)
deferred_reference
(
const
account_name
&
sender
,
const
uint128_t
&
sender_id
)
:
sender
(
sender
),
sender_id
(
sender_id
)
{}
...
...
@@ -263,4 +262,4 @@ FC_REFLECT_DERIVED( eosio::chain::signed_transaction, (eosio::chain::transaction
FC_REFLECT_ENUM
(
eosio
::
chain
::
packed_transaction
::
compression_type
,
(
none
)(
zlib
))
FC_REFLECT
(
eosio
::
chain
::
packed_transaction
,
(
signatures
)(
compression
)(
packed_context_free_data
)(
packed_trx
)
)
FC_REFLECT_DERIVED
(
eosio
::
chain
::
deferred_transaction
,
(
eosio
::
chain
::
transaction
),
(
sender_id
)(
sender
)(
payer
)(
execute_after
)
)
FC_REFLECT
(
eosio
::
chain
::
deferred_reference
,
(
sender
_id
)(
sender
)
)
FC_REFLECT
(
eosio
::
chain
::
deferred_reference
,
(
sender
)(
sender_id
)
)
libraries/chain/wasm_interface.cpp
浏览文件 @
82cde96d
...
...
@@ -545,7 +545,7 @@ class softfloat_api : public context_aware_api {
}
int32_t
_eosio_f32_trunc_i32s
(
float
af
)
{
float32_t
a
=
to_softfloat32
(
af
);
if
(
_eosio_f32_ge
(
af
,
2147483648.0
f
)
||
_eosio_f32_l
e
(
af
,
-
2147483649
.0
f
))
if
(
_eosio_f32_ge
(
af
,
2147483648.0
f
)
||
_eosio_f32_l
t
(
af
,
-
2147483648
.0
f
))
FC_THROW_EXCEPTION
(
eosio
::
chain
::
wasm_execution_error
,
"Error, f32.convert_s/i32 overflow"
);
if
(
is_nan
(
a
))
...
...
@@ -554,7 +554,7 @@ class softfloat_api : public context_aware_api {
}
int32_t
_eosio_f64_trunc_i32s
(
double
af
)
{
float64_t
a
=
to_softfloat64
(
af
);
if
(
_eosio_f64_ge
(
af
,
2147483648.0
)
||
_eosio_f64_l
e
(
af
,
-
2147483649
.0
))
if
(
_eosio_f64_ge
(
af
,
2147483648.0
)
||
_eosio_f64_l
t
(
af
,
-
2147483648
.0
))
FC_THROW_EXCEPTION
(
eosio
::
chain
::
wasm_execution_error
,
"Error, f64.convert_s/i32 overflow"
);
if
(
is_nan
(
a
))
FC_THROW_EXCEPTION
(
eosio
::
chain
::
wasm_execution_error
,
"Error, f64.convert_s/i32 unrepresentable"
);
...
...
@@ -578,7 +578,7 @@ class softfloat_api : public context_aware_api {
}
int64_t
_eosio_f32_trunc_i64s
(
float
af
)
{
float32_t
a
=
to_softfloat32
(
af
);
if
(
_eosio_f32_ge
(
af
,
9223372036854775808.0
f
)
||
_eosio_f32_l
e
(
af
,
-
9223372036854775809
.0
f
))
if
(
_eosio_f32_ge
(
af
,
9223372036854775808.0
f
)
||
_eosio_f32_l
t
(
af
,
-
9223372036854775808
.0
f
))
FC_THROW_EXCEPTION
(
eosio
::
chain
::
wasm_execution_error
,
"Error, f32.convert_s/i64 overflow"
);
if
(
is_nan
(
a
))
FC_THROW_EXCEPTION
(
eosio
::
chain
::
wasm_execution_error
,
"Error, f32.convert_s/i64 unrepresentable"
);
...
...
@@ -586,7 +586,7 @@ class softfloat_api : public context_aware_api {
}
int64_t
_eosio_f64_trunc_i64s
(
double
af
)
{
float64_t
a
=
to_softfloat64
(
af
);
if
(
_eosio_f64_ge
(
af
,
9223372036854775808.0
)
||
_eosio_f64_l
e
(
af
,
-
9223372036854775809
.0
))
if
(
_eosio_f64_ge
(
af
,
9223372036854775808.0
)
||
_eosio_f64_l
t
(
af
,
-
9223372036854775808
.0
))
FC_THROW_EXCEPTION
(
eosio
::
chain
::
wasm_execution_error
,
"Error, f64.convert_s/i64 overflow"
);
if
(
is_nan
(
a
))
FC_THROW_EXCEPTION
(
eosio
::
chain
::
wasm_execution_error
,
"Error, f64.convert_s/i64 unrepresentable"
);
...
...
libraries/utilities/CMakeLists.txt
浏览文件 @
82cde96d
...
...
@@ -7,7 +7,7 @@ if(NOT EOS_GIT_REVISION_DESCRIPTION)
set
(
EOS_GIT_REVISION_DESCRIPTION
"unknown"
)
endif
(
NOT EOS_GIT_REVISION_DESCRIPTION
)
file
(
GLOB HEADERS
"include/eos/utilities/*.hpp"
)
file
(
GLOB HEADERS
"include/eos
io
/utilities/*.hpp"
)
set
(
sources
key_conversion.cpp
...
...
plugins/chain_api_plugin/CMakeLists.txt
浏览文件 @
82cde96d
file
(
GLOB HEADERS
"include/eos/chain_api_plugin/*.hpp"
)
file
(
GLOB HEADERS
"include/eos
io
/chain_api_plugin/*.hpp"
)
add_library
(
chain_api_plugin
chain_api_plugin.cpp
${
HEADERS
}
)
...
...
plugins/chain_plugin/CMakeLists.txt
浏览文件 @
82cde96d
file
(
GLOB HEADERS
"include/eos/chain_plugin/*.hpp"
)
file
(
GLOB HEADERS
"include/eos
io
/chain_plugin/*.hpp"
)
add_library
(
chain_plugin
chain_plugin.cpp
${
HEADERS
}
)
...
...
plugins/eosio-make_new_plugin.sh
浏览文件 @
82cde96d
...
...
@@ -12,7 +12,7 @@ echo Copying template...
cp
-r
template_plugin
$pluginName
echo
Renaming files/directories...
mv
$pluginName
/include/eos
/template_plugin
$pluginName
/include/eos
/
$pluginName
mv
$pluginName
/include/eos
io/template_plugin
$pluginName
/include/eosio
/
$pluginName
for
file
in
`
find
$pluginName
-type
f
-name
'*template_plugin*'
`
;
do
mv
$file
`
sed
s/template_plugin/
$pluginName
/g
<<<
$file
`
;
done
;
echo
Renaming
in
files...
...
...
plugins/http_plugin/CMakeLists.txt
浏览文件 @
82cde96d
file
(
GLOB HEADERS
"include/eos/http_plugin/*.hpp"
)
file
(
GLOB HEADERS
"include/eos
io
/http_plugin/*.hpp"
)
add_library
(
http_plugin
http_plugin.cpp
${
HEADERS
}
)
...
...
plugins/producer_plugin/CMakeLists.txt
浏览文件 @
82cde96d
file
(
GLOB HEADERS
"include/eos/producer_plugin/*.hpp"
)
file
(
GLOB HEADERS
"include/eos
io
/producer_plugin/*.hpp"
)
add_library
(
producer_plugin
producer_plugin.cpp
...
...
plugins/wallet_api_plugin/CMakeLists.txt
浏览文件 @
82cde96d
file
(
GLOB HEADERS
"include/eos/wallet_api_plugin/*.hpp"
)
file
(
GLOB HEADERS
"include/eos
io
/wallet_api_plugin/*.hpp"
)
add_library
(
wallet_api_plugin
wallet_api_plugin.cpp
${
HEADERS
}
)
...
...
plugins/wallet_plugin/CMakeLists.txt
浏览文件 @
82cde96d
file
(
GLOB HEADERS
"include/eos/wallet_plugin/*.hpp"
)
file
(
GLOB HEADERS
"include/eos
io
/wallet_plugin/*.hpp"
)
add_library
(
wallet_plugin
wallet.cpp
wallet_plugin.cpp
...
...
tests/CMakeLists.txt
浏览文件 @
82cde96d
...
...
@@ -19,7 +19,7 @@ include_directories("${CMAKE_SOURCE_DIR}/plugins/wallet_plugin/include")
configure_file
(
${
CMAKE_CURRENT_SOURCE_DIR
}
/tests/config.hpp.in
${
CMAKE_CURRENT_SOURCE_DIR
}
/tests/config.hpp ESCAPE_QUOTES
)
file
(
GLOB UNIT_TESTS
"chain_tests/*.cpp"
"api_tests/*.cpp"
"tests/abi_tests.cpp"
"tests/database_tests.cpp"
"tests/misc_tests.cpp"
"wasm_tests/*.cpp"
"tests/message_buffer_tests.cpp"
"tests/wallet_tests.cpp"
"library_tests/*/*.cpp"
)
file
(
GLOB UNIT_TESTS
"chain_tests/*.cpp"
"api_tests/*.cpp"
"tests/abi_tests.cpp"
"tests/database_tests.cpp"
"tests/misc_tests.cpp"
"wasm_tests/*.cpp"
"tests/message_buffer_tests.cpp"
"tests/
special_accounts_tests.cpp"
"tests/
wallet_tests.cpp"
"library_tests/*/*.cpp"
)
add_executable
(
chain_test
${
UNIT_TESTS
}
${
WASM_UNIT_TESTS
}
common/main.cpp
)
target_link_libraries
(
chain_test eosio_testing eosio_chain chainbase eos_utilities chain_plugin wallet_plugin abi_generator fc
${
PLATFORM_SPECIFIC_LIBS
}
)
...
...
tests/chain_tests/delay_tests.cpp
浏览文件 @
82cde96d
...
...
@@ -1362,7 +1362,7 @@ BOOST_AUTO_TEST_CASE( canceldelay_test ) { try {
TESTER
chain
;
const
auto
&
tester_account
=
N
(
tester
);
std
::
vector
<
transaction_id_type
>
ids
;
chain
.
set_code
(
config
::
system_account_name
,
eosio_system_wast
);
chain
.
set_abi
(
config
::
system_account_name
,
eosio_system_abi
);
...
...
@@ -1428,9 +1428,11 @@ BOOST_AUTO_TEST_CASE( canceldelay_test ) { try {
(
"memo"
,
"hi"
),
30
,
10
);
ids
.
push_back
(
trace
.
id
);
BOOST_REQUIRE_EQUAL
(
transaction_receipt
::
delayed
,
trace
.
status
);
BOOST_REQUIRE_EQUAL
(
1
,
trace
.
deferred_transaction_requests
.
size
());
BOOST_REQUIRE_EQUAL
(
0
,
trace
.
action_traces
.
size
());
const
auto
sender_id_to_cancel
=
trace
.
deferred_transaction_requests
[
0
].
get
<
deferred_transaction
>
().
sender_id
;
chain
.
produce_blocks
();
...
...
@@ -1451,6 +1453,7 @@ BOOST_AUTO_TEST_CASE( canceldelay_test ) { try {
(
"delay"
,
0
),
30
,
10
);
ids
.
push_back
(
trace
.
id
);
BOOST_REQUIRE_EQUAL
(
transaction_receipt
::
delayed
,
trace
.
status
);
BOOST_REQUIRE_EQUAL
(
1
,
trace
.
deferred_transaction_requests
.
size
());
BOOST_REQUIRE_EQUAL
(
0
,
trace
.
action_traces
.
size
());
...
...
@@ -1477,6 +1480,7 @@ BOOST_AUTO_TEST_CASE( canceldelay_test ) { try {
(
"memo"
,
"hi"
),
30
,
10
);
ids
.
push_back
(
trace
.
id
);
BOOST_REQUIRE_EQUAL
(
transaction_receipt
::
delayed
,
trace
.
status
);
BOOST_REQUIRE_EQUAL
(
1
,
trace
.
deferred_transaction_requests
.
size
());
BOOST_REQUIRE_EQUAL
(
0
,
trace
.
action_traces
.
size
());
...
...
@@ -1491,14 +1495,16 @@ BOOST_AUTO_TEST_CASE( canceldelay_test ) { try {
// send canceldelay for first delayed transaction
signed_transaction
trx
;
trx
.
actions
.
emplace_back
(
vector
<
permission_level
>
{{
N
(
tester
),
config
::
active_name
}},
chain
::
contracts
::
canceldelay
{
sender_id_to_cancel
});
chain
::
contracts
::
canceldelay
{
ids
[
0
]
});
trx
.
actions
.
back
().
authorization
.
push_back
({
N
(
tester
),
config
::
active_name
});
chain
.
set_transaction_headers
(
trx
);
trx
.
sign
(
chain
.
get_private_key
(
N
(
tester
),
"active"
),
chain_id_type
());
trace
=
chain
.
push_transaction
(
trx
);
BOOST_REQUIRE_EQUAL
(
transaction_receipt
::
executed
,
trace
.
status
);
BOOST_REQUIRE_EQUAL
(
1
,
trace
.
deferred_transaction_requests
.
size
());
const
auto
sender_id_canceled
=
trace
.
deferred_transaction_requests
[
0
].
get
<
deferred_reference
>
().
sender_id
;
BOOST_REQUIRE_EQUAL
(
std
::
string
(
uint128
(
sender_id_to_cancel
)),
std
::
string
(
uint128
(
sender_id_canceled
)));
...
...
@@ -1555,7 +1561,6 @@ BOOST_AUTO_TEST_CASE( canceldelay_test ) { try {
BOOST_REQUIRE_EQUAL
(
asset
::
from_string
(
"85.0000 CUR"
),
liquid_balance
);
liquid_balance
=
get_currency_balance
(
chain
,
N
(
tester2
));
BOOST_REQUIRE_EQUAL
(
asset
::
from_string
(
"15.0000 CUR"
),
liquid_balance
);
}
FC_LOG_AND_RETHROW
()
}
/// schedule_test
BOOST_AUTO_TEST_SUITE_END
()
tests/tests/special_accounts_tests.cpp
0 → 100644
浏览文件 @
82cde96d
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#include <algorithm>
#include <vector>
#include <iterator>
#include <boost/test/unit_test.hpp>
#include <eosio/chain/chain_controller.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/permission_object.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/utilities/tempdir.hpp>
#include <fc/crypto/digest.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/range/algorithm/find.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <boost/range/algorithm/permutation.hpp>
using
namespace
eosio
;
using
namespace
chain
;
using
tester
=
eosio
::
testing
::
tester
;
BOOST_AUTO_TEST_SUITE
(
special_account_tests
)
//Check special accounts exits in genesis
BOOST_FIXTURE_TEST_CASE
(
accounts_exists
,
tester
)
{
try
{
tester
test
;
chain
::
chain_controller
*
control
=
test
.
control
.
get
();
chain
::
database
&
chain1_db
=
control
->
get_mutable_database
();
auto
nobody
=
chain1_db
.
find
<
account_object
,
by_name
>
(
config
::
nobody_account_name
);
BOOST_CHECK
(
nobody
!=
nullptr
);
const
auto
&
nobody_active_authority
=
chain1_db
.
get
<
permission_object
,
by_owner
>
(
boost
::
make_tuple
(
config
::
nobody_account_name
,
config
::
active_name
));
BOOST_CHECK_EQUAL
(
nobody_active_authority
.
auth
.
threshold
,
0
);
BOOST_CHECK_EQUAL
(
nobody_active_authority
.
auth
.
accounts
.
size
(),
0
);
BOOST_CHECK_EQUAL
(
nobody_active_authority
.
auth
.
keys
.
size
(),
0
);
const
auto
&
nobody_owner_authority
=
chain1_db
.
get
<
permission_object
,
by_owner
>
(
boost
::
make_tuple
(
config
::
nobody_account_name
,
config
::
owner_name
));
BOOST_CHECK_EQUAL
(
nobody_owner_authority
.
auth
.
threshold
,
0
);
BOOST_CHECK_EQUAL
(
nobody_owner_authority
.
auth
.
accounts
.
size
(),
0
);
BOOST_CHECK_EQUAL
(
nobody_owner_authority
.
auth
.
keys
.
size
(),
0
);
auto
producers
=
chain1_db
.
find
<
account_object
,
by_name
>
(
config
::
producers_account_name
);
BOOST_CHECK
(
producers
!=
nullptr
);
auto
&
gpo
=
chain1_db
.
get
<
global_property_object
>
();
const
auto
&
producers_active_authority
=
chain1_db
.
get
<
permission_object
,
by_owner
>
(
boost
::
make_tuple
(
config
::
producers_account_name
,
config
::
active_name
));
BOOST_CHECK_EQUAL
(
producers_active_authority
.
auth
.
threshold
,
config
::
producers_authority_threshold
);
BOOST_CHECK_EQUAL
(
producers_active_authority
.
auth
.
accounts
.
size
(),
gpo
.
active_producers
.
producers
.
size
());
BOOST_CHECK_EQUAL
(
producers_active_authority
.
auth
.
keys
.
size
(),
0
);
std
::
vector
<
account_name
>
active_auth
;
for
(
auto
&
apw
:
producers_active_authority
.
auth
.
accounts
)
{
active_auth
.
emplace_back
(
apw
.
permission
.
actor
);
}
std
::
vector
<
account_name
>
diff
;
for
(
int
i
=
0
;
i
<
std
::
max
(
active_auth
.
size
(),
gpo
.
active_producers
.
producers
.
size
());
++
i
)
{
account_name
n1
=
i
<
active_auth
.
size
()
?
active_auth
[
i
]
:
(
account_name
)
0
;
account_name
n2
=
i
<
gpo
.
active_producers
.
producers
.
size
()
?
gpo
.
active_producers
.
producers
[
i
].
producer_name
:
(
account_name
)
0
;
if
(
n1
!=
n2
)
diff
.
push_back
((
uint64_t
)
n2
-
(
uint64_t
)
n1
);
}
BOOST_CHECK_EQUAL
(
diff
.
size
(),
0
);
const
auto
&
producers_owner_authority
=
chain1_db
.
get
<
permission_object
,
by_owner
>
(
boost
::
make_tuple
(
config
::
producers_account_name
,
config
::
owner_name
));
BOOST_CHECK_EQUAL
(
producers_owner_authority
.
auth
.
threshold
,
0
);
BOOST_CHECK_EQUAL
(
producers_owner_authority
.
auth
.
accounts
.
size
(),
0
);
BOOST_CHECK_EQUAL
(
producers_owner_authority
.
auth
.
keys
.
size
(),
0
);
}
FC_LOG_AND_RETHROW
()
}
BOOST_AUTO_TEST_SUITE_END
()
tests/wasm_tests/test_softfloat_wasts.hpp
浏览文件 @
82cde96d
...
...
@@ -21647,3 +21647,38 @@ static const char f32_f64_conv_wast[] = R"=====(
(call $assert_returnf64 (call $f64_convert_u_i64 (i64.const 9007199254740995)) (f64.const 9007199254740996) (i32.const 1040))
))
)=====";
static const char i32_overflow_wast[] = R"=====(
(module
(import "env" "require_auth" (func $require_auth (param i64)))
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
(table 0 anyfunc)
(memory $0 1)
(export "apply" (func $apply))
(func $i32_trunc_s_f32 (param $0 f32) (result i32) (i32.trunc_s/f32 (get_local $0)))
(func $i32_trunc_u_f32 (param $0 f32) (result i32) (i32.trunc_u/f32 (get_local $0)))
(func $i32_trunc_s_f64 (param $0 f64) (result i32) (i32.trunc_s/f64 (get_local $0)))
(func $i32_trunc_u_f64 (param $0 f64) (result i32) (i32.trunc_u/f64 (get_local $0)))
(func $test (param $0 i32))
(func $apply (param $0 i64)(param $1 i64)(param $2 i64)
(call $test (call $%s (%s)))
))
)=====";
static const char i64_overflow_wast[] = R"=====(
(module
(import "env" "require_auth" (func $require_auth (param i64)))
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
(table 0 anyfunc)
(memory $0 1)
(export "apply" (func $apply))
(func $i64_trunc_s_f32 (param $0 f32) (result i64) (i64.trunc_s/f32 (get_local $0)))
(func $i64_trunc_u_f32 (param $0 f32) (result i64) (i64.trunc_u/f32 (get_local $0)))
(func $i64_trunc_s_f64 (param $0 f64) (result i64) (i64.trunc_s/f64 (get_local $0)))
(func $i64_trunc_u_f64 (param $0 f64) (result i64) (i64.trunc_u/f64 (get_local $0)))
(func $test (param $0 i64))
(func $apply (param $0 i64)(param $1 i64)(param $2 i64)
(call $test (call $%s (%s)))
))
)=====";
tests/wasm_tests/wasm_tests.cpp
浏览文件 @
82cde96d
...
...
@@ -360,6 +360,110 @@ BOOST_FIXTURE_TEST_CASE( f32_f64_conversion_tests, tester ) try {
}
}
FC_LOG_AND_RETHROW
()
// test softfloat conversion operations
BOOST_FIXTURE_TEST_CASE
(
f32_f64_overflow_tests
,
tester
)
try
{
int
count
=
0
;
auto
check
=
[
&
](
const
char
*
wast_template
,
const
char
*
op
,
const
char
*
param
)
->
bool
{
count
+=
16
;
create_accounts
(
{
N
(
f_tests
)
+
count
}
);
produce_blocks
(
1
);
std
::
vector
<
char
>
wast
;
wast
.
resize
(
strlen
(
wast_template
)
+
128
);
sprintf
(
&
(
wast
[
0
]),
wast_template
,
op
,
param
);
set_code
(
N
(
f_tests
)
+
count
,
&
(
wast
[
0
]));
produce_blocks
(
10
);
signed_transaction
trx
;
action
act
;
act
.
account
=
N
(
f_tests
)
+
count
;
act
.
name
=
N
();
act
.
authorization
=
vector
<
permission_level
>
{{
N
(
f_tests
)
+
count
,
config
::
active_name
}};
trx
.
actions
.
push_back
(
act
);
set_transaction_headers
(
trx
);
trx
.
sign
(
get_private_key
(
N
(
f_tests
)
+
count
,
"active"
),
chain_id_type
());
try
{
push_transaction
(
trx
);
produce_blocks
(
1
);
BOOST_REQUIRE_EQUAL
(
true
,
chain_has_transaction
(
trx
.
id
()));
const
auto
&
receipt
=
get_transaction_receipt
(
trx
.
id
());
return
true
;
}
catch
(
eosio
::
chain
::
wasm_execution_error
&
)
{
return
false
;
}
};
//
//// float32 => int32
// 2^31
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i32_overflow_wast
,
"i32_trunc_s_f32"
,
"f32.const 2147483648"
));
// the maximum value below 2^31 representable in IEEE float32
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i32_overflow_wast
,
"i32_trunc_s_f32"
,
"f32.const 2147483520"
));
// -2^31
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i32_overflow_wast
,
"i32_trunc_s_f32"
,
"f32.const -2147483648"
));
// the maximum value below -2^31 in IEEE float32
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i32_overflow_wast
,
"i32_trunc_s_f32"
,
"f32.const -2147483904"
));
//
//// float32 => uint32
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i32_overflow_wast
,
"i32_trunc_u_f32"
,
"f32.const 0"
));
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i32_overflow_wast
,
"i32_trunc_u_f32"
,
"f32.const -1"
));
// max value below 2^32 in IEEE float32
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i32_overflow_wast
,
"i32_trunc_u_f32"
,
"f32.const 4294967040"
));
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i32_overflow_wast
,
"i32_trunc_u_f32"
,
"f32.const 4294967296"
));
//
//// double => int32
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i32_overflow_wast
,
"i32_trunc_s_f64"
,
"f64.const 2147483648"
));
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i32_overflow_wast
,
"i32_trunc_s_f64"
,
"f64.const 2147483647"
));
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i32_overflow_wast
,
"i32_trunc_s_f64"
,
"f64.const -2147483648"
));
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i32_overflow_wast
,
"i32_trunc_s_f64"
,
"f64.const -2147483649"
));
//
//// double => uint32
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i32_overflow_wast
,
"i32_trunc_u_f64"
,
"f64.const 0"
));
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i32_overflow_wast
,
"i32_trunc_u_f64"
,
"f64.const -1"
));
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i32_overflow_wast
,
"i32_trunc_u_f64"
,
"f64.const 4294967295"
));
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i32_overflow_wast
,
"i32_trunc_u_f64"
,
"f64.const 4294967296"
));
//// float32 => int64
// 2^63
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i64_overflow_wast
,
"i64_trunc_s_f32"
,
"f32.const 9223372036854775808"
));
// the maximum value below 2^63 representable in IEEE float32
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i64_overflow_wast
,
"i64_trunc_s_f32"
,
"f32.const 9223371487098961920"
));
// -2^63
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i64_overflow_wast
,
"i64_trunc_s_f32"
,
"f32.const -9223372036854775808"
));
// the maximum value below -2^63 in IEEE float32
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i64_overflow_wast
,
"i64_trunc_s_f32"
,
"f32.const -9223373136366403584"
));
//// float32 => uint64
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i64_overflow_wast
,
"i64_trunc_u_f32"
,
"f32.const -1"
));
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i64_overflow_wast
,
"i64_trunc_u_f32"
,
"f32.const 0"
));
// max value below 2^64 in IEEE float32
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i64_overflow_wast
,
"i64_trunc_u_f32"
,
"f32.const 18446742974197923840"
));
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i64_overflow_wast
,
"i64_trunc_u_f32"
,
"f32.const 18446744073709551616"
));
//// double => int64
// 2^63
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i64_overflow_wast
,
"i64_trunc_s_f64"
,
"f64.const 9223372036854775808"
));
// the maximum value below 2^63 representable in IEEE float64
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i64_overflow_wast
,
"i64_trunc_s_f64"
,
"f64.const 9223372036854774784"
));
// -2^63
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i64_overflow_wast
,
"i64_trunc_s_f64"
,
"f64.const -9223372036854775808"
));
// the maximum value below -2^63 in IEEE float64
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i64_overflow_wast
,
"i64_trunc_s_f64"
,
"f64.const -9223372036854777856"
));
//// double => uint64
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i64_overflow_wast
,
"i64_trunc_u_f64"
,
"f64.const -1"
));
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i64_overflow_wast
,
"i64_trunc_u_f64"
,
"f64.const 0"
));
// max value below 2^64 in IEEE float64
BOOST_REQUIRE_EQUAL
(
true
,
check
(
i64_overflow_wast
,
"i64_trunc_u_f64"
,
"f64.const 18446744073709549568"
));
BOOST_REQUIRE_EQUAL
(
false
,
check
(
i64_overflow_wast
,
"i64_trunc_u_f64"
,
"f64.const 18446744073709551616"
));
}
FC_LOG_AND_RETHROW
()
/**
* Make sure WASM "start" method is used correctly
*/
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录