转载自:https://blog.csdn.net/karizhang/article/details/79110981

背景

geth源码一直在不断增加,优化,发展到现在已经非常庞大,第一次看geth源码,会有不小的难度。虽然如此,还是可以从geth仓库的第一个commit开始,这时的代码比较少,但是以太坊核心的雏形已经隐隐可见,阅读代码可以加深理解以太坊的模块组成,揣测设计的想法和思路。

项目结构

去掉单元测试文件,整个项目只有 
big.go 
vm.go 
parsing.go 
transaction.go 
block.go 
block_manager.go 
ethereum.go 
serialization.go 
8个文件。这8个文件都比较小,功能比较简单,也很好理解。

数学计算

big.go 封装了大整数的指数运输。

虚拟机

vm.go 定义了虚拟机操作码, 操作码类型, 虚拟机结构和虚拟机的实现。 
虚拟机内部定义的指令码有:

  oSTOP      int = 0x00oADD       int = 0x10oSUB       int = 0x11oMUL       int = 0x12oDIV       int = 0x13oSDIV      int = 0x14oMOD       int = 0x15oSMOD      int = 0x16oEXP       int = 0x17oNEG       int = 0x18oLT        int = 0x20oLE        int = 0x21oGT        int = 0x22oGE        int = 0x23oEQ        int = 0x24oNOT       int = 0x25oSHA256    int = 0x30oRIPEMD160 int = 0x31oECMUL     int = 0x32oECADD     int = 0x33oSIGN      int = 0x34oRECOVER   int = 0x35oCOPY      int = 0x40oST        int = 0x41oLD        int = 0x42oSET       int = 0x43oJMP       int = 0x50oJMPI      int = 0x51oIND       int = 0x52oEXTRO     int = 0x60oBALANCE   int = 0x61oMKTX      int = 0x70oDATA      int = 0x80oDATAN     int = 0x81oMYADDRESS int = 0x90oSUICIDE   int = 0xff

总共36个指令码,细心的读者可能会发现指令码定义的值不是连续的,是跳跃的,通过通读代码分析,原因是指令码值的高位是记录指令类型。 
vm的实现是基于栈的,实现相对比较简单。 
大部分指令码的功能没有实现,只实现了以下指令码的功能 
oSTOP 
oADD 
oSUB 
oMUL 
oDIV 
oSET 
oLD 
oLT 
oJMP 
oJMPI

智能合约编译

parsing.go 主要实现的是智能合约的编译和对编译后的代码进行处理,后续供vm执行。

交易

transaction.go 定义了交易的结构,还有费用和收益变量。一笔交易包括发起者,接受者,交易的数量,交易的费用,编译后的脚本源码, 运行需要内存,交易签名 和 地址。 
费用和收益变量只有初始化赋值,没有具体使用。 
脚本源码是智能合约的雏形,为了方便描述和理解还是称呼它为智能合约。此时的智能合约语言和x86 intel汇编类似, 语法比较简单,一个操作指令加上操作数,操作数的个数最常见是0个,1个,2个和3个,设计者实现的时候,最多可以支持6个。 
操作指令和操作数之间用空格分开,操作数与操作数之间也用空格分开。 
定义的操作指令有以下这些:(记作 映射表1)

  "STOP":       "0","ADD":        "16",  // 0x10"SUB":        "17",  // 0x11"MUL":        "18",  // 0x12"DIV":        "19",  // 0x13"SDIV":       "20",  // 0x14"MOD":        "21",  // 0x15"SMOD":       "22",  // 0x16"EXP":        "23",  // 0x17"NEG":        "24",  // 0x18"LT":         "32",  // 0x20"LE":         "33",  // 0x21"GT":         "34",  // 0x22"GE":         "35",  // 0x23"EQ":         "36",  // 0x24"NOT":        "37",  // 0x25"SHA256":     "48",  // 0x30"RIPEMD160":  "49",  // 0x31"ECMUL":      "50",  // 0x32"ECADD":      "51",  // 0x33"SIGN":       "52",  // 0x34"RECOVER":    "53",  // 0x35"COPY":       "64",  // 0x40"ST":         "65",  // 0x41"LD":         "66",  // 0x42"SET":        "67",  // 0x43"JMP":        "80",  // 0x50"JMPI":       "81",  // 0x51"IND":        "82",  // 0x52"EXTRO":      "96",  // 0x60"BALANCE":    "97",  // 0x61"MKTX":       "112", // 0x70"DATA":       "128", // 0x80"DATAN":      "129", // 0x81"MYADDRESS":  "144", // 0x90"BLKHASH":    "145", // 0x91"COINBASE":   "146", // 0x92"SUICIDE":    "255", // 0xff

