Hyperledger Burrow由Linux基金会托管,最初由Monax设计,Monax是一个开放平台,可为企业生态系统构建,交付和运行基于区块链的应用程序。著名的处理器和芯片制造商英特尔也共同赞助了该项目。

Hyperledger Burrow充当许可的智能合约应用程序引擎,其主要工作是以安全有效的方式执行和处理智能合约程序。它是为支持特定于应用程序的优化的多链环境而构建的。

以太坊等许多区块链网络都支持智能合约,自行执行的合约,这些合约的合约条款直接写入代码中。简而言之,Hyperledger Burrow充当智能合同解释器,促进遵循以太坊虚拟机(EVM)标准的网络上此类合同的执行。EVM使用全球公共节点网络执行以太坊智能合约脚本。Burrow充当区块链上的一个节点,该区块链使用EVM标准来提供各种智能合约交易的结论性和高交易吞吐量。

Hyperledger Burrow包含以下组件:

共识引擎负责在区块链上订购和处理各种交易,并确保高交易量输出。它具有一组内置的事务验证器,还可以防止任何可能的恶意企图来破解和分叉区块链。共识引擎与智能合约应用程序无关,因为另一层应用程序区块链接口(ABCI)将两者分开,从而确保了核心引擎与各种应用程序(有时可能包括恶意应用程序)之间的安全性。

每当在区块链网络上发生的交易要求执行智能合约代码时,智能合约应用程序(SCA)组件都会在许可的EVM中激活该帐户代码的必要执行。EVM的工作是确保执行应用程序的代码遵守以太坊操作代码规范,并正确授予所需的权限。Burrow通过EVM模块支持合约的执行与调用,调用时根据合约地址获取到代码,生成环境后载入到EVM中运行。通常智能合约的开发流程是用solidlity编写逻辑代码,再通过编译器编译元数据,最后再发布。

虽然Burrow遵循以太坊虚拟机标准,但是其EVM的设计与以太坊的虚拟机还是有一定差别。

Burrow EVM

Hyperledger Burrow 的EVM代码存放于execution\evm中。

其结构:

Burrow EVM 其他部分与以太坊虚拟机差别不大,都是基于栈的虚拟机,其中:
•contract.go 定义了智能合约的数据结构
•evm.go 定义了执行器,以及对外提供一些外部接口
•memory.go 定义了EVM的内存
•stack.go 定义了EVM的栈

gas

其gas花费代码位于execution\native\gas.go中,与以太坊虚拟机不同,Burrow EVM每次花费固定为1:

智能合约

合约是EVM智能合约的存储单位也是解释器执行的基本单位,包含了代码,调用人,所有人,gas相关的信息。定义于native\contract.go中:

type Contract struct {// Comment describing purpose of native contract and reason for assembling// the particular functionsComment string// Name of the native contractName          stringfunctionsByID map[abi.FunctionID]*Functionfunctions     []*Functionaddress       crypto.Addresslogger        *logging.Logger
}

执行环境

执行入口定义在evm.go中,功能是组装执行环境(代码,执行人关系,参数等)。同样需要创建调用对象的state,但参数稍有不同,这里没有考虑别人合约可能需要花钱。

func (vm *EVM) Execute(st acmstate.ReaderWriter, blockchain engine.Blockchain, eventSink exec.EventSink,params engine.CallParams, code []byte) ([]byte, error) {// Make it appear as if natives are stored in statest = native.NewState(vm.options.Natives, st)state := engine.State{CallFrame:  engine.NewCallFrame(st).WithMaxCallStackDepth(vm.options.CallStackMaxDepth),Blockchain: blockchain,EventSink:  eventSink,}output, err := vm.Contract(code).Call(state, params)if err == nil {// Only sync back when there was no exceptionerr = state.CallFrame.Sync()}// Always return output - we may have a reverted exception for which the return is meaningfulreturn output, err
}

ABI

