跨链是如何实现的

由于区块链可扩展性未解决

链之间的交互,数据、资产和功能的互通

一、跨链通信

主要有两类跨链通信:

  1. 最小化信任跨链通信:集群内部,rollups
  2. 可信任跨链通信:集群之间

常见可信任跨链通信协议

1. IBC

cosmos中的核心部分,为一种标准(链间标准ICS),由TAO层和Application层组成。

点对点连接

链之间不是直接通信,用专用通道发送信息,通道中包含一个轻客户端

2. ZK

用zkp代替原数据

步骤:

  1. 决定要传递的数据
  2. 获取证明数据存在EVM中的存储证明
  3. 由存储证明生成ZK证明,以默克尔树的形式
  4. 传递zkp
  5. 展开zkp
  6. 读取跨链信息
3. LayerZero

传输层协议,架构由端点、中继点和预言机组成

步骤:

  1. 向communicator发送交易信息
  2. communicator将交易信息以某种形式发送给validator
  3. 未完,有点复杂
4. axelar

验证者网络+网关智能合约+开发者工具

非点对点,链只需要接入一次即可跨多条链

5. wormhole

POA共识机制,核心合约+守护者网络。

守护者网络有19名守护者,负责交易验证

二、跨链技术

1. 公证人机制

引入第三方来验证信息

有点像交易所

2. 哈希锁定

借助哈希的单向性实现跨链交易

3. 侧链

two-way peg,在主链锁定货币后在侧链中释放等价货币

SPV模式:simplified payment verification,通过将交易发给本链的一个特殊地址,由此会自动创建一个SPV证明给侧链上并发起一个交易在侧链上解锁对应的资产。

4. 中继机制

跨链信息通过中继链的验证者验证后发布到中继链上

5. 分布式私钥控制

lock-in,lock-out,分片密钥

三、跨链的未来展望

  • 跨链桥
  • OmniChain NFT
  • layerzero的新应用
  • chainlink作为预言机
  • 整合ICS标准

疑惑

  1. 跨链通信中的集群是什么意思?——同一生态,比如说polkadot中的平行链和中继链。
  2. 跨链通信协议和跨链技术的区别?——跨链通信协议是一种标准化的规则和协议,用于确保区块链之间的通信。跨链技术是一组具体的技术和方法,用于实际实现区块链之间的互操作性。跨链技术依赖跨链通信协议来建立通信,以实现跨链交互。这两者共同协助解决了区块链互操作性的挑战。
  3. 跨链桥是什么?——有点类似侧链

九、智能合约安全

9.3 重入

原理:调用外部fallback函数来进行转账,导致合约可重入

防范技术:

  1. 用transfer()进行转账,虽然会带来额外gas
  2. 使用“检查-生效-交互”模式
  3. 使用互斥锁

案例:DAO攻击

9.4 算术溢出

原理:Solidity中整数存在上下限

防范技术:

  1. 使用SafeMath库合约

案例:PoWHC

9.5 意外的以太币

原理:强制发送以太币导致合约无法执行,self-destruct或预先发送都可以实现

防范技术:

  1. 少用this.balance,使用状态变量保存余额

9.6 delegatecall

原理:delegatecall保持上下文,状态或存储变量(可以在独立的交易之间保持其数值的变量)会按照它们被引入合约的顺序放置在存储槽中,这时我们改变的变量可能不是我们期望改变的。

防范技术:

  1. 使用library关键字可以保证库合约是无状态和不会自我销毁的

案例:Parity多重签名钱包的第二次攻击

9.7 默认的可见性

原理:Solidity函数可见性默认为public,可能出现纰漏

防范技术:为每个函数都指定可见性

案例:Parity多重签名钱包的首次攻击

9.8 无序错觉

原理:为了在以太坊中引入无序性(即随机性),使用哈希值、区块号等可被操控的区块变量作为随机值

防范技术:无序性必须来自区块链外部

案例:PRNG合约

9.9 外部合约引用

原理:可以故意将地址指向错误的合约,假如引用的合约不包含要调用的函数,将执行回退函数。如果用户可以修改合约引用的合约库,那么基本上他们就可以使其他用户在不知情的情况下运行任意代码。

防范技术:

  1. new一个要引用的合约
  2. 对外部合约进行硬编码

一般建议将合约地址设置为public以方便用户检查引用的合约