可以看出这是操作指令到虚拟机内部指令码的映射。 
编译规则很简单: 
1. 操作指令根据映射表1, 得到vm的内部指令码。 
2. 每一个操作数(第i个操作数,i记作位置序数, 从1开始)分别乘以 256的i次方, 
3. 将步骤2的乘积依次相加,最后加上步骤1得到的指令, 最终的和作为编译结果。 
一个合法的智能合约源码片段可能是这样(记作 代码片段1)

    "SET 10 6","LD 10 10",

按照编译规则,代码片段1最终的编译结果是这样的

395843    // 67 + 10 * 256 + 6 * 256^2
133698    // 66 + 10 * 256 + 10 * 256^2

vm运行时,根据编译规则的逆规则,解析出指令码和操作数,根据指令码的功能,进行下一步处理。 
运行需要内存没有使用,猜测是用作运行智能合约。 
签名字段没有使用,猜测是校验交易是否篡改过。 
地址是对transaction结构序列化后的字节数组取sha256的前20位。

区块

block.go用来定义块结构,非常简单,仅包含一个transaction数组.

区块管理器

block_manager.go是定义块管理器,用来处理块,持有一个vm指针,依次执行块里面的每一个交易的智能合约。

以太坊入口

ethereum.go是demo程序入口, mock两笔交易,打印vm执行的日志,最后打印了其中一笔交易的序列化结果。

交易序列化

serialization.go 实现序列化功能,采用的是RLP编码,只能对字符串编码。编码规则是 
1. 如果是字符串,编码结果是”\x00” 加上字符串的长度,再加上原字符串。计算字符串的长度有一个规则,确保编码无二义性,能正确解码。 
2.如果是字符串数组,编码结果是”\x01”加上每一个字符串编码结果的长度和的编码,再加上每一个字符串的编码结果。有点绕口,这是个递归的过程。 
3.如果是其他类型需要转换成字符串或者字符串数组。 
RLP编码的规律是以数据类型开始,字符串是”\x00”, 字符串数组是”\x01, 然后是数据长度,最后是数据内容。 
RLP编码和解码是递归过程,实现比较简单,编码紧凑,传输效率较高,后续版本中,在网络传输和本地存储都有RLP编码的影子。

总结

总体来说,这个版本的代码比较简单,是geth的初始设计和验证,没有实现太多的功能,比喻账号,P2P网络,共识算法等都没有实现,区块链,编译器和虚拟机也设计比较简单,与正式发布版差异比较大,不过对于初次学习geth源码,整体认识geth还是有一定的意义。

