Neo编译器

上一篇区块链研究方案
先整理一下Neo编译器的知识吧。git

项目连接

  1. Neo自己是开源的,在github搜索就能够拿到源码,我为了方便调试,把全部代码都放在一块儿。https://github.com/benhaben/n...
  2. Neo是C#开发的,大部分代码能够跨平台,可是也有不能再mac上运行的代码,好比改装后的leveldb的代码,因此最好仍是用VisualStudio在windows上调试研究较好。
  3. 本文档主要是总结本身所研究的东西,如今不太规范,主要考虑好理解,并不完善,后面也能够进一步规范化提交到neo项目中。

主框架

clipboard.png
框架程序员

你们能够看到Compiler所处的位置github

Compiler做用

  1. 在Neo区块链系统中,智能合约是一段代码,能够完成必定的逻辑,最后算出合约的结果。如今已经有不少具体的应用了,感兴趣的能够看一下基于Neo作的项目。
  2. 若是对比特币或者智能合约不了解,不知道为何须要有这些代码,能够看一下比特币的白皮书。这里简单说一下,在比特币系统中,当一个“人”(能够当作一个公钥)须要和另外一个“人”产生交易的时候,这段代码用来检查身份,分配比特币。具体的了解能够看一下普林斯顿的公开课
  3. 下面进入到Neo compiler的介绍了,前面所需的基础知识本文不在关注。

Compiler的框架

下面的图主要显示代码的主要流程:算法

clipboard.png
基本的流程windows

  1. Neo能够用各类语言写,不过如今主要是C#。
  2. Neo的编译器主要是一个翻译器
  3. C#代码被C#编译器编译成MSIL,对MSIL的理解能够查看Standard ECMA-335 Common Language
    Infrastructure (CLI)
  4. Neo compiler使用Mono.Cecil读取IL
  5. Neo编译器只关注C#中的static function,因此只是C#语言的一个超级阉割版
  6. Neo的编译器遍历IL,根据语义转成Neo虚拟机的opcode
  7. 至于MSIL向neo.vm的opcode怎么转,须要仔细研究neo.vm的opcode的设计

Compiler工做一个具体事例

先看一段智能合约代码框架

这段代码没有什么实际的做用,就是返回a+b,可是main能够接受参数。函数

using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;

public class Sum : SmartContract
{
    public static int Main(int a, int b)
    {
        return a + b;
    }
}

MSIL

main function IL code区块链

IL_0000 Nop
IL_0001 Ldarg_0
IL_0002 Ldarg_1
IL_0003 Add
IL_0004 Stloc_0
IL_0005 Br_S
IL_0007 Ldloc_0
IL_0008 Ret

这段代码很简单,就是读取参数Ldarg_0,Add,返回。能够看到CLR的虚拟机也是堆栈虚拟机。
关于基于栈的虚拟机和基于寄存器的虚拟机能够看一下这些文章:
栈式虚拟机和寄存器式虚拟机
另外还有一篇概念讲解的很详细的文章虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩spa

neo.compiler

为了感性的认识neo编译器作了什么,咱们能够看一下上面的只能合约被翻译成了什么翻译

hex:53-C5-6B-6C-76-6B-00-52-7A-C4-6C-76-6B-51-52-7A-C4-61-6C-76-6B-00-C3-6C-76-6B-51-C3-93-6C-76-6B-52-52-7A-C4-62-03-00-6C-76-6B-52-C3-61-6C-75-66

其实是一串数字了,每一个数字对应一个vm的操做码或者是数值,为了更好理解,把汇编代码放出来

PUSH4
PUSH3
RET
PUSH3
NEWARRAY
TOTALSTACK
FROMALSTACK
DUP
TOALTSTACK
PUSH0
PUSH2
ROLL
SETITEM
FROMALSTACK
DUP
TOTALSTACK
PUSH1
PUSH2
ROLL
SETITEM
NOP
FROMALSTACK
DUP
TOTALSTACK
PUSH0
PICKITEM
FROMALSTACK
DUP
TOTALSTACK
PUSH1
PICKITEM
ADD
FROMALSTACK
DUP
TOTALSTACK
PUSH2
PUSH2
ROLL
SETITEM
JMP
FROMALSTACK
DUP
TOTALSTACK
PUSH2
PICKITEM
NOP
FROMALSTACK
DROP
ret

neo汇编的说明,能够查看这个文档

咱们能够发现以下状况:

  1. MSIL的代码很短,Neo.VM的代码很长,这是因为虚拟机的指令和能力不一样形成的。咱们只须要关注,汇编代码处理了局部变量的存贮获取,参数的传递,程序的退出,还有add指令。
  2. 汇编代码和compiler的生成算法相关,须要咱们去同时研究neo的编译器和虚拟机,才能明白具体的细节。
  3. 具体每一行的含义,怎么执行的,能够查看这个文档
  4. 后面还会有一个讲解虚拟机的文章,到那个时候在仔细说明

neo.compiler代码阅读指南

代码阅读仍是很头痛的,因此作了两个脑图:

  1. compiler执行脑图
  2. compiler对象关系

clipboard.png
对象关系

  1. ILModule是对MSIL的一个映射,包含模块,类型,函数,字段,函数中又包含返回值,参数,函数体,能够点开脑图一层一层查看。
  2. Mono.Cecil是使用来读取MSIL的,他也是对MSIL的一个映射,因为没有文档,只能看代码知道他的类结构了,这一部分在脑图中没有显示,不过不要紧,compiler会把感兴趣的代码转成ILModule
  3. ModuleConverter用来遍历ILModule,把里面的MSIL转成Neo.VM的代码,存贮在NeoModule
  4. 具体两边的指令如何对应,真是须要一个一个理解的,很是繁琐,两边都有不少的指令。能够看看这个代码

总结

看完这个文章,并不能了解到具体的细节,具体的细节已经在代码中,这篇文章的主要目的是提供不少资料,提供大的框架,帮助对Neo.Compiler感兴趣的程序员加速阅读代码的速度。

做者:沈寅
原文连接:https://www.jianshu.com/p/646...