ABI即Application Binary Interface,是应用程序二进制接口,描述了应用程序和EVM之间,一个应用和它的库之间,或者应用的组成部分之间的低接口。ABI涵盖了各种细节,如:
●数据类型的大小、布局和对齐;
●调用约定(控制着函数的参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后;
●系统调用的编码和一个应用如何向EVM进行系统调用;
●以及在一个完整的EVM的ABI中,目标文件的二进制格式、程序库等等。

这么说可能有点难懂,先从智能合约的角度说起。

我们编写智能合约的流程是:
●编写合约代码(一般使用solidity语言)
●编译合约,将solidity编写的代码编译成EVM可识别的bytecode,这一步生成abi
●部署合约,将合约部署到区块链上,生成合约地址,将合约内容(即上一步生成的bytecode)作为input date输入。部署合约是一个交易过程,所以也会生成一个交易Hash
●执行合约,获取合约地址,然后传入参数调用合约中的方法,获得执行结果

从上面的步骤可以看出,abi对于EVM来说,其实是不需要的。但是对于调用者来说,就需要知道合约有哪些方法,方法的参数是什么,返回值是什么,而这些信息就记录在智能合约的abi中。
所以简单来说,ABI其实就相当于开发者的接口文档,方便开发者调用执行合约。

以一个简单的solidity为例,通过Web3,Remix等工具编译生成ABI。

pragma solidity ^0.4.24;contract Demo {uint private x;function set(uint _x) public {x = _x;}}

执行 truffle compile 编译合约,就会生成对应的文件Demo.json

{"contractName": "Demo","abi": [{"constant": false,"inputs": [{"name": "_x","type": "uint256"}],"name": "set","outputs": [],"payable": false,"stateMutability": "nonpayable","type": "function"}],"bytecode": "0x6080604052348015600f57600080fd5b5060a48061001e6000396000f300608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b1146044575b600080fd5b348015604f57600080fd5b50606c60048036038101908080359060200190929190505050606e565b005b80600081905550505600a165627a7a723058201dfe7c019fec67ccd87250c9ac8642c163cc5f43588715b33e8a8953df3715f60029","deployedBytecode": "0x608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b1146044575b600080fd5b348015604f57600080fd5b50606c60048036038101908080359060200190929190505050606e565b005b80600081905550505600a165627a7a723058201dfe7c019fec67ccd87250c9ac8642c163cc5f43588715b33e8a8953df3715f60029","sourceMap": "27:97:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;27:97:1;;;;;;;","deployedSourceMap": "27:97:1:-;;;;;;;;;;;;;;;;;;;;;;;;69:52;;8:9:-1;5:2;;;30:1;27;20:12;5:2;69:52:1;;;;;;;;;;;;;;;;;;;;;;;;;;;112:2;108:1;:6;;;;69:52;:::o","source": "pragma solidity ^0.4.24;\n\n\ncontract Demo {\n\n    uint private x;\n\n    function set(uint _x) public {\n        x = _x;\n    }\n\n}\n","sourcePath": "/Users/root/Workspace/DApp/demo/contracts/Demo.sol","ast": {...},"legacyAST": {...},"compiler": {"name": "solc","version": "0.4.24+commit.e67f0147.Emscripten.clang"},"networks": {},"schemaVersion": "2.0.1","updatedAt": "2018-09-14T11:57:49.750Z"
}

其中,各字段的意义分别为:
name:函数名称
type:方法类型,包括function, constructor, fallback(缺省方法)可以缺省,默认为function
constant:布尔值,如果为true指明方法不会修改合约字段的状态变量
payable:布尔值,标明方法是否可以接收ether
stateMutability:状态类型,包括pure (不读取区块链状态),view (和constant类型,只能查看,不会修改合约字段),nonpayable(和payable含义一样),payable(和payable含义一样)。其实保留payable和constant是为了向后兼容
inputs:数组,描述参数的名称和类型
name:参数名称
type:参数类型
outputs:和inputs一样,如果没有返回值,缺省是一个空数组

在使用ABI调用合约函数时,传入的ABI会被编码成calldata(一串hash值)。calldata由function signature和argument encoding两部分组成。通过读取call data的内容, EVM可以得知需要执行的函数,以及函数的传入值,并作出相应的操作。

EVM读取并执行call data的规则:
●函数选择器: Call data的前4个bytes对应了合约中的某个函数。因此EVM通过这4个bytes, 可以跳转到相应的函数。

ByteCode中的体现:


上面两张图是合约bytecode最开始的部分,EVM依次执行每条命令,当执行到CALLDATASIZE(L6)时,EVM读取input的size(读取的是function的hash, 长度为4bytes)。L7会和4进行比较,作为L9的JUMPI的跳转条件

input的size比4小,则跳转到fallback function(fallback function是唯一一个没有名字的函数)。跳转的地址是由L8 push到栈中的,跳转的地址是6d,转换成10进制为109,也就是L42。

input的size长度为4,则会继续执行每个指令。L11的CALLDATALOAD会从读取input的具体值,与L18,23,28,33,38的hash值(该合约中的函数签名)进行比较,以L18为例,L19会比较input的函数签名与L18的哈希值是否相等。如果相等,则跳转到L20表明的地址(PC:8d),否则继续执行,直到遇到函数签名相等的情况为止

如果没有一个函数签名相等(此时执行到L41),因为没有执行到终止命令,如stop。EVM会继续往下执行L42,L42是fallback function的起始位置。因此fallback function的执行情况是:
A contractcan have exactly one unnamed function. This function cannot have arguments and cannot return anything. It is executed on a call to the contract if none of theother functions match the given function identifier. Furthermore, this functionis executed whenever the contract receives plain Ether (without data).

●参数读取:call data是32bytes的整数倍(头4 bytes的函数签名除外),EVM通过CALLDATALOAD指令,每次能从call data中读取32byte的值,放入stack中。上面的图通过2个CALLDATALOAD分别读出了newState和value的值,放入了stack中。通过JUMP指令跳转到函数体(tag19),并继续执行。

●返回值:

当函数结束完时,会跳转到tag18。Tag 18最末尾的RETURN指令。RETURN指令会从stack中读取两个值,通过这两个值从memory中读取相应的值,以返回给调用方。

ABI是如何编码的

●函数编码:在EVM中,每个函数都由4个byte长度的16进制值来唯一标识,这4个bytes叫做函数签名。函数签名是对函数名,函数参数做Keccak(SHA-3) 运算后,获得的hash值的前4个bytes.

如下面increaseAge这个函数,直接通过web3提供的sha3,取前4bytes即可获得函数签名F9EA5E79. EVM会通过这个函数签名找到对应的函数,通过JUMPI跳转到对应的函数。

functionincreaseAge(string name, uint num)returns (uint){return ++age;
}

●函数参数编码:

每个参数都是以一个32byte长度hash值的形式传入的,长度不够用0补,如uint8的长度是8bytes,前面不足的24bytes都用0来补。用下面的合约来举例:

pragma solidity ^0.4.16;contract Foo {function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; }function bar(bytes3[2] memory) public pure {}function f(uint, uint32[], bytes10, bytes) public pure {}
}