案例:可重入的蜜罐

9.10 短地址攻击

原理:当实际发送的数据长度小于标准编码长度时,EVM将在数据末尾补0,这种操作可能影响末尾参数

防范技术:对参数进行校验

9.11 未检查的调用返回值

原理:send和call外部调用失败仅返回false,不revert

防范技术:

  1. 检查返回值
  2. 使用withdraw模式

9.12 预先交易

原理:gas高的优先被打包

防范技术:

  1. 设置gas上限
  2. 使用commit-reveal模式
  3. submarine sends

案例:erc20的approve函数

9.13 拒绝服务

原理:各种原因使合约不可用,比如说事先向合约转账使合约无法通过某些限制条件

防范技术:各个情况方法不同

9.14 区块时间戳操纵

原理:区块时间戳可被矿工指定。

防范技术:不应使用区块时间戳作为随机数。

案例:GovernMental

9.15 小心使用构造函数

原理:solidity0.4.22前,构造函数和合约同名;若合约名称和构造函数名称不同,构造函数将变成一个普通函数。

防范技术:使用constructor关键字。

案例:Rubixi

9.16 未初始化的存储指针

原理:状态变量和复杂类型的局部变量都存储在storage中;状态变量按照顺序保存在storage中(存储槽),未初始化的局部变量可能指向已有的状态变量。

防范技术:用storage和memory关键字明确指定变量的存储位置。

案例:OpenAddressLottery

9.17 浮点数和精度

原理:solidity的除法会舍去小于除数的所有精度。

防范技术:先执行加法和乘法,再执行减法和除法。

案例:Ethstick

9.18 Tx.Origin验证

原理:全局变量tx.origin表示最初发起交易的账户地址;若使用tx.origin作为判定条件,合约易受到钓鱼攻击。

防范技术:少用tx.origin作为判定条件。

可用require(tx.origin == msg.sender)来拒绝外部合约调用。

9.19 合约程序库

OpenZepplin包含丰富的库合约。

ZeppelinOS使开发者更简单地发布DApp。

疑惑

  1. 谁可以调用合约的self-destruct
  2. 外部合约引用的防范技术没看懂

数据集蒸馏-调研梳理

一、动机

大规模数据集包含了大量的冗余信息和噪声,这可能会导致模型过拟合或训练时间过长。所以我们希望通过保留关键样本和信息,从而创建一个更紧凑的数据集,以加快模型的训练速度并提高模型的泛化性能。

二、基本思想

数据集蒸馏的过程可以分为以下几个基本步骤:

  1. 初始化:先初始化一些合成数据和模型参数。
  2. 训练模型:然后我们使用这些合成数据来训练模型,得到模型结果。
  3. 优化合成数据:我们希望在当前模型参数下,模型在合成数据上的结果尽可能的接近原数据集的结果,所以每次训练我们将模型结果作为优化目标,更新合成数据。

不同数据集蒸馏算法的主要不同在于优化目标不同,优化目标除了预测值外,还有模型参数更新的梯度、数据分布、优化轨迹等等。

新提出了数据集蒸馏算法,基于因子分解。

三、局限性

数据集蒸馏还存在以下几个局限性:

  1. 可移植性:在不同的网络架构上的泛化能力较差。
  2. 计算量大:在训练时间和内存消耗方面存在一些限制。
  3. 性能下降:在处理具有更多类别和更少图像的数据集时表现不佳。

四、参考资料

Data Distillation: A Survey

【知识蒸馏论文解读】Dataset Distillation 创新性十足的数据集蒸馏 - 知乎 (zhihu.com)

浓缩的数据可以训练出一个好网络吗? - 知乎 (zhihu.com)

DATASET CONDENSATION WITH GRADIENT MATCHING-CSDN博客

Dataset Condensation with Distribution Matching论文笔记-CSDN博客

十一、预言机

为什么需要预言机?

为了保持共识,EVM的执行过程必须完全确定,并且仅基于以太坊状态和签名交易的共享上下文。这导致两个后果:一个是EVM和智能合约没有内在的随机性来源;另一个是外部数据只能作为交易的数据载荷引入。

假如提供随机性,网络将无法就结果状态应该是什么达成去中心化的共识。

引入外部信息,包括随机性、价格信息、天气预报等,当作随机源,作为发送到网络的交易的数据部分。

