Substrate交易实现流程(1)
Substrate把交易分成两种类型,一种由用户生成,称之为extrinsic,另一种由substrate自己生成,称之为inherent data。
用户通过调用Substrate的RPC接口与Substrate交互。Substrate系统提供author、chain、state和system默认的 RPC接口,开发者也可以自定义RPC供用户使用。
1 发起交易
用户通过调用author模块的author_submitExtrinsic函数或者author_submitAndWatchExtrinsic函数发起一笔交易。二者的区别是后者除了提交一笔交易还要把交易的执行结果返回给调用方。这里以前者为例来说明交易的实现流程。
![](https://img.haomeiwen.com/i12133671/b59057f3965e3fb3.png)
实现author_submitExtrinsic接口的是submit_extrinsic方法,它接收一个16进制编码的交易字节流的参数。
![](https://img.haomeiwen.com/i12133671/c3311653ef4d971d.png)
submit_extrinsic方法首先解码交易数据,然后调用submit_one方法将这笔交易放进交易池(transaction pool),submit_one则直接调用submit_at方法。submit_one和submit_at的区别是前者只处理单笔交易,后者可批量处理。
![](https://img.haomeiwen.com/i12133671/408d7af3fe95d489.png)
由代码可以看出,submit_at完成两件事情,一是验证(verify)每笔交易,二是如果验证通过,把它提交(submit)到交易池里。下面分别介绍。
2 验证交易
verify方法对传进来的每笔交易调用verify_one进行验证:
![](https://img.haomeiwen.com/i12133671/6f009585608241ac.png)
verify_one进一步调用ChainApi里的validate_transaction方法来验证一笔交易。
![](https://img.haomeiwen.com/i12133671/41b508b93a31be5d.png)
Substrate里验证交易的逻辑是在runtime实现的,所以会看到validate_transaction进一步调用runtime里的validate_transaction api:
![](https://img.haomeiwen.com/i12133671/2536d2ad3bb1d0be.png)
每个runtime实现验证交易的逻辑会有不同,在substrate提供的模版runtime实现里,validate_transaction的代码如下:
![](https://img.haomeiwen.com/i12133671/8ccc14dd320a9dd7.png)
其中Executive是runtime里的执行调度器,具体实现在executive frame里:
![](https://img.haomeiwen.com/i12133671/dbdb19ed3e622d87.png)
Executive的validate_transaction对交易数据先check再validate。check函数的实现在primitives/runtime/src/generic/unchecked_extrinsic.rs里:
![](https://img.haomeiwen.com/i12133671/fa6519ec15f84833.png)
check函数的主要功能是,对于包含签名的交易,它验证签名是否正确。无论交易是否包含签名,最终会返回一笔已经checked的交易。
而validate函数的实现在primitives/runtime/src/generic/checked_extrinsic.rs里,它对checked的交易做进一步处理:
![](https://img.haomeiwen.com/i12133671/94a6b3d7e1777882.png)
对于已经签名的交易调用Extra::validate函数。这里的Extra是system frame。system frame 里实现validate的代码:
![](https://img.haomeiwen.com/i12133671/c5d890675a4d5d3f.png)
因为已经验证过签名,这里只检查账户的nonce。检查完毕,返回一笔有效的交易。
对于不包含签名的交易,首先调用Extra::validate_unsigned函数,再调用U::validate_unsigned函数。这里的U是support frame。Extra::validate_unsigned主要是检查交易所在的区块高度是否正确、交易数据长度是否超限。下面是U::validate_unsigned的代码(在frame/support/src/unsigned.rs里):
![](https://img.haomeiwen.com/i12133671/e3de5ea5834e3b14.png)
这是一段用rust宏写的代码,它调用了module里的validate_unsigned函数。就是说,对于不包含签名的交易,签名的验证逻辑由模块的实现者完成。下面是一个简单的例子:
![](https://img.haomeiwen.com/i12133671/16377336c2b7f59b.png)
这里模块实现了ValidateUnsigned Trait的validate_unsigned方法来对签名进行校验。如果检验通过,则返回一笔有效的交易。它被上面定义的宏调用。
至此,验证交易完成。
-------------
***转载请注明出处