案例一:
函数:baz(bytes3[2] memory)
调用:baz(69, true)

0xcdcd77c0,在node中使用new Web3().sha3('baz(uint32,bool)')生成

const Web3 = require('web3')const web3 = new Web3()
console.log(web3.sha3('f(uint256,uint32[],bytes10,bytes)'))

0x0000000000000000000000000000000000000000000000000000000000000045,十进制69,转成16进制为45,因为是正数,高位补0至32bytes

0x0000000000000000000000000000000000000000000000000000000000000001,bool类型,true=1,false=0,高位补0
所以最终字符串为:

0xcdcd77c0
0000000000000000000000000000000000000000000000000000000000000045
0000000000000000000000000000000000000000000000000000000000000001

一共68bytes。

返回:该函数返回的是true,output将会是

0x0000000000000000000000000000000000000000000000000000000000000000
案例二:
函数:bar(bytes3[2] memory)
调用:bar(["abc", "def"])

0xfce353f6,在node中使用new Web3().sha3('bar(bytes3[2])')生成
固定长度不需要计算偏移量
0x6162630000000000000000000000000000000000000000000000000000000000,字符串abc转成16进制后为616263,低位补0
0x6465660000000000000000000000000000000000000000000000000000000000,同上
所以最终字符串为:

0xfce353f6
6162630000000000000000000000000000000000000000000000000000000000
6465660000000000000000000000000000000000000000000000000000000000

