以太坊 交易发送
交易由客户通过客户端软件发送。
下图为客户端软件通过 web3 与向网络发送交易的示意图。
通过 web3 发送交易
交易分为简单的转账交易与智能合约调用,收到交易请求的节点进行相应的余额变更或者执行合约代码,在这个过程中是要消耗计算机算力、 内存与占用硬盘存储空间的。
相应地,该交易发起者也需要支付交易费来承担该计算行为,交易是用以太币支付的。
用户与以太坊互动的行为只有一种:发送交易。 以太坊上的交易活动是由三个步骤完成的:
- 用户签名打包一条或多条消息,组装成一笔交易,发送到以太坊网络上。
- 该交易被矿工捕获,并收纳入某一个区块。
- 区块形成后,被矿工广播到节点网络中,最终加入区块链。
用户所使用的手机 App 软件可以代替用户管理账户的细节、检查地址、检查签名的合规性。常见的客户端软件诸如前文提到的 Mist、imToken 等,它们代劳了“组装一笔交易”的步骤。组装完毕后,客户端程序需要和某一个以太坊网络的节点通信,才能将交易信息传递到网络,被矿工捕获。
Warning
web3.js 从2018年中到2019年初,已经快速从0.21.0稳定版本演化到1.0.0 Beta版本, 它规定了交易签名、合约创建、余额查询还有账户管理等实用接口规范,这套规范也能被其他语言所实现。
升级还将原来库中同步调用的操作在 1.0.0-Beta 37 中全部更改为基于 Promise 的异步操作。这会影响到使用该库的JS程序的代码逻辑,请选择库版本时特别小心。
本书后续章节的演示也根据 1.0.0 Beta 版本进行讲解。
交易与消息的区别
在以太坊中,经常混淆的两个概念是交易transaction与消息message。
有人用外部交易与内部交易来解释这两个概念,这是不够完整的认识。
交易 是外部账户发起的,可以包含一条消息。
消息 在账户与账户之间传递数据(data)与价值(value),消息的具体表现形式如下:
- 数据:一个账户向另一个账户请求函数调用。
- 价值:一个账户向另一个账户发送以太币。
消息的确可以由外部账户通过请求一次交易来触发。但是,被作用的对象如果是一个智能合约的话, 它还可以进一步调用其他的合约 (进一步发送消息);
举例说明:某用户调用了智能合约A的一个方法。可能会依序发生如下的效果:
- A合约代码被运行,该方法中调用了另一个智能合约B的一个方法。(函数调用)
- B合约代码被运行。运行中要给账户C 转账以太币。(价值转移)
- 以上的函数调用和价值转移这类消息并不是外部可见的,不记录在区块里。
根据以太坊黄皮书中的定义:
Transaction: A piece of data, signed by an External Actor. It represents either a Message or a new Autonomous Object. Transactions are recorded into each block of the blockchain.
交易: 一段数据,由外部账户持有人签名发起。交易内包含了一个消息或一个新的自治实体(智能合约)。交易将会包含在区块链的区块中
Message: Data (as a set of bytes) and Value (specified as Ether) that is passed between two Accounts, either through the deterministic operation of an Autonomous Object or the cryptographically secure signature of the Transaction.
消息:是用于在两个账户之间传递数据(一组byte)和价值(以太币)的载体。消息由自治实体(智能合约)在运行时产生,也可以由外部签名的交易产生。
交易的特性是什么?
“原子性”
如果将区块链看作是一个巨型分布式数据库,一次交易就是执行对该数据库的一次修改操作。例如某智能合约在执行的过程中修改了一个或者数个外部账户的余额。 这些修改操作要么完全执行,要么完全不执行 ,它不会部分执行,部分不执行。哪怕智能合约在执行某些操作后出现异常而失败,之前执行成功的部分操作也会被“回滚”来撤销影响,这就叫“原子性”。
“串行” 执行
每一笔交易都会影响世界状态的一小部分,它们发生影响的顺序不是同时的,而是一个接一个的,单一时刻只有一个交易被执行,不会有并行出现。哪怕归入了同一个区块的数笔交易,在以太坊虚拟机上也有先后的执行顺序,并不会在虚拟机中多线程并发执行。
“进入区块链的顺序不确定”
当全球的数万名用户向区块链中的节点发送交易时,交易最终进入区块链的顺序并不取决于发送的前后顺序。消息在因特网上广播扩散的快慢,交易费用的高低等诸多因素影响着交易最终进入区块链的顺序。负责记账的矿工因为受到共识规定的约束,所以打包出来的区块内含的多个交易也可能有顺序上的排列组合的考量。某个矿工成功打包的区块有可能不能入选最终的区块链,导致用户的交易没有在第一时间进入区块链,此时用户交易会临时等待,直到进入被另一个矿工捕获被打包。 我们举一个例子:如下图所示,用户发出的一笔 交易A,同时被三个矿工捕获,并且和 B、C、D、E交易自由地组合在一起执行打包形成一个区块。三位矿工分别选取了任意的三条交易进行组合打包,最快被打包完成的区块胜选并进入区块链,成为最新的区块,其余两个矿工的打包完成的区块则未能入选。
在这种情形下,交易A 何时进入区块链,是否能在交易B 之前,是不确定的。
下一章:以太坊 交易方法
我们用 web3.js 代发的交易都是很简单的结构,寥寥数个字段。{ nonce: web3.toHex(10), GasPrice: web3.toHex(100000000000), Gas: web3.toHe ...