通讯模型
EOSIO智能合约由一组 action 和 type 的定义(definitions)组成.action的定义指定并实现了合约中的行为.type的定义指定了所需的内容及结构.EOSIO的actions主要在基于消息的通讯结构中执行.客户端可以通过发送(推送)信息到nodeos
来执行actions.这可以通过使用cleos
命令来完成.也可以通过EOSIO的send
方法之一来完成(例如:eosio::action::send
).nodeos
将请求分派给实现合约的WASM代码.该代码完整运行,然后继续处理下一个操作.
EOSIO智能合约能与其他合约进行交互,例如,让另一个合约执行能让当前交易完成的某些相关操作,或者触发一个当前合约范围外的未来交易.
EOSIO支持两种基本的通讯模型,inline和deferred.例如一个执行当前交易的操作是inline action,一个触发未来交易的操作是deferred action.
合约间的通讯应该考虑到异步的情况.异步通讯模型可能会导致spam,资源限制算法会解决这个问题.
Inline Communication
Inline communication采用请求其他操作的形式,这些操作需要作为当前调用操作的一部分执行.Inline actions在原始交易相同的范围与授权执行操作,并保证在当前交易执行.他们可以有效地被认为是调用事务中的嵌套事务.如果该交易的任何一步失败了,inline actions将会和其他部分解绑.无论成功与否,调用inline actions都不会再事务范围之外产生任何通知.
Deferred Communication
Deferred communication在概念上采用将action通知发送到对等交易的形式.根据生产者的判断,Deferred actions将按计划执行,最好的情况是在之后执行.deferred action不能保证一定会被执行.
就像刚刚提到的一样,deferred communication将会根据生产者的判断被安排在之后执行.从原始交易的角度来看,即创建deferred transaction的transaction,它只能判断创建出来的请求是否已经成功提交或是否失败(如果失败,则会立即失败).Deferred transactions能携带发送给他们的权限.交易能取消deferred transaction.
Transactions VS. Action
每个action代表一个独立的操作,transaction是一个或多个action的集合.合约和账号以action的形式进行通讯.如果actions将作为一个整体被执行,它们能被单独的或组合的形式发送.
单个action的transaction:
{
"expiration": "2018-04-01T15:20:44",
"region": 0,
"ref_block_num": 42580,
"ref_block_prefix": 3987474256,
"net_usage_words": 21,
"kcpu_usage": 1000,
"delay_sec": 0,
"context_free_actions": [],
"actions": [{
"account": "eosio.token",
"name": "issue",
"authorization": [{
"actor": "eosio",
"permission": "active"
}
],
"data": "00000000007015d640420f000000000004454f5300000000046d656d6f"
}
],
"signatures": [
""
],
"context_free_data": []
}
多个actions的交易,这些actions必须全部成功,否则transaction将会失败:
{
"expiration": "...",
"region": 0,
"ref_block_num": ...,
"ref_block_prefix": ...,
"net_usage_words": ..,
"kcpu_usage": ..,
"delay_sec": 0,
"context_free_actions": [],
"actions": [{
"account": "...",
"name": "...",
"authorization": [{
"actor": "...",
"permission": "..."
}
],
"data": "..."
}, {
"account": "...",
"name": "...",
"authorization": [{
"actor": "...",
"permission": "..."
}
],
"data": "..."
}
],
"signatures": [
""
],
"context_free_data": []
}
Context-Free Actions
Action Name Restrictions
Action类型是 base32编码的64-bit 整数类型.这意味着它们的前12个字符被约束在 a-z
,1-5
以及.
如果有第十三个字符,那么它被严格约束为前16个字符(.
和a-p
).
更详细的资料请看 link here.
Transction Confirmations
当交易完成,交易的收据生成出来.该收据采用hash的形式.收到交易hash并不意味该交易已经被确认,只意味着节点在没有出错的情况下接收了它,也意味着有很大的可能性有其他的见证者会接收它.
为了确认它是否被确认,你应该在交易历史记录中看到包含有block number的该事务.
Action Handlers and Action "Apply" Context
智能合约提供action handlers处理请求actions的工作.每当一个action执行,例如,action通过执行合约中实现的apply
被"applied",EOSIO创建了一个新的action"apply"上下文来让该action运行.下图解释了action "apply"上下文的关键元素.
从EOSIO区块链的全局来看,EOSIO网络的每个节点都能获得每一个合约的每一个函数的并会运行.一些节点会真正的执行这些合约,其他的这么做只是为了验证交易区块.因此,重要的是合同有能力知道"他们是谁",或者基础的来说,它们是在什么上下文运行.上下文定义信息在action上下文提供,就如上图所示,通过receiver
,code
,action
. receiver
是当前处理该action的account.code
是是授权合约的account.action
是当前运行action的ID.
就如上面所述,action的操作是和transactions一起的;如果transaction失败了,所有该transaction的action的结果都会被回滚.action上下文的主要部分是当前Transation的数据.它包含了transaction header,一个当前交易的所有原始actions的ordered vector,交易中context free actions的vector,通过实现该合约的代码提供的一组可以打印context free data(vector的blobs提供的),以及blobs的vector的全索引.
在执行一个action之前,EOSIO会为该action配置一个干净的工作内存区.action操作的变量将会存储于此.action的工作内存区只对该action可用,即使是该transaction的其他action也不行.当另一个action在它的上下文不可用时变量可能已经被设定了.通过actions传递状态的唯一途径是使用EOSIO database.查看Persistence API获取更多如何使用EOSIO persistence services的细节.
action会产生许多副作用,例如:
- 改变EOSIO persistent storage已经持久化的状态
- 通知当前交易的收据
- 发送inline action请求到一个新的接收者
- 生成一个新的(deferred)交易
- 取消退出(in-flight)deferred transactions(例如:取消已经提交的deferred transaction requests)
Transaction Limitations
每一个transaction必须在30ms内执行完毕.如果一个transaction包含数个actions,这些actions如果耗时超过30ms,那么该transaction将会失败.在这些actions没有并发需求的情况下,可以通过在单独的transaction中包含CPU来consuming actions.