案例三:
函数:f(uint,uint32[],bytes10,bytes)
调用:

f(0x123, [0x456, 0x789], "1234567890", "Hello, world!")

0x8be65246,在node中使用f(uint256,uint32[],bytes10,bytes)生成
0x00000000000000000000000000000000000000000000000000000000000001230x123对应的16进制,正数补全
0x0000000000000000000000000000000000000000000000000000000000000080,动态类型,计算偏移量。这个的偏移量是指实际存储值的位置,由于这个函数有4个变量,那么实际存储值的位置就是第五个32bytes位置,也就是说偏移量等于4×32bytes=128,转成16进制后就是对应的值
0x3132333435363738393000000000000000000000000000000000000000000000,字符串1234567890转成16进制后为31323334353637383930,bytes类型,低位补全
0x00000000000000000000000000000000000000000000000000000000000000e0,动态类型,计算偏移量,这个偏移量就等于参数长度4×32bytes+前面的动态参数参数占有的长度(因为前面只有一个动态参数,所以这个长度就是1×32bytes+2×32bytes,1×32bytes是第一个动态参数长度所占的bytes数,2×32bytes是因为该函数中的第一个动态参数有2个值),那么具体的值就是 4×32bytes+(1×32bytes+2×32bytes)=7×32bytes=224,转成16进制就是e0,高位补全就是对应的值
0x0000000000000000000000000000000000000000000000000000000000000002,第一个动态参数的长度,长度为2
0x0000000000000000000000000000000000000000000000000000000000000456,第一个动态参数中的第一个元素
0x0000000000000000000000000000000000000000000000000000000000000789,第一个动态参数中的第二个元素
0x000000000000000000000000000000000000000000000000000000000000000d,第二个动态参数的长度,长度为13
0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000,第二个动态参数的值编码
所以最终字符串为:

0x8be65246
0000000000000000000000000000000000000000000000000000000000000123
0000000000000000000000000000000000000000000000000000000000000080
3132333435363738393000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000e0
0000000000000000000000000000000000000000000000000000000000000002
0000000000000000000000000000000000000000000000000000000000000456
0000000000000000000000000000000000000000000000000000000000000789
000000000000000000000000000000000000000000000000000000000000000d
48656c6c6f2c20776f726c642100000000000000000000000000000000000000

用ABI与smart contract进行交互

当DAPP端调用smart contract的某个函数时,web3的作用就是把ABI通过网络发送给Node。Node接收到ABI之后,编译成hash值并且执行。Node把执行完的结果上传到区块链。如果有返回值,Node再通过网络的方式返回给DAPP。

