最新内容会更新在主站深入浅出区块链社区

原文链接:智能合约语言 Solidity 教程系列8 - Solidity API

这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里。

写在前面

Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊、智能合约有所了解,

如果你还不了解,建议你先看以太坊是什么

欢迎订阅区块链技术专栏阅读更全面的分析文章。

Solidity API 主要表现为Solidity 内置的特殊的变量及函数,他们存在于全局命名空间里,主要分为以下几类:

  1. 有关区块和交易的属性
  2. 有关错误处理
  3. 有关数学及加密功能
  4. 地址相关
  5. 合约相关

下面详细讲解下

区块和交易的属性(Block And Transaction Properties)

用来提供一些区块链当前的信息。

  • block.blockhash(uint blockNumber) returns (bytes32):返回给定区块号的哈希值,只支持最近256个区块,且不包含当前区块。
  • block.coinbase (address): 当前块矿工的地址。
  • block.difficulty (uint):当前块的难度。
  • block.gaslimit (uint):当前块的gaslimit。
  • block.number (uint):当前区块的块号。
  • block.timestamp (uint): 当前块的Unix时间戳(从1970/1/1 00:00:00 UTC开始所经过的秒数)
  • msg.data (bytes): 完整的调用数据(calldata)。
  • msg.gas (uint): 当前还剩的gas。
  • msg.sender (address): 当前调用发起人的地址。
  • msg.sig (bytes4):调用数据(calldata)的前四个字节(例如为:函数标识符)。
  • msg.value (uint): 这个消息所附带的以太币,单位为wei。
  • now (uint): 当前块的时间戳(block.timestamp的别名)
  • tx.gasprice (uint) : 交易的gas价格。
  • tx.origin (address): 交易的发送者(全调用链)

注意:

msg的所有成员值,如msg.sender,msg.value的值可以因为每一次外部函数调用,或库函数调用发生变化(因为msg就是和调用相关的全局变量)。

不应该依据 block.timestamp, now 和 block.blockhash来产生一个随机数(除非你确实需要这样做),这几个值在一定程度上被矿工影响(比如在赌博合约里,不诚实的矿工可能会重试去选择一个对自己有利的hash)。

对于同一个链上连续的区块来说,当前区块的时间戳(timestamp)总是会大于上一个区块的时间戳。

为了可扩展性的原因,你只能查最近256个块,所有其它的将返回0.

错误处理

  • assert(bool condition)

    用于判断内部错误,条件不满足时抛出异常
  • require(bool condition):

    用于判断输入或外部组件错误,条件不满足时抛出异常
  • revert():

    终止执行并还原改变的状态

数学及加密功能

  • addmod(uint x, uint y, uint k) returns (uint):

    计算(x + y) % k,加法支持任意的精度且不会在2**256处溢出,从0.5.0版本开始断言k != 0。
  • mulmod(uint x, uint y, uint k) returns (uint):

    计算 (x * y) % k, 乘法支持任意的精度且不会在2**256处溢出, 从0.5.0版本开始断言k != 0。
  • keccak256(...) returns (bytes32):

    使用以太坊的(Keccak-256)计算HASH值。紧密打包参数。
  • sha256(...) returns (bytes32):

    使用SHA-256计算hash值,紧密打包参数。
  • sha3(...) returns (bytes32):

    keccak256的别名
  • ripemd160(...) returns (bytes20):

    使用RIPEMD-160计算HASH值。紧密打包参数。
  • ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):

    通过椭圆曲线签名来恢复与公钥关联的地址,或者在错误时返回零。可用于签名数据的校验,如果返回结果是签名者的公匙地址,那么说明数据是正确的。

ecrecover函数需要四个参数,需要被签名数据的哈希结果值,r,s,v分别来自签名结果串。

r = signature[0:64]

s = signature[64:128]

v = signature[128:130]

其中v取出来的值或者是00或01。要使用时,我们先要将其转为整型,再加上27,所以我们将得到27或28。在调用函数时v将填入27或28。

用javascript表达如下:

    var msg = '0x8CbaC5e4d803bE2A3A5cd3DbE7174504c6DD0c1C'

    var hash = web3.sha3(msg)
var sig = web3.eth.sign(address, h).slice(2)
var r = `0x${sig.slice(0, 64)}`
var s = `0x${sig.slice(64, 128)}`
var v = web3.toDecimal(sig.slice(128, 130)) + 27

订阅区块链技术专栏可以参考到完整的使用例子。

紧密打包参数(tightly packed)意思是说参数不会补位,是直接连接在一起的,下面几个是相等的。