预言机的应用场景和示例

理想情况下,预言机提供了一种无信任(或至少近乎无信任)的方式来获取外在的(即“真实世界”或“链外”)信息。

可以将预言机视为弥合链外世界与智能合约之间差距的机制。

“证言”将成为未来区块链平台成功的重要组成部分,特别是在验证身份或声誉的相关问题方面,因此探索区块链平台如何为其提供服务非常重要。

预言机的设计模式

一旦数据在智能合约的存储中可用,其他智能合约就可以通过调用预言机智能合约的“检索”功能来访问它;它也可以通过“查看”预言机的存储直接由以太坊节点或支持网络的客户端访问。

设置预言机的三种主要方式可以分为请求与响应、发布与订阅和立即读取。

  1. 立即读取:那些希望查询此类数据的人倾向于在“即时”的基础上这样做;查找是在需要信息时完成的,可能永远不会再次查找。
  2. 发布与订阅:要对预期改变的数据(可能是定期和频繁地)提供有效的广播服务,预言机要么由链上的智能合约轮询,要么由链外守护进程监视和更新。
  3. 请求/响应:这是数据空间太大而无法存储在智能合约中的情况,并且用户每次只需要整个数据集的一小部分。

数据认证

两种常见的数据认证方法是真实性证明(authenticity proof)以及可信执行环境(Trusted Execution Environment,TEE)。

真实性证明是用密码学证据证明数据没有被篡改过。