Hyperledger Burrow EVM相关推荐

  1. Hyperledger发布Burrow新版本,改进集成和开发体验

    在最近的一篇博文中,Hyperledger开源项目宣布了下一个版本的Burrow,v.0.21.0.这个版本改进了集成.密钥签名.Helm Charts for Kubernetes及开发体验. \\ ...

  2. 超级账本(Hyperledger)

    摘要 超级账本(Hyperledger)是linux基金会下的众多项目中的一个.是由IBM.因特尔,还有金融公司,GP摩根以及其他联合机构于2015年提出来的区块链项目,超级账本还包括5个框架项目:S ...

  3. 什么是Hyperledger?Linux如何围绕英特尔的区块链项目构建开放平台?

      访问区块链会议并关注区块链新闻时,不可避免地,您会遇到Linux基金会的Hyperledger.理解像比特币.以太坊这样的加密货币还算相对容易的,Hyperledger却不然.但如果你多研究研究, ...

  4. Hyperledger Fabric介绍

    转载地址 https://blog.csdn.net/xiaonu123/article/details/81006936 简介 Hyperledger介绍 超级账本(Hyperledger)项目是首 ...

  5. Kubernetes helm burrow 集成

    环境 [root@k8s-master-a ~]# cat /etc/redhat-release CentOS Linux release 7.8.2003 (Core)[root@k8s-node ...

  6. 从程序员到CTO都应该了解的一些技术趋势

    作者 | ThoughtWorks 编辑 | 小智 ThoughtWorks 每年都会出品两期技术雷达,这是一份关于技术趋势的报告,由 ThoughtWorks 技术战略委员会(TAB)经由多番正式讨 ...

  7. 区块链为什么热衷开源?超级账本最有说服力!

    作者:刘学习  | 小编:小葱 区块链的一个基本技术特征就是共享账本,需要多方参与.多方合作.在这个合作链条中,如何快速的建立起信任?一家企业为什么要把自己的业务系统,建立在一个完全不了解的新项目上呢 ...

  8. Linux基金会超级记账本开发框架和工具

    Linux基金会的Hyperledger超级记账本是一个开源合作的跨行业的区块链技术,包括金融,银行,物联网,工厂,科技等行业的领军者如IBM, Intel, Huawei, Baidu, Tence ...

  9. HyperLeger Fabric学习(一)

    HyperLeger Fabric学习(一) 一.HyperLeger简介 1.HyperLeger简介 2.Hyperledger社区组织结构 3.Hyperledger顶级项目 二.Hyperle ...

最新文章

  1. PHP常用函数及其注释
  2. 处理过拟合问题-Regularization
  3. 关于公司内部域名称是否要和外部真实域名称对应的问题
  4. 当yum 遇到No more mirrors to try
  5. html加载完显示图片,js图片未加载完显示loading效果
  6. wxWidgets:wxFileDirPickerEvent类用法
  7. python程序运行时间计算公式_Python执行时间的计算方法小结
  8. 根据父类id查询所有的父级_031、组函数和子查询
  9. linux下修改当前目录下图像文件并删除
  10. 让Windows Server 2008 + IIS 7+ ASP.NET 支持10万并发请求--转载
  11. 用汇编的眼光看C++(之算术符重载陷阱)
  12. JAVA对List进行手动分页
  13. 代码不是重点, 领悟OO思想(一)
  14. 辽宁工业大学计算机复试经验,辽宁工业大学车辆工程考研经验
  15. NB-IoT、LoRa、eMTC、Zigbee、Sigfox、WiFi、蓝牙,谁能称霸物联网时代
  16. 北大计算机系研究生宿舍地址,北京大学研究生宿舍
  17. 自治区计算机考试试题,2014新疆维吾尔自治区计算机等级考试试题 二级C试题试题及答案...
  18. 百度地图离线API开发(真正的离线开发)
  19. 华为备胎除了鸿蒙还有什么,硬件有备胎软件也有!华为鸿蒙操作系统曝光:或可取代安卓Win...
  20. 当代大学生开展团队学习的意义

热门文章

  1. Could not find com.android.tools.build:gradle:3.3.1
  2. MySQL-5.5.40-win32.msi安装教程
  3. mint linux使用教程,Linux:Linux Mint系统的安装
  4. 【论文总结】对中国安卓应用市场大规模比较研究
  5. 网页设计需要会java吗_网页设计的三大注意事项
  6. 网络上所谓的《ARM嵌入式系统入门最好的文章》
  7. 计算机视觉与模式识别 code
  8. 北京邮电大学2021年C语言航空售票系统
  9. 365. 水壶问题-暴力模拟倒水过程-递归法
  10. C语言里字符串的解析