以太坊的数据组织
以太坊的数据组织初步理解以太坊虚拟机EVM的设计与原理 这篇文章主要介绍以太坊的数据组织形式,构建以太坊各部分数据结构是如何组织的系统观。随后,我将会选取黄皮书中的核心设计思想,写得相对通俗易懂。各部分具体的数据结构,将会在后续的源码解读中给出。 概览 以太坊的区块由区块头和区块体构成,区块头存储元数据,通过区块哈希形成链式结构。区块体用于存储交易的集合和其他数据,大致结构如下: Trie Tree Trie Tree 被称作字典树,或者 前缀树 (prefix Tree),用于管理键值对类型的多叉树。字典树的 Key 不是直接保存在某一个节点,而是通过节点在树中的位置确定,类似于哈夫曼编码树。因此,可知子节点都有相同的前缀。只有叶子节点才存放 Value,从根节点到叶子节点形成的路径上的节点,按照顺序排列构成 Value 的 Key. 假如 节点 d 存储 Value,则 and 是它的 Key 总体如下: 根节点不包含字符,根节点外的所有节点都只包含一个字符。 从根节点到某个节点,路径上经过的的字符连起来,为该节点对应的 Key. 每个节点的 Key...
初步理解以太坊虚拟机
以太坊的数据组织初步理解以太坊虚拟机EVM的设计与原理 体系结构 存储层 一般的客户端采用 LevelDB 数据库,而 OpenEthereum 采用了 RocksDB。LevelDB 是 Key-Value 的、基于 Log-Structured Merge Tree 的非关系数据库。例如 geth 的所有区块数据都是存储在 LevelDB 中,而 LevelDB 的实现在源代码的 ethdb 包内。 数据层 以太坊的数据层主要定义了数据结构、数据模型、哈希函数、签名算法等。以太坊采用独特的数据结构保护区块头和区块体,区块头含有交易的 Merkle 根哈希值,还有账户状态的 Merkle 根哈希值、日志的 Merkle 根哈希值。以太坊中 Merkle 根哈希值是采用 Merkle Patricia Tree 计算的。哈希函数使用 keccak256,数字签名采用 ECDSA。 网络层 以太坊节点通信采用的 p2p 协议是 DEVp2p,包含了 RLPx、Discv4 等子协议。RLPx 是安全的数据传输协议,采用 ECIES(Elliptic Curve...
(八)合约的高级特性(完)
区块链基础(一)初步理解智能合约(二)代码结构和合约特性(三)控制结构(四)类型(五)字面量和内置单位、函数(六)应用二进制接口(七)特殊函数(八)合约的高级特性(完) 继承 继承的机制和 python 的非常相似,但是存在差异。一般而言使用过 C++, 基本已经掌握。 当合约继承其他的合约时,只会在区块链上生成一个合约,所有相关的合约都会编译进这个合约,调用机制和写在一个合约上一致。 继承时,全局变量无法覆盖,如果出现可见的同名变量会编译错误。通过例子来体会细节,重点理解语法,而不是程序逻辑。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.7.0 <0.9.0;contract Owned { constructor() { owner =...
DeFi攻击事件研究
前言:本文只为了交流学习,为了快速学习,已有的写的较好的资料直接照抄,并且在参考中注明来源。介绍的都非常简略,但是读者可以根据参考链接得到详细的讲解。 汇总表格 发生时间 名字 类型 损失金额 简述原因 代码 txhash 2022 年 07 月 25 日 LPC BNB 约 45,715 美元 实际的账户余额在后续操作中变化了,但是变量 recipientBalance 没有再次更新,导致后续计算余额偏大。 0x0e970ed84424d8ea51f6460ce6105ab68441d4450a80bc8d749fdf01e504ed8c 2022 年 06 月 27 日 XCarnival NFT ETH,业务逻辑漏洞 约 380 万美元 未考虑抵押物被取出不能借款的业务逻辑,主要是 isWithdraw(bool) 未在 borrow...
(七)特殊函数
区块链基础(一)初步理解智能合约(二)代码结构和合约特性(三)控制结构(四)类型(五)字面量和内置单位、函数(六)应用二进制接口(七)特殊函数(八)合约的高级特性(完) 底层函数交互 特殊交互方式 call 是底层的调用(没有封装过),直接发送消息给合约。方式如下: 所有的参数,都会打包成一串 32 个字节,连续存放的序列。 若第一个参数是函数的签名(函数哈希之后的前 4 个字节),则第二、第三这些后面的参数是函数的参数。如:nameReg.call(bytes4(keccak256("fun(uint256)")), a); <address>.call(bytes memory) returns (bool, bytes memory) 用给定的合约发出低级 CALL 调用,返回成功状态及返回数据,发送所有可用 gas,也可以调节 gas。 123456789101112131415161718192021222324252627282930313233343536373839//...
(六)应用二进制接口
区块链基础(一)初步理解智能合约(二)代码结构和合约特性(三)控制结构(四)类型(五)字面量和内置单位、函数(六)应用二进制接口(七)特殊函数(八)合约的高级特性(完) 接口含义 在地址类型的介绍中提到了底层调用的 call 函数,这里将会介绍它的用法,以及和 ABI 函数的配合。 ABI 全名 Application Binary Interface,翻译为应用二进制接口。它定义了与合约交互的规范,因此底层函数 (如 call) 直接给合约发消息前,需要了解 ABI。 ABI 是由合约生成的,规定与合约交互方式的规则,它是一个接口,常被 web3 等库调用。熟悉 REST API 的读者应该能很快理解。 例如下面是智能合约: 12345678910111213141516171819202122232425262728293031323334353637383940// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.7.0 <0.9.0;/** * @title Owner * @dev...
(五)字面量和内置单位、函数
区块链基础(一)初步理解智能合约(二)代码结构和合约特性(三)控制结构(四)类型(五)字面量和内置单位、函数(六)应用二进制接口(七)特殊函数(八)合约的高级特性(完) 字面常量 地址 地址的字面常量有 EIP-55 的标准(区分大写字母和小写字母来验证),只有经过校验后才能作为 address 变量。 有理数和整数 十进制的小数字面常量都会带一个.比如1. .1...
(四)类型
区块链基础(一)初步理解智能合约(二)代码结构和合约特性(三)控制结构(四)类型(五)字面量和内置单位、函数(六)应用二进制接口(七)特殊函数(八)合约的高级特性(完) Solidity 的值传递和引用传递有自己的规则,通过不同的存储域决定,后面详述。 默认值:Solidity 中不存在undefined或null,每种变量都有自己的默认值,一般是“零状态”。 运算符优先级 布尔类型 bool:常量值为true和false 整型 int / uint :分别表示有符号和无符号的不同位数的整型变量。 支持关键字 uint8 到 uint256 (无符号,从 8 位到 256 位)以及 int8 到 int256,以 8 位为步长递增。 uint 和 int 分别是 uint256 和 int256 的别名。 可以用type(x).min type(x).max来获取这个类型地最小值和最大值。 位运算 在二进制地补码上操作,特别的 ~int256(0)==...
(三)控制结构
区块链基础(一)初步理解智能合约(二)代码结构和合约特性(三)控制结构(四)类型(五)字面量和内置单位、函数(六)应用二进制接口(七)特殊函数(八)合约的高级特性(完) 表达式和控制结构 Solidity 支持 if, else, while, do, for, break, continue, return这些和 C 语言一样的关键字。 Solidity 还支持 try/catch 语句形式的异常处理, 但仅用于 外部函数调用 和 合约创建调用. 由于不支持非布尔类型值转换成布尔类型,因此if(1){}是不合法的。 函数调用 内部调用 内部调用再 EVM 中只是简单的跳转(不会产生实际的消息调用),传递当前的内存的引用,效率很高。但是仍然要避免过多的递归,因为每次进入内部函数都会占用一个堆栈槽,而最多只有 1024 个堆栈槽。 外部调用 只有external或者public的函数才可以通过消息调用而不是单纯的跳转调用,外部函数的参数会暂时复制在内存中。 this不可以出现在构造函数里,因为此时合约还没有完成。 调用时可以指定 value 和...
(二)代码结构和合约特性
区块链基础(一)初步理解智能合约(二)代码结构和合约特性(三)控制结构(四)类型(五)字面量和内置单位、函数(六)应用二进制接口(七)特殊函数(八)合约的高级特性(完) 代码结构 直观理解代码结构,下面是铸造,生成代币的代码。 123456789101112131415161718192021222324252627pragma solidity ^0.4;contract Coin{ //set the "address" type variable minter address public minter; mapping (address =>uint) public balances; // set an event so as to be seen publicly event Sent(address from,address to,uint amount); //constructor only run once when creating contract,unable to...