Town Crier( http://www.town-crier.org/ )是一个基于可信执行环境的验证数据馈送预言机系统

计算性的预言机

预言机也可以用来执行任意计算,尤其是当给定gas上限和计算成本较贵时。

计算预言机也可以用来执行带有一组输入的相关计算并返回计算结果,而这种计算可能无法在链上进行。

去中心化预言机

去中心化预言机可以用于保证数据可得性,还可搭配链上数据汇总系统创建独立数据提供者网络。

谢林币协议:多个参与者记录数值,这些数值的中位数会被当成“正确”答案。记录者必须先质押保证金,这些保证金会根据它与中位数的接近程度重新分配,由此可以激励人们记录与其他人提供的值相近的值。这样共同的数值,也就是所谓的“谢林点”,预计会接近真实值,因为真实数值是响应者协作中所围绕的自然而明显的目标。

Solidity中的预言机客户端接口

使用Oraclize库。

疑惑

  1. 没太明白这章,具体预言机是怎么实现的?
  2. 需要多读几遍

十、代币

代币和可替代性

严格意义上说,如果一个代币的交易历史是公开的,那么它就不完全是一个可互相替代的代币。根据代币交易历史的追踪,可由此设定对应的黑名单或白名单,这会降低甚至消除这个代币的可替代性。

对手方风险

对手方风险是指交易的另一方没有履行他们的承诺或义务。

代币和内在性

有些代币所代表的资产是区块链内在的。这些资产是由共识规则所控制的,就如同代币本身。

区块链内在资产的代币不会有额外的对手方风险。

一个非常重要的未来,就是用区块链内的资产替代区块链外的资产,因此可以消除对手方风险。

使用代币:工具型代币还是权益型代币?

工具型代币是指用来支付某个服务、应用或资源的代币。

权益型代币可以被设定为没有投票权的,用来分红和分配利润的代币,也可以承载一个去中心化自治组织的投票权,这类组织的管理由持有代币的所有人共同投票决定。

对于一个初创公司,每次创新都增加了失败的风险。

有限的流动性、有限的应用范围和较高的沟通交易成本降低了代币的价值。

如果你在进行创业并且面临的是一个全新的市场,发行工具型代币并不会为你带来优势。

只有在你的应用必须使用工具型代币的时候,才考虑发行。使用代币来解决你所面临的市场准入或其他门槛问题。不要因为更快融资的原因而发行那些看上去不是公开募资的工具型代币。

以太坊的代币

以太坊账户的以太币余额在协议级别处理,而以太坊账户的代币余额在智能合约级别处理。

要在以太坊上创建新代币,你必须创建一个新的智能合约。

ERC20代币标准是代币的第一个标准。

ERC20标准定义了通过合约实现代币的通用接口,兼容此标准的所有代币都可以采用相同的方式被访问和使用。这个接口包含了一组必须实现的函数,及若干可选的函数和属性,可供开发者根据需要添加。

ERC20支持两种转账。第一种是单一式转账,直接使用transfer函数。

第二种方式是使用了approve和transferFrom的两步式交易。这个流程允许代币的持有人授权其他地址操纵他们的代币。这通常用于授权给某一个合约地址,进行代币的分发,但也可以用于交易所的场景。

ICO是一种众筹机制,公司和组织通过销售代币来筹集资金。

文中有创建和发行代币的例子,使用Truffle框架和Ganache测试链。

在把合约部署到具体的以太坊测试网络之前,先启动一个本地区块链环境来做一遍测试。

以太币是使用带有目标接受人地址的交易进行转账的,而代币的转账是通过代币合约内相关的状态转换进行的,使用合约作为地址,而不是接收方的地址。

一个发送以太币的合约会改变目标地址的状态。一个发送代币的合约只会改变合约内部的状态,而不是接收方地址的状态。即代币仅存在合约内部,出了合约则不存在代币。

如果你有一个长期使用的活跃以太币地址,特别是这个地址是在以太坊平台众筹前后创建的,那么你会发现这个地址充满了不知道来自何方的各种垃圾代币的余额。

你不能使用代币来支付一笔交易所需要的gas,代币合约也不会替你支付这笔gas。即需要L1层的代币来支付gas,有种用假币换真币的感觉。

ERC223方案试图解决不慎把代币转入不支持代币的合约这个问题,通过检测目标地址是否为合约的方式来完成。另一个针对代币合约的改进行方案是ERC777。

ERC721方案是针对不可替代物代币的标准,也称为契约代币。

ERC20将所有者作为映射的主键,跟踪每个所有者的余额;而ERC721将契约ID作为映射的主键,跟踪每个契约ID及其所有者。

代币标准

代币标准是实现的最小化标准。

现存的实现,比如说OpenZeppin,是“经过实战检验的”。

代币接口标准的扩展

很多项目在此基础上创建了扩展的实现,用于支持它们应用中所需要的功能。这些扩展包括:销毁、铸币、众筹、硬顶等等。

代币和ICO

在代币世界中生存的诀窍是将这种技术的长期愿景和影响与可能是巨大的短期ICO泡沫分离开来,这种泡沫充斥着欺诈行为。

三、以太坊客户端

不同客户端之间遵从相同协议和规范,所以在同一个网络中可以交互。

存在多个以太坊网络,比如以太坊、以太坊经典、Polygon、BSC等等。

每一个全功能节点可以帮助其他新加入网络的节点获取开始运行所需要的区块数据,全功能节点的另一个重要任务是为用户提供独立和权威的交易及合约验证。

运行一个全功能节点需要消耗大量的硬件资源和网络带宽。

也可以运行一个仅从远程调用以太坊的客户端,就是说,不在本地保存区块链数据,也不参与区块和交易验证。

轻客户端类似于比特币网络中的简单支付验证,也就是SPV节点。

全功能节点、远程客户端、轻节点之间的区别。

以太坊主网、公共测试网、本地测试网之间的区别。

四、以太坊背后的密码学

4.1 密钥和地址

截至本书出版时(18年),以太坊协议本身并没有任何加密信息,也就是说,所有通信和交易数据都不是加密的,因此所有人都必然可以读取。

一个私钥会与唯一一个以太坊地址(也称为账户)挂钩。

资金的访问与控制权都是通过数字签名实现的。

外部账户的以太坊账户地址由密钥对中的公钥生成。

合约背后就没有私钥来控制所有权。

4.2 公钥密码学和加密货币

质因数分解问题、离散对数难题。

公钥和私钥一起表示一个以太坊账户,公钥用于可访问账户管理(也就是地址),而私钥用于控制账户内持有的以太币,并控制使用智能合约时所需的认证程序。

4.3 私钥

私钥就是一组随机获取的数字,以太坊软件使用底层操作系统的随机数生成器生成一个256位的“熵”,作为随机源,放入256比特的哈希算法中,产生一个256比特的数字。

请使用密码学安全的伪随机数生成器(如CSPRNG)生成私钥,并且使用熵源充足的随机源做种子。

4.4 公钥

每个以太坊公钥都是椭圆曲线上的一个点(x, y)。

以太坊使用跟比特币系统相同的椭圆曲线算法,称为secp256k1。

通过私钥可以推算出公钥,但是通过公钥无法反向计算得出私钥,因为这个数学算法是单向的。

采用130个十六进制字符(65字节)表示的公钥。这是由SECG所发布的行业标准的一种序列化编码方式。

以太坊只使用未压缩的公钥,因此唯一相关的前缀就是0x04。

4.5 密码学哈希函数

以太坊协议中多处用到了名为Keccak-256的密码学哈希函数。

如何辨别所使用的程序库是FIPS-202 SHA-3还是Keccak-256:

  1. Keccak256(“”) = c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
  2. SHA3(“”) = a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a

4.6 以太坊地址

从私钥开始,通过椭圆曲线乘法运算获得了一个公钥,然后使用Keccak-256来计算公钥的哈希值,保留后20位(大端序中最末的字节),这就是我们的以太坊地址。

ICAP地址可以用于编码以太坊地址,也可以用于编码注册在以太坊域名注册服务之下的通用名称。

EIP-55为以太坊地址提供了一种后向兼容的校验机制,这个机制是通过修改十六进制地址中的大写字母来实现的:对全小写的十六进制地址计算Keccak-256哈希,如果在哈希中对应的十六进制大于或者等于8,就把这个字母改为大写。

疑惑

  1. 有效范围什么意思?
  2. 公钥加密算法中的G是固定的吗
  3. 为什么要对地址进行编码?

初入职场

7月26号入职,进去先办手续,然后去工位,开始装环境装软件。

unity用的2018版本,IDE用的idea2017,项目管理用的Redmine,版本控制用的SVN,本地搭建了SVN服务器和共享云盘。

为了实现热更新,使用c#实现底层逻辑,lua实现业务逻辑,平时不会动底层的c#,只需要编写业务层面的lua。

前端框架为魔改后的luaframework,用的MVC架构,前端代码共100w+行,听说mj这体量还算小的qaq。

后端框架用的SpringBoot,协议用的protobuf。

说实话,平时福利我觉得还不错,包两餐,二四有下午茶,工作环境啥的都挺好的。

熟悉项目

进去第一周,先看代码,熟悉项目,上手基本操作,比如说项目运行,挂载调试,设计UI场景,SVN提交等等。

项目是真的没多少注释,还没要求项目代码规范,每个人写的不一样,看得心累。

直到自己处理了几个需求后,8月17号才理解他们的逻辑。

其实就是在解析后端发送的数据,然后展示到对应的位置上。

model负责请求数据,设计接口以便view来读取数据,view就负责展示数据并进行业务逻辑判断。

开始干活

第二周开始干活,处理点海外的优化需求。

果然还是得需求驱动,带着需求来看代码有干劲多了。

二三四周一周一个优化需求,第五周一周来了5个优化需求qaq,还好离职前做完了。

其实我没明白,为什么说我干活他们第一反应都是在做海外的活,无论是cm还是hy。

当吃瓜群众

呆到第三周才知道工作室领导集体离职了,我就说怎么领导只来两天,那两天还一直摸鱼。

果然领导才是第一生产力,领导来的那两天hx哪敢这么摸鱼,现在晶核时间都比idea时间长(开个玩笑)。

领导们走了之后,工作室是真乱啊,需求提的少了,大家都没事做,而且一直有人被hy叫去会议室面谈。

可惜了,好像并不会叫实习生面谈,乐子没了。

初用unity感觉

感觉sk这种游戏公司里,使用unity、qt这类工具的程序员,和传统公司里用js的程序员区别有点大。

感觉他们的技术建立在unity这类工具上,而不是编程语言上。

可能是mjwy是2d卡牌手游的缘故吧,不需要前端过多的处理界面,不需要前端做特效啥的。

不知道他们的新项目xtc能不能做起来,祝好。

大无语事件

第二周的某天,在园区班车上听到hx用潮汕话说我,主要是没听清是说我好话还是坏话,有点郁闷。

真别在背后讨论别人,尤其用方言讨论,印象分大减。

领导交接

原来打包怎么复杂的嘛,fg学了半天还是战战兢兢的。

早知道就留一份public了,说不定还能学点东西。

之前瞅过一眼public里的代码,感觉就是在不停的解析参数,有点记不清了qaq,不管了。

END

总的来说,还是有收获的,看看职场和学校的不同。

可惜了,这一离职有很多人是真的见不到,成过客了,祝好叭,sayorala了各位。

六、以太坊交易

交易是从外部账户发出的经过签名的消息,经传播后记录在区块链上。

6.1 交易结构

以太坊客户端在收到交易后会把交易保存在内存中并使用应用内部的交易格式,其中添加了一些推导出的数据,不具有普适性,这里讨论的交易格式为以太坊网络上交易传输时的交易格式,包括以下内容:

  • nonce:由构建交易的外部账户提供,防止重放攻击
  • gas price:支付的gas
  • gas limit:最大gas
  • recipient:接收方以太坊地址
  • value:以太币数量
  • data:见下文
  • v,r,s:椭圆曲线签名的三个部分

使用RLP编码标准,其中不包含字段标识符,由长度偏移量表示每个字段的长度。

应用添加的数据:外部地址、交易ID等等——为了节约空间,交易中并不包含外部用户的地址,vrs可计算出外部用户的公钥,由公钥可得出外部用户的地址,交易ID同理。

6.2 交易的随机数

黄皮书中的定义:一个数值,等于这个地址发出的交易数量,当这个地址与合约关联时,是这个地址所创建的合约数量。

nonce可以说是发送方地址的一个属性,用于确定发出的交易的顺序以及避免交易重复,不会显示保存而是由已确认的交易动态计算出的。

交易待确认时getTransactionCount无法返回正确值,可用parity_nextNonce()计算下一个nonce。

6.3 交易的gas

独立的虚拟货币,和以太币有汇率关系。

最低可到0,但存在交易无法确认的可能。

由于合约所消耗的gas可能不同,所以需要设置gas limit

6.4 交易的接收方

接收方在交易的to字段中指定,字段中包含了一个20字节的以太坊地址,该地址可以是外部账户,也可以是合约的地址。

以太坊不会验证地址的正确性。

6.5 交易中的以太币和数据

交易只有value无data:支付操作

交易只有data无value:调用合约

交易既没有value也没有data:没作用,但允许存在

目的地址

如果目的地址为外部账户or未注册为合约的地址,以太坊会在目的账户余额中增加转入的以太币。

如果目的地址为合约,EVM则会执行这个合约,并调用data中指定的函数;若data中为空,则执行合约的回退函数。此时data中有以下部分:函数选择器、函数参数

6.6 特殊交易:合约创建

合约创建交易的目的地址是一个特殊的地址——零地址,即to字段为0x0,该地址永远不能用来支付以太坊or触发交易。

向合约创建地址发送只有value无data的交易相当于转账,也有专门销毁以太币的地址。

合约创建交易中的data为代码编译后的字节码,value中可以包含以太币作为合约的初始余额。

奇思妙想

  1. 后面的nonce会被搁置,那可不可以先发后面的nonce来实现智能合约的操作?

疑惑

  1. 交易触发合约执行?
  2. 交易中的data有什么用?——普通交易中data经常为空,调用智能合约函数的交易中data为函数名和参数。
  3. 交易中的随机数真的随机吗?
  4. 为什么向没有私钥的地址发送以太币相当于销毁以太币?——没有已知的私钥,以致无法生成签名来使用。
  5. 账户是否就等于地址?——账户由私钥和公钥定义,外部账户的地址为公钥哈希值的后20位字节,合约账户的地址则为该合约在区块链中的位置。账户通过地址表示。
  6. 交易目的地址为合约时,该合约是新的,还是别人已经写好了的?——应该是已经写好了的。

七、智能合约和Solidity

7.1 什么是智能合约

数字化的承诺,运行在EVM中。

特点:

  • 不可改变
  • 有确定性:每次输出是相同的

7.2 智能合约的生命周期

合约的地址由合约的创建交易在创建账户和随机数时生成。

智能合约并没有对应的私钥。

智能合约仅在被其他交易调用时执行。

不存在并发执行——EVM可认为是一台单线程计算机。

交易是原子的,若程序出错,则回滚之前所有操作,依旧会扣除gas。

合约不能更改,但可以通过执行SELFDESTRUCT的EVM字节码来删除,删除会提供gas退款。

SELFDESTRUCT需要开发者编写,否则无法删除。

7.3 以太坊高级编程语言

EVM高度隔离且极其简单。

智能合约的编程语言应极力避免任何可能的副作用。

Solidity为指令式编程语言。

7.4 使用Solidity编写智能合约

Solidity项目主要产出为Solidity编译器和ABI接口标准

7.5 以太坊合约的应用程序二进制接口

ABI是向机器指令层面编码和解码并传送数据的主要方式。

用JSON格式表示,包含描述函数和事件的数组。

应用与合约的交互完全依赖于ABI和应用实例部署的以太坊地址。

7.6 使用Solidity进行编程

预定义的全局变量和函数

Solidity基本数据类型:

  1. 布尔型(bool)
  2. 整数型(int, uint)
  3. 固定浮点数(fixed, ufixed):ufixed32x2表示该变量有32bit,小数点后有2位
  4. 地址address,有成员函数balance, transfer…
  5. 字节数组,从bytes1到bytes32,有固定和动态的区别
  6. 枚举,enum name{}
  7. 数组
  8. 结构体,struct name{}
  9. 映射,mapping(key_type=>value_type)
  10. 时间单位
  11. 以太币单位

触发合约执行的交易(msg)的属性:

  1. msg.sender:发起合约调用的地址
  2. msg.value:以太币数量
  3. msg.gas:当前可用gas数量
  4. msg.data:调用时传入的数据
  5. msg.sig:函数选择器

交易(tx)的属性:

  1. tx.gasprice:调用交易的gas价格
  2. tx.origin:发起交易的外部账户的地址

block的属性:

  1. block.blockhash(blockNumber):指定区块的哈希值,仅限于当前区块之前不超过256个区块
  2. block.coinbase:当前区块的矿工地址
  3. block.difficulty:POW的难度
  4. block.gaslimit:最大gas数量
  5. block.number:当前区块编号
  6. block.timestamp:当前区块的时间戳

address的属性:

  1. address.balance:地址余额
  2. address.transfer(amount):转出一定以太币
  3. address.send(amount):类似transfer
  4. address.call(payload)
  5. address.callcode(payload)
  6. address.delegatecall()

内建函数:

  1. addmod(), mulmod()
  2. sha256(), sha3()等等hash函数
  3. ecrecover,获得签名地址
  4. selfdestruct(recipient),删除合约并将剩余以太币转到recipient
  5. this,当前账户以太坊地址

合约定义

其他对象:

  1. interface
  2. library:只被部署一次

函数调用范围:

  1. public:可被交易,其他合约和合约内部调用
  2. external:类似public,不能内部调用除非指明this
  3. internal:只能被当前合约及其子合约内部调用
  4. private:只能被当前合约调用

函数都是可见的。

函数的行为:

  1. constant和view:不修改任何状态
  2. pure:不会在区块链中读取or写入任何数据
  3. payable:接收外部支付

构造函数constructor和自毁函数selfdestruct

函数修饰符modifier:_的地方会被修饰符的代码代替

继承is:contract 子合约 is 父合约1,父合约2 {}

错误处理

如果条件不满足则触发错误并且中止合约的执行:

  1. assert用于判断输出条件为真的情况
  2. require用来判断输入

立即中止合约执行并把状态回滚:

  1. revert
  2. throw已被淘汰

事件

当交易完成后,无论成功与否,都会生成一个交易收据,收据中包含由事件生成的日志。

关键字:

  1. indexed
  2. emit:将数据写入日志

调用其他合约

import引入合约文件

new实例化合约

可以添加已存在的实例,但很危险

call和delegatecall

这里给了调用合约的例子,值得看一下。

与gas有关的注意事项

如果gas耗尽,将触发以下事件:

  1. 抛出“out of gas”异常
  2. 恢复状态
  3. 消耗gas

避免消耗过多gas:

  1. 避免动态大小的数组
  2. 避免调用其他合约
  3. 使用estimateGas估计gas开销

疑惑

  1. 合约没有私钥,那要怎么使用其地址上的以太币?
  2. msg.sig是什么,有什么用?
  3. address.call是什么,有什么用?
  4. 假如我以简单的难度快速的算出了多个区块,别人算出了一个高难度的区块,那这时候主链怎么选择?
  5. interface例子?
  6. 事件indexed有什么用?
  7. 怎么理解添加已存在的实例?
  8. 使用Solidity进行编程这节需要重读
0%