怎么使用以太坊的预编译合约

发布时间:2021-12-29 14:30:05 作者:iii
来源:亿速云 阅读:148

这篇文章主要讲解了“怎么使用以太坊的预编译合约”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用以太坊的预编译合约”吧!

以太坊包含了一些用于密码学计算的预编译合约,可以用来实现高级隐私保护功能。在这个教程中我们将了解以太坊提供的预编译合约清单,并通过bn256ScalarMulbigModExp这两个实例学习以太坊预编译合约的使用方法。

1、以太坊虚拟机基本概念

在继续下面的教程之前,我们需要对以太坊和Solidity有一些基本的了解。我们关心的重点在于,以太坊有一个分布式的虚拟机即EVM,EVM提供了一组指令可以用于在区块链上执行交易并更新状态。关于EVM的一些基本概念如下:

2、以太坊预编译合约清单

以太坊Geth客户端的预编译合约清单看起来像这样:

var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{     
  common.BytesToAddress([]byte{1}): &ecrecover{}, 
  common.BytesToAddress([]byte{2}): &sha256hash{}, 
  common.BytesToAddress([]byte{3}): &ripemd160hash{}, 
  common.BytesToAddress([]byte{4}): &dataCopy{}, 
  common.BytesToAddress([]byte{5}): &bigModExp{}, 
  common.BytesToAddress([]byte{6}): &bn256Add{}, 
  common.BytesToAddress([]byte{7}): &bn256ScalarMul{}, 
  common.BytesToAddress([]byte{8}): &bn256Pairing{},
}

上述代码中的映射结构记录了预编译合约的地址,是最后4个是新增的预编译 合约:

bigModExp:地址0x05,执行操作:b^e mod m。bigModExp预编译合约的输入为: 底数长度、指数长度、模长度、底数即b的值、指数即e的值、模即m的值

bn256Add:地址0x06,执行操作:(x1, y1) + (x2, y2),其中x1, y1, x2, y2 都是256位的域成员,因此 (x1, y1)和 (x2, y2)都是bn256曲线上的有效点,满足公式y^2 = x^3 + 3 mod fieldOrder。 bn256预编译合约的输入就是x1, y1, x2, y2。

bn256ScalarMul:地址0x07,执行操作:k * (x, y),其中k属于群,(x,y)是曲线上的有效点。 bn256scalarMul的输入是x, y, k。

bn256Pairing:地址0x08,执行操作:配对检查e(g1, g2) = e(-h2, h3,其中g1和h2属于群G1, g2和h3属于群G2。bn256Pairing可以接收任意多对椭圆曲线上的点。群G1上的点形式为(x,y),群 G2上的点形式为(ai + b, ci + d),其中a, b, c, d (依次为虚部、实部、虚部、实部) 需要在预编译 调用时传入。bn256Pairing代码首先检查已经送出6的倍数个成员,然后执行配对检查。

x, y, a, b, c, d的值都是域成员,因此都会按域大小取模。在bn256ScalarMul中使用的k的值,则是按椭圆曲线群的阶取模。

下面我们将要学习两个主要的示例:bn256ScalarMul和bigModExp。bn256ScalarMul操作和bn256Add非常类似,而bn256Pairing操作则更像bigModExp,因为这两者都接受可变长度的输入,因此调用时需要指定输入大小。下面是调用bn256ScalarMul的代码:

function ecmul(uint ax, uint ay, uint k) public view returns(uint[2] memory p) { uint[3] memory input;
 input[0] = ax;
 input[1] = ay;
 input[2] = k;

 assembly {
   if iszero(staticcall(gas, 0x07, input, 0x60, p, 0x40)) {
       revert(0,0)
   }
 }
 return p;
}

目前内联汇编已经支持if语句,调用时设置gas数量也比以前简单 —— 在调用时使用gas,就表示利用所有可用gas,这避免了我们自己猜测需要的gas数量。

revert操作码将回滚所有的状态变化,起作用是在gas不足时或对预编译合约的调用发生故障后,可以回滚部分完成的状态更新。

3、调用bn256ScalarMul预编译合约

每个地址关联的持久化内存被称为存储(Storage),这时一个key-value库,实现从256位到256位数据的映射。在合约内这个键值库没有办法枚举,合约也不能访问其他地址关联的存储。

如果采用如下形式初始化变量:uint256 blah,那么就会将变量blah保存到持久化存储。uint是uint256的别名,如果需要更细粒度的管理,可以使用uint8,uint16等等。

EVM有一个虚拟栈可以保存256位的值。选择256位的目的是与密码学操作保持兼容。所有的EVM操作都是利用这个虚拟栈完成的,它最多可以容纳1024个成员。你可以拷贝栈顶16个成员之一,或者两两交换。所有其他的操作码都利用栈顶特定位置的成员作为输入并将结果压入栈。

对于每一个消息调用,易失内存都被复位,内存以32字节为单位分配,使用gas支付内存利用的成本。我们需要调用预编译合约的值保持在这个内存的顶部。

我们可以将之前保存在持久化存储中的变量赋值给内存,方式如下:

uint256[2] memory inputToPrecompile;
input[0] = somePreviouslyStoredValue;
input[1] = someOtherPreviouslyStoredValue;

这实际上就是我们在ecmul中的开始4行的操作。我们将值ax,ay,k压入虚拟栈的顶部。然后通过调用bn256ScalarMul预编译合约的地址就完成调用了。看下一部分的代码:

assembly {
   if iszero(staticcall(gas, 0x07, input, 0x60, p, 0x40)) {
       revert(0,0)
   }
 }

staticcall操作码的调用形式如下:

staticcall(gasLimit, to, inputOffset, inputSize, outputOffset, outputSize)

可以看到在上面的调用bn256ScalarMul的代码中,我们:

这样就完成了对以太坊预编译合约bn256ScalarMul的调用,ecmul函数的返回值现在就是bn256ScalarMul预编译合约的返回值!

4、调用bigModExp预编译合约

下面的代码调用bigModExp预编译合约:

function expmod(uint base, uint e, uint m) public view returns (uint o) {
  
  assembly {
   // define pointer
   let p := mload(0x40)
   // store data assembly-favouring ways
   mstore(p, 0x20)             // Length of Base
   mstore(add(p, 0x20), 0x20)  // Length of Exponent
   mstore(add(p, 0x40), 0x20)  // Length of Modulus
   mstore(add(p, 0x60), base)  // Base
   mstore(add(p, 0x80), e)     // Exponent
   mstore(add(p, 0xa0), m)     // Modulus
   if iszero(staticcall(sub(gas, 2000), 0x05, p, 0xc0, p, 0x20)) {
     revert(0, 0)
   }
   // data
   o := mload(p)
  }}

需要注意的是,0x40始终是空闲内存,因此可以使用p:=mload(0x40)来初始化内存指针。

感谢各位的阅读,以上就是“怎么使用以太坊的预编译合约”的内容了,经过本文的学习后,相信大家对怎么使用以太坊的预编译合约这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. 以太坊众筹智能合约怎么实现
  2. 以太坊智能合约ABI怎么获取

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

以太坊

上一篇:git有什么作用

下一篇:如何在Web应用中添加同态加密支持

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》