智能合约从入门到精通:调用数据的布局和ABI

本文详细介绍了以太坊智能合约中的调用数据布局和ABI,包括函数选择器、参数编码、动态内容类型的处理以及ABI在函数调用和事件中的应用。内容涵盖ABI的基本设计思想、函数签名、参数编码规则和动态内容类型的编码方式,旨在帮助读者深入理解智能合约的交互机制。
摘要由CSDN通过智能技术生成

简介:本文将介绍Solidity语言的调用数据的布局和ABI详解。其中调用数据的布局将主要介绍以太坊合约间调用时的消息格式ABI

好久时间没有更新文章,前文中我们介绍了Solidity的特性与内部机制,本文我们将Solidity的调用数据的布局和ABI详解。

调用数据的布局(Layout of CallData)

Solidity合约被部署后,从某个帐户调用这个合约,需要输入的数据是需要符合the ABI specificationABI是以太坊的一种合约间调用时的一个消息格式。类似Webservice里的SOAP协议一样;也就是定义操作函数签名,参数编码,返回结果编码等。

ABI详解

函数

基本设计思想

使用ABI协议时必须要求在编译时知道类型,也就是说不支持动态语言那样的声明的变量还会变类型的情况。由于协议假设合约在编译期间知道另一个合约的接口定义,所以协议内没有明确定义存的内容类型(协议非类型内省)。

所以这个协议并不支持合约接口是动态的,或者是仅在运行时才知道类型的情况。如果这些情况很重要,可以使用以太坊生态系统建立自己的基础设施来解决这个问题。

函数选择器

一个函数调用的前四个字节数据指定了要调用的函数签名。计算方式是使用函数签名的keccak256的哈希,取4个字节。

bytes4(keccak256("foo(uint32,bool)"))

函数签名使用基本类型的典型格式(canonical expression)定义,如果有多个参数使用,隔开,要去掉表达式中的所有空格。

参数编码

由于前面的函数签名使用了四个字节,参数的数据将从第五个字节开始。参数的编码方式与返回值,事件的编码方式一致,后面一起介绍。

支持的类型

支持的类型可参考原文2。支持的类型里面有一些比较特殊的是动态内容的类型,比如string需要存储的空间是不固定的。

编码方式 

针对数组参数中的嵌套数组的优化:

访问一个参数属性需要的读取次数,在一个数组结构中最多是数组的深度,比如a_i[k][l][r],最多4次。在之前的ABI协议版本中,在最差情况下读取次数会随着总的动态类型的参数量线性增长。

变量的值或数组的元素间不应该是隔开存储的,可支持重定位,比如使用相对地址来定位。

区分了动态内容类型和固定大小的类型。固定大小的类型按原位置存储到当前块。动态类型的数据则独立存储在其它数据块。 

动态内容类型的定义

 bytes

 string

 T[] 某个类型的不定长数组

 T[k] 某个类型的定长数组

所有其它类型则称为固定大小的类型。

长度函数的定义

len(a)是二进制字符串a的中的字节数。len(a)的结果类型是uint256

我们定义enc,编码函数,是一个ABI类型值到二进制串的映射函数,也就是ABI类型到二进制字符串的映射函数。由此len(enc(X))的结果也将因为X是不是动态内容类型而有所不同(也就是说动态内容类型的编码方式稍有不同)。

进一步定义 

对于任何ABI的值,根据X的类型不同,我们递归定义enc(X),如下:

对于X是任意类型的T和长度值kT[k]

enc(X) = head(X[0]) ... head(x[k-1] tail(X[0]) ... tail(X[k-1])

对于X[i],如果其为固定大小的类型,head函数定义为,head(X[i]) = enc(X[i])tail函数定义为tail(X[i]) = ""

对于动态内容类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值