以太坊源码学习(一)相关推荐

  1. 以太坊源码学习 -- EVM

    以太坊源码学习 – EVM 学习文档链接:here 一.虚拟机外 主要功能: 执行前将Transaction类型转化成Message,创建虚拟机(EVM)对象,计算一些Gas消耗,以及执行交易完毕后创 ...

  2. 以太坊源码学习(一) 正本清源

    以太坊源码学习(一)正本清源 背景 geth源码一直在不断增加,优化,发展到现在已经非常庞大,第一次看geth源码,会有不小的难度.虽然如此,还是可以从geth仓库的第一个commit开始,这时的代码 ...

  3. 以太坊源码学习—RLP编码

    [原文]:https://segmentfault.com/a/1190000011763339 RLP(Recursive Length Prefix),中文翻译过来叫递归长度前缀编码,它是以太坊序 ...

  4. kademlia java_死磕以太坊源码分析之Kademlia算法

    死磕以太坊源码分析之Kademlia算法 KAD 算法概述 Kademlia是一种点对点分布式哈希表(DHT),它在容易出错的环境中也具有可证明的一致性和性能.使用一种基于异或指标的拓扑结构来路由查询 ...

  5. 3 v4 中心节点固定_死磕以太坊源码分析之p2p节点发现

    死磕以太坊源码分析之p2p节点发现 在阅读节点发现源码之前必须要理解kadmilia算法,可以参考:KAD算法详解. 节点发现概述 节点发现,使本地节点得知其他节点的信息,进而加入到p2p网络中. 以 ...

  6. 以太坊源码分析-交易

    以太坊源码分析-交易 机理 先说一点区块链转账的基本概念和流程 用户输入转账的地址和转入的地址和转出的金额 系统通过转出的地址的私钥对转账信息进行签名(用于证明这 笔交易确实有本人进行) 系统对交易信 ...

  7. php区块链以太坊,兄弟连区块链教程以太坊源码分析CMD深入分析(一)

    兄弟连区块链教程以太坊源码分析CMD深入分析. cmd包分析 cmd下面总共有13个子包,除了util包之外,每个子包都有一个主函数,每个主函数的init方法中都定义了该主函数支持的命令,如 geth ...

  8. 以太坊源码阅读3——MPT原理

    以太坊源码阅读3--MPT原理 介绍 MPT(Merkel-Patricia Tree),翻译为梅克尔-帕特里夏树 MPT提供了一个基于密码学验证的底层数据结构,用来存储键值对( key-value) ...

  9. 以太坊源码阅读2——RLP编码

    以太坊源码阅读2--RLP编码 RLP介绍 目前网上的资料都是RLP(Recursive Length prefix),叫递归长度前缀编码,但目前源码的doc.go的第20行里面的注释写的是 The ...

最新文章

  1. matlab结果输出的代码,哪位大神能帮我看一下下列代码输出的结果是啥!
  2. 十字消源码分享(基于libgdx开发)
  3. python matplotlib.pyplot plt.ioff()函数(关闭交互模式用于阻塞程序,不让图片关闭)
  4. 服务器监控工具_系统管理员不可错过的 6 款服务器监控工具
  5. 互联网1分钟 |1128
  6. 信道分配 以太网
  7. 求出所有这些四位数是素数的个数cnt,再把所有满足此条件的四位数依次存入数组b中,然后对数组b中的四位数按从小到大的顺序进行排序
  8. Handler源码解析2
  9. pytorch 对抗样本_【天池大赛】通用目标检测的对抗攻击方法一览
  10. Linux初级入门百篇-​LVM 简介
  11. 2021 年全球知名开源项目
  12. 以太坊交易的打包规则
  13. 文件无法复制到c盘的解决办法
  14. 数学建模国赛拿奖关键tips,错过这7条可能与国奖无缘!
  15. 开源BI工具对比(二):宜信 davinci
  16. 北大计算机前辈徐,九年中获得国家最高科学技术奖的八位北大人
  17. Baker Tilly与RGL Forensics宣布合并
  18. 紧贴潮流,初心未改:OpenInfra Days China升级回归,打造专属OpenStackers的开源大趴
  19. jQuery实现消息列表循环垂直向上滚动
  20. 解决腾讯文档使用收集表收集图片,图片无法批量保存到本地问题

热门文章

  1. python import _ssl_Python 3没有名为’_ssl’的模块
  2. matlab求两向量夹角_高等数学之向量代数与空间解析几何知识点与题型总结
  3. linux未设置为接受端口,Simple gawk server
  4. Win-MASM64汇编语言-visual studio下环境搭建
  5. 4.7_singleton_创建型模式:单例模式
  6. 不在gopath目录下能使用godoc吗_一文搞懂 Go Modules 前世今生及入门使用
  7. 美团面经-java开发
  8. R 指定安装镜像的方法
  9. C# 高效率创建字符串类(StringBuilder)
  10. 动态延迟加载网页元素jQuery插件scrollLoading