keccak256("ab", "c")
keccak256("abc") keccak256(0x616263) // hex
keccak256(6382179)
keccak256(97, 98, 99) //ascii

如果需要填充,可以使用显式类型转换:keccak256("\x00\x12") 与keccak256(uint16(0x12))相同。

注意,常量将使用存储它们所需的最少字节数来打包,例如keccak256(0) == keccak256(uint8(0))和keccak256(0x12345678) == keccak256(uint32(0x12345678))

在私链(private blockchain)上运行sha256,ripemd160或ecrecover可能会出现Out-Of-Gas报错。因为私链实现了一种预编译合约,合约要在收到第一个消息后才会真正存在(虽然他们的合约代码是硬编码的)。而向一个不存在的合约发送消息,所以才会导致Out-Of-Gas的问题。一种解决办法(workaround)是每个在你真正使用它们之前先发送1 wei到这些合约上来完成初始化。在官方和测试链上没有这个问题。

地址相关

  • .balance (uint256):

Address的余额,以wei为单位。

  • .transfer(uint256 amount):

发送给定数量的ether到某个地址,以wei为单位。失败时抛出异常。

  • .send(uint256 amount) returns (bool):

发送给定数量的ether到某个地址,以wei为单位, 失败时返回false。

  • .call(...) returns (bool):

发起底层的call调用。失败时返回false。

  • .callcode(...) returns (bool):

发起底层的callcode调用,失败时返回false。

不鼓励使用,未来可能会移除。

  • .delegatecall(...) returns (bool):

发起底层的delegatecall调用,失败时返回false

更多信息参考地址篇

警告:send() 执行有一些风险:如果调用栈的深度超过1024或gas耗光,交易都会失败。因此,为了保证安全,必须检查send的返回值,如果交易失败,会回退以太币。如果用transfer会更好。

合约相关

  • this(当前合约的类型):

    表示当前合约,可以显式的转换为Address
  • selfdestruct(address recipient):

    销毁当前合约,并把它所有资金发送到给定的地址。
  • suicide(address recipient):

    selfdestruct的别名

另外,当前合约里的所有函数均可支持调用,包括当前函数本身。

参考视频

我们也推出了目前市面上最全的视频教程:深入详解以太坊智能合约语言Solidity

目前我们也在招募体验师,可以点击链接了解。

参考文档

深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。

如果想与我有更密切的交流可以选择加入我的知识星球(星球成员可加入微信技术交流群)

最新文章

  1. Effective java笔记(一),创建与销毁对象
  2. JQuery 实现两列等高并自适应高度
  3. Android 中的常用方法
  4. code complete part1
  5. 解决 Oracle exp导出表数据时空表不能导出的问题
  6. 多台linux服务器时间同步
  7. IOS Label 自动换行 IOS6和IOS7
  8. crm操作安全角色
  9. 【MSP是什么】MSP认证之项目群管理
  10. 利用POI获取Excel中图片和图片位置
  11. Mysql按时间段分组查询
  12. TypeScript之interface初探
  13. python中shelve模块的使用
  14. python摸爬滚打之day16----类的成员
  15. ROS知识(24)——ros::spin()和spinOnce的含义及其区别
  16. 第9天 py就业班基础02.01-02
  17. hdu 1507 记录路径的二分匹配 **
  18. 有用的 JS 和 CSS 库
  19. OpenGL常用的函数
  20. Hive与Hbase的区别

热门文章

  1. Java数组及其内存分配
  2. javascript学习笔记(四):事件处理函数和动态创建html标记。
  3. jQuery Jcrop API参数说明(中文版)(转)(图片剪切)
  4. [CentOS 6.5 X64]讓firefox java plugin 啟動
  5. 【JavaScript】页面加载性能优化
  6. awesome awesomeness
  7. 「前端开发者」如何把握住「微信小程序」这波红利?
  8. Google AdSense的CPC点击单价超百度联盟(2014)
  9. 经纪xx系统节点VIP案例介绍和深入分析异常
  10. CentOS上安装NodeJs
  11. flask 电子邮件进阶实践-用模板发送163邮件
  12. poj 1164 深度优先搜索模板题
  13. NF5280M4 安装 Win2016 的方法
  14. jenkins X实践系列(2) —— 基于jx的DevOps实践
  15. dropwizard使用cors支持跨域浏览器取不到自定义header问题
  16. python读取yaml配置文件
  17. C语言 · 求最大公约数
  18. APM最佳实践: 诊断平安城市视频网性能问题
  19. logging.basicConfig参数简介
  20. # 20155224 2016-2017-2 《Java程序设计》第10周学习总结