Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
59b5c209
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,发现更多精彩内容 >>
提交
59b5c209
编写于
9月 05, 2017
作者:
B
Bart Wyatt
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
changed API to be inline messages and deferred transactions
first swipe at processing thereof, need tests badly ref EOSIO/eos#175
上级
45ad2937
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
247 addition
and
174 deletion
+247
-174
contracts/eoslib/transaction.h
contracts/eoslib/transaction.h
+73
-68
libraries/chain/chain_controller.cpp
libraries/chain/chain_controller.cpp
+19
-11
libraries/chain/include/eos/chain/message_handling_contexts.hpp
...ies/chain/include/eos/chain/message_handling_contexts.hpp
+29
-25
libraries/chain/include/eos/chain/transaction.hpp
libraries/chain/include/eos/chain/transaction.hpp
+30
-13
libraries/chain/message_handling_contexts.cpp
libraries/chain/message_handling_contexts.cpp
+56
-15
libraries/chain/wasm_interface.cpp
libraries/chain/wasm_interface.cpp
+40
-42
未找到文件。
contracts/eoslib/transaction.h
浏览文件 @
59b5c209
...
...
@@ -5,8 +5,7 @@ extern "C" {
/**
* @defgroup transactionapi Transaction API
* @ingroup contractdev
* @brief Define API for sending transactions to other contracts inline with
* the current transaction or deferred to a future block.
* @brief Define API for sending transactions and inline messages
*
* A EOS.IO transaction has the following abstract structure:
*
...
...
@@ -20,32 +19,32 @@ extern "C" {
*
* This API enables your contract to construct and send transactions
*
* A Transaction can be processed immediately after the execution of the
* parent transaction (inline). An inline transaction is more restrictive
* than a deferred transaction however, it allows the success or failure
* of the parent transaction to be affected by the new transaction. In
* other words, if an inline transaction fails then the whole tree of
* transactions rooted in the block will me marked as failing and none of
* their affects on the database will persist.
*
* Because of this and the parallel nature of transaction application,
* inline transactions may not adopt any `scope` which is not listed in
* their parent transaction's scope. They may adopt any `readScope` listed
* in either their parent's `scope` or `readScope`.
*
* Deferred transactions carry no `scope` or `readScope` restrictions. They
* may adopt any valid accounts for either field.
*
* Deferred transactions will not be processed until a future block. They
* can therefore have no effect on the success of failure of their parent
* transaction so long as they appear well formed. If any other condition
* causes the parent transaction to be marked as failing, then the deferred
* transaction will never be processed.
*
*
Both Deferred and Inline transactions must adhere to the permissions
*
available to the parent transaction or, in the future, delegated to the
*
contract account
for future use.
*
Deferred transactions must adhere to the permissions available to the
*
parent transaction or, in the future, delegated to the contract account
* for future use.
*
* An inline message allows one contract to send another contract a message
* which is processed immediately after the current message's processing
* ends such that the success or failure of the parent transaction is
* dependent on the success of the message. If an inline message fails in
* processing then the whole tree of transactions and messages rooted in the
* block will me marked as failing and none of effects on the database will
* persist.
*
* Because of this and the parallel nature of transaction application,
* inline messages may not affect any `scope` which is not listed in
* their parent transaction's `scope`. They also may not read any `scope`
* not listed in either their parent transaction's `scope` or `readScope`.
*
* Inline messages and Deferred transactions must adhere to the permissions
* available to the parent transaction or, in the future, delegated to the
* contract account for future use.
*/
/**
...
...
@@ -58,8 +57,9 @@ extern "C" {
typedef
uint32_t
TransactionHandle
;
#define InvalidTransactionHandle (0xFFFFFFFFUL)
#define SendInline (1)
#define SendDeferred (0)
typedef
uint32_t
MessageHandle
;
#define InvalidMessageHandle (0xFFFFFFFFUL)
/**
* @brief create a pending transaction
...
...
@@ -75,7 +75,7 @@ extern "C" {
TransactionHandle
transactionCreate
();
/**
* @brief
add a scope to
a pending transaction
* @brief
require a scope to process
a pending transaction
*
* This function adds either a `scope` or `readScope` to the given pending
* transaction.
...
...
@@ -84,86 +84,91 @@ extern "C" {
* @param scope - the `AccountName` to add
* @param readOnly - whether `scope` should be added to `scope[]` or `readScope[]`
*/
void
transaction
Add
Scope
(
TransactionHandle
trx
,
AccountName
scope
,
int
readOnly
=
0
);
void
transaction
Require
Scope
(
TransactionHandle
trx
,
AccountName
scope
,
int
readOnly
=
0
);
/**
* @brief
set the destination for the pending message
* @brief
finalize the pending message and add it to the transaction
*
* This function sets the `AccountName` of the owner of the contract
* that is acting as the reciever of the pending message and the type of
* message;
* The message handle should be considered invalid after the call
*
* @param trx - the `TransactionHandle` of the pending transaction to modify
* @param code - the `AccountName` which owns the contract code to execute
* @param type - the type of this message
* @param msg - the `MessageHandle` of the pending message to add
*/
void
transactionSetMessageDestination
(
TransactionHandle
trx
,
AccountName
code
,
FuncName
type
);
void
transactionAddMessage
(
TransactionHandle
trx
,
MessageHandle
msg
);
/**
* @brief
add a permission to the pending message
* @brief
send a pending transaction
*
* This function adds a @ref PermissionName to the pending message
* This function will finalize a pending transaction and enqueue it for
* processing either immediately after this transaction and its previously
* sent inline transactions complete OR in a future block.
*
* This handle should be considered invalid after the call
*
* @param trx - the `TransactionHandle` of the pending transaction to modify
* @param account - the `AccountName` to add
* @param permission - the `PermissionName` to add
* @param trx - the `TransactionHandle` of the pending transaction to send
*/
void
transaction
AddMessagePermission
(
TransactionHandle
trx
,
AccountName
account
,
PermissionName
permission
);
void
transaction
Send
(
TransactionHandle
trx
);
/**
* @brief drop a pending transaction
*
* This function will discard a pending transaction and its associated
* resources. Once a transaction is sent it can no longer be dropped.
*
* This handle should be considered invalid after the call
*
* @param trx - the `TransactionHandle` of the pending transaction to send
*/
void
transactionDrop
(
TransactionHandle
trx
);
/**
* @brief
finalize the pending message and add it to the transaction
* @brief
create a pending message
*
* This function
adds payload data to the pending message and pushes it into
* t
he given transaction.
* This function
creates a pending message to be included in a deferred
* t
ransaction or to be send as an inline message
*
* This will reset the destination and permissions for the pending message on
* the given transaction.
* This message has no default permissions, see @ref messageRequirePermission
*
* @param trx - the `TransactionHandle` of the pending transaction to modify
* @param code - the `AccountName` which owns the contract code to execute
* @param type - the type of this message
* @param data - the payload data for this message
* @param size - the size of `data`
*/
void
transactionPushMessage
(
TransactionHandle
trx
,
void
*
data
,
int
size
);
MessageHandle
messageCreate
(
AccountName
code
,
FuncName
type
,
void
*
data
,
int
size
);
/**
* @brief re
set the destination and persmisions of the pending transaction
* @brief re
quire a permission for the pending message
*
* This will reset the destination and permissions for the pending message on
* the given transaction without committing the existing settings effectively
* dropping any changes made so far.
* Indicates that a given pending message requires a certain permission
*
* @param trx - the `TransactionHandle` of the pending transaction to modify
* @param msg - the `MessageHandle` pending message referred to
* @param account - the `AccountName` to of the permission
* @param permission - the `PermissionName` to of the permision
*/
void
transactionResetMessage
(
TransactionHandle
trx
);
void
messageRequirePermission
(
MessageHandle
msg
,
AccountName
account
,
PermissionName
permission
);
/**
* @brief send a pending
transaction
* @brief send a pending
message as an inline message
*
* This function will finalize a pending transaction and enqueue it for
* processing either immediately after this transaction and its previously
* sent inline transactions complete OR in a future block.
*
* This handle should be considered invalid after the call
*
* @param trx - the `TransactionHandle` of the pending transaction to send
* @param inlineMode - whether to send as an inline transaction (!=0) or deferred(=0)
* @param msg - the `MessageHandle` of the pending message to send inline
*/
void
transactionSend
(
TransactionHandle
trx
,
int
mode
=
SendDeferred
);
void
messageSend
(
MessageHandle
msg
);
/**
* @brief d
rop a pending transaction
* @brief d
iscard a pending message
*
* This function will discard a pending transaction and its associated
* resources. Once a transaction is sent it can no longer be dropped.
*
* This handle should be considered invalid after the call
*
* @param trx - the `
TransactionHandle` of the pending transaction to sen
d
* @param trx - the `
MessageHandle` of the pending message to discar
d
*/
void
transactionDrop
(
TransactionHandle
trx
);
void
messageDrop
(
MessageHandle
msg
);
///@ } transactioncapi
}
libraries/chain/chain_controller.cpp
浏览文件 @
59b5c209
...
...
@@ -626,7 +626,7 @@ void check_output(const Transaction& expected, const Transaction& actual, const
template
<
>
void
check_output
(
const
ProcessedSyncTransaction
&
expected
,
const
ProcessedSync
Transaction
&
actual
,
const
path_cons_list
&
path
)
{
void
check_output
(
const
InlineTransaction
&
expected
,
const
Inline
Transaction
&
actual
,
const
path_cons_list
&
path
)
{
check_output
<
Transaction
>
(
expected
,
actual
,
path
);
check_output
(
expected
.
output
,
actual
.
output
,
path
(
".output"
));
}
...
...
@@ -640,8 +640,8 @@ void check_output(const GeneratedTransaction& expected, const GeneratedTransacti
template
<
>
void
check_output
(
const
MessageOutput
&
expected
,
const
MessageOutput
&
actual
,
const
path_cons_list
&
path
)
{
check_output
(
expected
.
notify
,
actual
.
notify
,
path
(
".notify"
));
check_output
(
expected
.
sync_transactions
,
actual
.
sync_transactions
,
path
(
".sync_transactions
"
));
check_output
(
expected
.
async_transactions
,
actual
.
async_transactions
,
path
(
".async
_transactions"
));
check_output
(
expected
.
inline_transaction
,
actual
.
inline_transaction
,
path
(
".inline_transaction
"
));
check_output
(
expected
.
deferred_transactions
,
actual
.
deferred_transactions
,
path
(
".deferred
_transactions"
));
}
template
<
typename
T
>
...
...
@@ -898,19 +898,27 @@ void chain_controller::process_message(const Transaction& trx, AccountName code,
}
FC_CAPTURE_AND_RETHROW
((
apply_ctx
.
notified
[
i
]))
}
for
(
const
auto
&
generated
:
apply_ctx
.
sync_transactions
)
{
try
{
output
.
sync_transactions
.
emplace_back
(
process_transaction
(
generated
)
);
}
FC_CAPTURE_AND_RETHROW
((
generated
))
}
// combine inline messages and process
auto
inline_transaction
=
PendingInlineTransaction
(
trx
);
inline_transaction
.
messages
=
std
::
move
(
apply_ctx
.
inline_messages
);
try
{
output
.
inline_transaction
=
process_transaction
(
inline_transaction
);
}
FC_CAPTURE_AND_RETHROW
((
inline_transaction
))
for
(
auto
&
asynctrx
:
apply_ctx
.
deferred_transactions
)
{
digest_type
::
encoder
enc
;
fc
::
raw
::
pack
(
enc
,
trx
);
fc
::
raw
::
pack
(
enc
,
asynctrx
);
auto
id
=
enc
.
result
();
auto
gtrx
=
GeneratedTransaction
(
id
,
asynctrx
);
for
(
auto
&
asynctrx
:
apply_ctx
.
async_transactions
)
{
_db
.
create
<
generated_transaction_object
>
([
&
](
generated_transaction_object
&
transaction
)
{
transaction
.
trx
=
async
trx
;
transaction
.
trx
=
g
trx
;
transaction
.
status
=
generated_transaction_object
::
PENDING
;
});
output
.
async_transactions
.
emplace_back
(
std
::
move
(
asynctrx
)
);
output
.
deferred_transactions
.
emplace_back
(
gtrx
);
}
// propagate used_authorizations up the context chain
...
...
libraries/chain/include/eos/chain/message_handling_contexts.hpp
浏览文件 @
59b5c209
...
...
@@ -271,6 +271,7 @@ public:
* @throws tx_missing_auth If no sufficient permission was found
*/
void
require_authorization
(
const
types
::
AccountName
&
account
);
void
require_authorization
(
const
types
::
AccountName
&
account
,
const
types
::
PermissionName
&
permission
);
void
require_scope
(
const
types
::
AccountName
&
account
)
const
;
void
require_recipient
(
const
types
::
AccountName
&
account
);
...
...
@@ -286,41 +287,26 @@ public:
chain_controller
&
mutable_controller
;
chainbase
::
database
&
mutable_db
;
std
::
deque
<
AccountName
>
notified
;
std
::
deque
<
Transaction
>
inline_transactions
;
///< queued inline tx
s
std
::
deque
<
Transaction
>
deferred_transactions
;
///< deferred txs
std
::
deque
<
AccountName
>
notified
;
std
::
vector
<
types
::
Message
>
inline_messages
;
///< queued inline message
s
std
::
vector
<
types
::
Transaction
>
deferred_transactions
;
///< deferred txs
///< Parallel to msg.authorization; tracks which permissions have been used while processing the message
vector
<
bool
>
used_authorizations
;
///< pending transaction construction
typedef
uint32_t
pending_transaction_handle
;
struct
pending_transaction
{
struct
pending_transaction
:
public
types
::
Transaction
{
typedef
uint32_t
handle_type
;
static
const
handle_type
Invalid_handle
=
0xFFFFFFFFUL
;
pending_transaction
(
const
handle_type
&
_handle
,
const
UInt16
&
block_num
,
const
UInt32
&
block_ref
,
const
Time
&
expiration
)
:
types
::
Transaction
(
block_num
,
block_ref
,
expiration
,
vector
<
types
::
AccountName
>
(),
vector
<
types
::
AccountName
>
(),
vector
<
types
::
Message
>
())
,
handle
(
_handle
)
{}
handle_type
handle
;
struct
message_dest
{
AccountName
code
;
FuncName
type
;
};
// state set that applies to pushed message data
optional
<
message_destination
>
current_destination
;
vector
<
types
::
AccountPermission
>
current_permissions
;
// state to apply when the transaction is pushed
vector
<
AccountName
>
scopes
;
vector
<
AccountName
>
read_scopes
;
vector
<
types
::
Message
>
messages
;
types
::
Transaction
as_transaction
()
const
;
void
check_size
()
const
;
void
reset_message
()
{
current_destination
=
decltype
(
current_destination
)();
current_permissions
.
clear
();
}
};
pending_transaction
::
handle_type
next_pending_transaction_serial
;
...
...
@@ -330,6 +316,24 @@ public:
pending_transaction
&
create_pending_transaction
();
void
release_pending_transaction
(
pending_transaction
::
handle_type
handle
);
///< pending message construction
typedef
uint32_t
pending_message_handle
;
struct
pending_message
:
public
types
::
Message
{
typedef
uint32_t
handle_type
;
pending_message
(
const
handle_type
&
_handle
,
const
AccountName
&
code
,
const
FuncName
&
type
,
const
Bytes
&
data
)
:
types
::
Message
(
code
,
type
,
vector
<
types
::
AccountPermission
>
(),
data
)
,
handle
(
_handle
)
{}
handle_type
handle
;
};
pending_transaction
::
handle_type
next_pending_message_serial
;
vector
<
pending_message
>
pending_messages
;
pending_message
&
get_pending_message
(
pending_message
::
handle_type
handle
);
pending_message
&
create_pending_message
(
const
AccountName
&
code
,
const
FuncName
&
type
,
const
Bytes
&
data
);
void
release_pending_message
(
pending_message
::
handle_type
handle
);
};
using
apply_handler
=
std
::
function
<
void
(
apply_context
&
)
>
;
...
...
libraries/chain/include/eos/chain/transaction.hpp
浏览文件 @
59b5c209
...
...
@@ -53,7 +53,7 @@ namespace eos { namespace chain {
*/
struct
ProcessedTransaction
;
struct
ProcessedSync
Transaction
;
struct
Inline
Transaction
;
struct
ProcessedGeneratedTransaction
;
...
...
@@ -115,6 +115,15 @@ namespace eos { namespace chain {
* subsequent blocks by referencing this ID.
*/
struct
GeneratedTransaction
:
public
types
::
Transaction
{
GeneratedTransaction
()
=
default
;
GeneratedTransaction
(
generated_transaction_id_type
_id
,
const
Transaction
&
trx
)
:
types
::
Transaction
(
trx
)
,
id
(
_id
)
{}
GeneratedTransaction
(
generated_transaction_id_type
_id
,
const
Transaction
&&
trx
)
:
types
::
Transaction
(
trx
)
,
id
(
_id
)
{}
generated_transaction_id_type
id
;
digest_type
merkle_digest
()
const
;
...
...
@@ -156,16 +165,30 @@ namespace eos { namespace chain {
typedef
ProcessedTransaction
Processed
;
};
struct
NotifyOutput
;
struct
PendingInlineTransaction
:
public
types
::
Transaction
{
typedef
types
::
Transaction
super
;
using
super
::
super
;
typedef
InlineTransaction
Processed
;
};
struct
MessageOutput
;
struct
InlineTransaction
:
public
types
::
Transaction
{
explicit
InlineTransaction
(
const
PendingInlineTransaction
&
t
)
:
Transaction
(
t
){}
InlineTransaction
(){}
vector
<
MessageOutput
>
output
;
};
struct
NotifyOutput
;
/**
* Output generated by applying a particular message.
*/
struct
MessageOutput
{
vector
<
NotifyOutput
>
notify
;
///< accounts to notify, may only be notified once
vector
<
ProcessedSyncTransaction
>
sync_transactions
;
///< transactions generated and applied after notify
vector
<
GeneratedTransaction
>
async
_transactions
;
///< transactions generated but not applied
InlineTransaction
inline_transaction
;
///< transactions generated and applied after notify
vector
<
GeneratedTransaction
>
deferred
_transactions
;
///< transactions generated but not applied
};
struct
NotifyOutput
{
...
...
@@ -180,13 +203,6 @@ namespace eos { namespace chain {
vector
<
MessageOutput
>
output
;
};
struct
ProcessedSyncTransaction
:
public
Transaction
{
explicit
ProcessedSyncTransaction
(
const
Transaction
&
t
)
:
Transaction
(
t
){}
ProcessedSyncTransaction
(){}
vector
<
MessageOutput
>
output
;
};
struct
ProcessedGeneratedTransaction
{
explicit
ProcessedGeneratedTransaction
(
const
generated_transaction_id_type
&
_id
)
:
id
(
_id
){}
explicit
ProcessedGeneratedTransaction
(
const
GeneratedTransaction
&
t
)
:
id
(
t
.
id
){}
...
...
@@ -201,8 +217,9 @@ namespace eos { namespace chain {
FC_REFLECT
(
eos
::
chain
::
GeneratedTransaction
,
(
id
))
FC_REFLECT_DERIVED
(
eos
::
chain
::
SignedTransaction
,
(
eos
::
types
::
SignedTransaction
),
)
FC_REFLECT
(
eos
::
chain
::
MessageOutput
,
(
notify
)(
sync_transactions
)(
async
_transactions
)
)
FC_REFLECT
(
eos
::
chain
::
MessageOutput
,
(
notify
)(
inline_transaction
)(
deferred
_transactions
)
)
FC_REFLECT_DERIVED
(
eos
::
chain
::
ProcessedTransaction
,
(
eos
::
types
::
SignedTransaction
),
(
output
)
)
FC_REFLECT_DERIVED
(
eos
::
chain
::
ProcessedSyncTransaction
,
(
eos
::
types
::
Transaction
),
(
output
)
)
FC_REFLECT_DERIVED
(
eos
::
chain
::
PendingInlineTransaction
,
(
eos
::
types
::
Transaction
),
)
FC_REFLECT_DERIVED
(
eos
::
chain
::
InlineTransaction
,
(
eos
::
types
::
Transaction
),
(
output
)
)
FC_REFLECT
(
eos
::
chain
::
ProcessedGeneratedTransaction
,
(
id
)(
output
)
)
FC_REFLECT
(
eos
::
chain
::
NotifyOutput
,
(
name
)(
output
)
)
libraries/chain/message_handling_contexts.cpp
浏览文件 @
59b5c209
...
...
@@ -6,6 +6,8 @@
#include <eos/utilities/parallel_markers.hpp>
#include <fc/bitutil.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
#include <boost/range/algorithm/find_if.hpp>
...
...
@@ -18,6 +20,13 @@ void apply_context::require_authorization(const types::AccountName& account) {
used_authorizations
[
itr
-
msg
.
authorization
.
begin
()]
=
true
;
}
void
apply_context
::
require_authorization
(
const
types
::
AccountName
&
account
,
const
types
::
PermissionName
&
permission
)
{
auto
itr
=
boost
::
find_if
(
msg
.
authorization
,
[
&
account
,
&
permission
](
const
auto
&
auth
)
{
return
auth
.
account
==
account
&&
auth
.
permission
==
permission
;
});
EOS_ASSERT
(
itr
!=
msg
.
authorization
.
end
(),
tx_missing_auth
,
"Transaction is missing required authorization from ${acct} with permission ${permission}"
,
(
"acct"
,
account
)(
"permission"
,
permission
));
used_authorizations
[
itr
-
msg
.
authorization
.
begin
()]
=
true
;
}
void
apply_context
::
require_scope
(
const
types
::
AccountName
&
account
)
const
{
auto
itr
=
boost
::
find_if
(
trx
.
scope
,
[
&
account
](
const
auto
&
scope
)
{
return
scope
==
account
;
...
...
@@ -51,7 +60,7 @@ vector<types::AccountPermission> apply_context::unused_authorizations() const {
return
{
range
.
begin
(),
range
.
end
()};
}
pending_transaction
&
apply_context
::
get_pending_transaction
(
pending_transaction
::
handle_type
handle
)
{
apply_context
::
pending_transaction
&
apply_context
::
get_pending_transaction
(
pending_transaction
::
handle_type
handle
)
{
auto
itr
=
boost
::
find_if
(
pending_transactions
,
[
&
](
const
auto
&
trx
)
{
return
trx
.
handle
==
handle
;
});
EOS_ASSERT
(
itr
!=
pending_transactions
.
end
(),
tx_unknown_argument
,
"Transaction refers to non-existant/destroyed pending transaction"
);
...
...
@@ -59,16 +68,21 @@ pending_transaction& apply_context::get_pending_transaction(pending_transaction:
}
const
int
Max_pending_transactions
=
4
;
const
uint32_t
Max_pending_transaction_size
=
16
*
1024
;
const
uint32_t
Max_pending_transaction_size
=
64
*
1024
;
const
auto
Pending_transaction_expiration
=
fc
::
seconds
(
21
*
3
);
pending_transaction
&
apply_context
::
create_pending_transaction
()
{
apply_context
::
pending_transaction
&
apply_context
::
create_pending_transaction
()
{
EOS_ASSERT
(
pending_transactions
.
size
()
<
Max_pending_transactions
,
tx_resource_exhausted
,
"Transaction is attempting to create too many pending transactions. The max is ${max}"
,
(
"max"
,
Max_pending_transactions
));)
"Transaction is attempting to create too many pending transactions. The max is ${max}"
,
(
"max"
,
Max_pending_transactions
));
pending_transaction
::
handle
handle
=
next_pending_transaction_serial
++
;
pending_transactions
.
push_back
({
handle
});
return
pending_transaction
.
back
();
pending_transaction
::
handle_type
handle
=
next_pending_transaction_serial
++
;
auto
head_block_id
=
controller
.
head_block_id
();
decltype
(
pending_transaction
::
refBlockNum
)
head_block_num
=
fc
::
endian_reverse_u32
(
head_block_id
.
_hash
[
0
]);
decltype
(
pending_transaction
::
refBlockPrefix
)
head_block_ref
=
head_block_id
.
_hash
[
1
];
decltype
(
pending_transaction
::
expiration
)
expiration
=
controller
.
head_block_time
()
+
Pending_transaction_expiration
;
pending_transactions
.
emplace_back
(
handle
,
head_block_num
,
head_block_ref
,
expiration
);
return
pending_transactions
.
back
();
}
void
apply_context
::
release_pending_transaction
(
pending_transaction
::
handle_type
handle
)
{
...
...
@@ -83,17 +97,44 @@ void apply_context::release_pending_transaction(pending_transaction::handle_type
pending_transactions
.
pop_back
();
}
types
::
Transaction
apply_context
::
pending_transaction
::
as_transaction
()
const
{
decltype
(
types
::
Transaction
::
refBlockNum
)
head_block_num
=
chain_controller
.
head_block_num
();
decltype
(
types
::
Transaction
::
refBlockRef
)
head_block_ref
=
fc
::
endian_reverse_u32
(
chain_controller
.
head_block_ref
().
_hash
[
0
]);
decltype
(
types
::
Transaction
::
expiration
)
expiration
=
chain_controller
.
head_block_time
()
+
Pending_transaction_expiration
;
return
types
::
Transaction
(
head_block_num
,
head_block_ref
,
expiration
,
scopes
,
read_scopes
,
messages
);
}
void
apply_context
::
pending_transaction
::
check_size
()
const
{
auto
trx
=
as_transaction
()
;
const
types
::
Transaction
&
trx
=
*
this
;
EOS_ASSERT
(
fc
::
raw
::
pack_size
(
trx
)
<=
Max_pending_transaction_size
,
tx_resource_exhausted
,
"Transaction is attempting to create a transaction which is too large. The max size is ${max} bytes"
,
(
"max"
,
Max_pending_transaction_size
));
}
apply_context
::
pending_message
&
apply_context
::
get_pending_message
(
pending_message
::
handle_type
handle
)
{
auto
itr
=
boost
::
find_if
(
pending_messages
,
[
&
](
const
auto
&
msg
)
{
return
msg
.
handle
==
handle
;
});
EOS_ASSERT
(
itr
!=
pending_messages
.
end
(),
tx_unknown_argument
,
"Transaction refers to non-existant/destroyed pending message"
);
return
*
itr
;
}
const
int
Max_pending_messages
=
4
;
const
uint32_t
Max_pending_message_size
=
4
*
1024
;
apply_context
::
pending_message
&
apply_context
::
create_pending_message
(
const
AccountName
&
code
,
const
FuncName
&
type
,
const
Bytes
&
data
)
{
EOS_ASSERT
(
pending_messages
.
size
()
<
Max_pending_messages
,
tx_resource_exhausted
,
"Transaction is attempting to create too many pending messages. The max is ${max}"
,
(
"max"
,
Max_pending_messages
));
EOS_ASSERT
(
data
.
size
()
<
Max_pending_message_size
,
tx_resource_exhausted
,
"Transaction is attempting to create a pending message that is too large. The max is ${max}"
,
(
"max"
,
Max_pending_message_size
));
pending_message
::
handle_type
handle
=
next_pending_message_serial
++
;
pending_messages
.
emplace_back
(
handle
,
code
,
type
,
data
);
return
pending_messages
.
back
();
}
void
apply_context
::
release_pending_message
(
pending_message
::
handle_type
handle
)
{
auto
itr
=
boost
::
find_if
(
pending_messages
,
[
&
](
const
auto
&
trx
)
{
return
trx
.
handle
==
handle
;
});
EOS_ASSERT
(
itr
!=
pending_messages
.
end
(),
tx_unknown_argument
,
"Transaction refers to non-existant/destroyed pending message"
);
auto
last
=
pending_messages
.
end
()
-
1
;
if
(
itr
!=
last
)
{
std
::
swap
(
itr
,
last
);
}
pending_messages
.
pop_back
();
}
}
}
// namespace eos::chain
libraries/chain/wasm_interface.cpp
浏览文件 @
59b5c209
...
...
@@ -253,33 +253,46 @@ DEFINE_INTRINSIC_FUNCTION0(env,transactionCreate,transactionCreate,i32) {
return
ptrx
.
handle
;
}
DEFINE_INTRINSIC_FUNCTION3
(
env
,
transaction
AddScope
,
transactionAdd
Scope
,
none
,
i32
,
handle
,
i64
,
scope
,
i32
,
readOnly
)
{
DEFINE_INTRINSIC_FUNCTION3
(
env
,
transaction
RequireScope
,
transactionRequire
Scope
,
none
,
i32
,
handle
,
i64
,
scope
,
i32
,
readOnly
)
{
auto
&
ptrx
=
wasm_interface
::
get
().
current_apply_context
->
get_pending_transaction
(
handle
);
if
(
readOnly
==
0
)
{
ptrx
.
scope
s
.
emplace_back
(
scope
);
ptrx
.
scope
.
emplace_back
(
scope
);
}
else
{
ptrx
.
read
_scopes
.
emplace_back
(
scope
);
ptrx
.
read
scope
.
emplace_back
(
scope
);
}
ptrx
.
check_size
();
}
DEFINE_INTRINSIC_FUNCTION3
(
env
,
transactionSetMessageDestination
,
transactionSetMessageDestination
,
none
,
i32
,
handle
,
i64
,
code
,
i64
,
type
)
{
auto
&
ptrx
=
wasm_interface
::
get
().
current_apply_context
->
get_pending_transaction
(
handle
);
ptrx
.
current_destination
=
decltype
(
ptrx
.
current_destination
)({
Name
(
code
),
Name
(
type
)});
DEFINE_INTRINSIC_FUNCTION2
(
env
,
transactionAddMessage
,
transactionAddMessage
,
none
,
i32
,
handle
,
i32
,
msg_handle
)
{
auto
apply_context
=
wasm_interface
::
get
().
current_apply_context
;
auto
&
ptrx
=
apply_context
->
get_pending_transaction
(
handle
);
auto
&
pmsg
=
apply_context
->
get_pending_message
(
msg_handle
);
ptrx
.
messages
.
emplace_back
(
pmsg
);
ptrx
.
check_size
();
apply_context
->
release_pending_message
(
msg_handle
);
}
DEFINE_INTRINSIC_FUNCTION3
(
env
,
transactionAddMessagePermission
,
transactionAddMessagePermission
,
none
,
i32
,
handle
,
i64
,
account
,
i64
,
permission
)
{
wasm_interface
::
get
().
current_apply_context
->
require_authorization
(
Name
(
account
),
Name
(
permission
));
auto
&
ptrx
=
wasm_interface
::
get
().
current_apply_context
->
get_pending_transaction
(
handle
);
ptrx
.
current_permissions
.
emplace_back
(
Name
(
account
),
Name
(
permission
));
DEFINE_INTRINSIC_FUNCTION1
(
env
,
transactionSend
,
transactionSend
,
none
,
i32
,
handle
)
{
auto
apply_context
=
wasm_interface
::
get
().
current_apply_context
;
auto
&
ptrx
=
apply_context
->
get_pending_transaction
(
handle
);
EOS_ASSERT
(
ptrx
.
messages
.
size
()
>
0
,
tx_unknown_argument
,
"Attempting to send a transaction with no messages"
);
apply_context
->
deferred_transactions
.
emplace_back
(
ptrx
);
apply_context
->
release_pending_transaction
(
handle
);
}
DEFINE_INTRINSIC_FUNCTION1
(
env
,
transactionDrop
,
transactionDrop
,
none
,
i32
,
handle
)
{
wasm_interface
::
get
().
current_apply_context
->
release_pending_transaction
(
handle
);
}
DEFINE_INTRINSIC_FUNCTION
3
(
env
,
transactionPushMessage
,
transactionPushMessage
,
none
,
i32
,
handle
,
i32
,
msg_buffer
,
i32
,
msg_size
)
{
DEFINE_INTRINSIC_FUNCTION
4
(
env
,
messageCreate
,
messageCreate
,
i32
,
i64
,
code
,
i64
,
type
,
i32
,
data
,
i32
,
length
)
{
auto
&
wasm
=
wasm_interface
::
get
();
auto
mem
=
wasm
.
current_memory
;
EOS_ASSERT
(
msg_size
>
0
,
tx_unknown_argument
EOS_ASSERT
(
length
>
0
,
tx_unknown_argument
,
"Attempting to push an empty message"
);
const
char
*
buffer
=
nullptr
;
...
...
@@ -287,47 +300,32 @@ DEFINE_INTRINSIC_FUNCTION3(env,transactionPushMessage,transactionPushMessage,non
// memoryArrayPtr checks that the entire array of bytes is valid and
// within the bounds of the memory segment so that transactions cannot pass
// bad values in attempts to read improper memory
buffer
=
memoryArrayPtr
<
const
char
>
(
mem
,
msg_buffer
,
msg_size
);
buffer
=
memoryArrayPtr
<
const
char
>
(
mem
,
data
,
uint32_t
(
length
)
);
}
catch
(
const
Runtime
::
Exception
&
e
)
{
FC_THROW_EXCEPTION
(
tx_unknown_argument
,
"Message data is not
valid
"
);
FC_THROW_EXCEPTION
(
tx_unknown_argument
,
"Message data is not
a valid memory range
"
);
}
auto
&
ptrx
=
wasm
.
current_apply_context
->
get_pending_transaction
(
handle
);
EOS_ASSERT
(
ptrx
.
destination
.
valid
(),
tx_unknown_argument
"Attempting to push a message without setting a destination"
);
auto
&
dest
=
*
ptrx
.
destination
;
ptrx
.
messages
.
emplace_back
(
dest
.
code
,
dest
.
type
,
ptrx
.
current_permissions
,
Bytes
(
buffer
,
buffer
+
msg_size
));
ptrx
.
reset_message
();
ptrx
.
check_size
();
auto
&
pmsg
=
wasm
.
current_apply_context
->
create_pending_message
(
Name
(
code
),
Name
(
type
),
Bytes
(
buffer
,
buffer
+
length
));
return
pmsg
.
handle
;
}
DEFINE_INTRINSIC_FUNCTION1
(
env
,
transactionResetMessage
,
transactionResetMessage
,
none
,
i32
,
handle
)
{
auto
&
ptrx
=
wasm_interface
::
get
().
current_apply_context
->
get_pending_transaction
(
handle
);
ptrx
.
reset_message
();
DEFINE_INTRINSIC_FUNCTION3
(
env
,
messageRequirePermission
,
messageRequirePermission
,
none
,
i32
,
handle
,
i64
,
account
,
i64
,
permission
)
{
auto
apply_context
=
wasm_interface
::
get
().
current_apply_context
;
apply_context
->
require_authorization
(
Name
(
account
),
Name
(
permission
));
auto
&
pmsg
=
apply_context
->
get_pending_message
(
handle
);
pmsg
.
authorization
.
emplace_back
(
Name
(
account
),
Name
(
permission
));
}
DEFINE_INTRINSIC_FUNCTION2
(
env
,
transactionSend
,
transactionSend
,
none
,
i32
,
handle
,
i32
,
mode
)
{
EOS_ASSERT
(
mode
==
0
||
mode
==
1
,
tx_unknown_argument
"Unknown delivery mode when sending transaction: ${mode}"
,
(
"mode"
:
mode
));
DEFINE_INTRINSIC_FUNCTION1
(
env
,
messageSend
,
messageSend
,
none
,
i32
,
handle
)
{
auto
apply_context
=
wasm_interface
::
get
().
current_apply_context
;
auto
&
ptrx
=
apply_context
->
get_pending_transaction
(
handle
);
EOS_ASSERT
(
ptrx
.
messages
.
size
()
>
0
,
,
tx_unknown_argument
"Attempting to send a transaction with no messages"
);
if
(
mode
==
0
)
{
apply_context
->
deferred_transactions
.
emplace_back
(
ptrx
.
as_transaction
());
}
else
{
apply_context
->
inline_transactions
.
emplace_back
(
ptrx
.
as_transaction
());
}
auto
&
pmsg
=
apply_context
->
get_pending_message
(
handle
);
apply_context
->
release_pending_transaction
(
handle
);
apply_context
->
inline_messages
.
emplace_back
(
pmsg
);
apply_context
->
release_pending_message
(
handle
);
}
DEFINE_INTRINSIC_FUNCTION1
(
env
,
transactionDrop
,
transaction
Drop
,
none
,
i32
,
handle
)
{
wasm_interface
::
get
().
current_apply_context
->
release_pending_
transaction
(
handle
);
DEFINE_INTRINSIC_FUNCTION1
(
env
,
messageDrop
,
message
Drop
,
none
,
i32
,
handle
)
{
wasm_interface
::
get
().
current_apply_context
->
release_pending_
message
(
handle
);
}
/**
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录