• 以太坊账户类型

  • 交易部署合约

  • 交易调用合约(ERC20 等)

  • 合约运行报错

  • 合约的gas不足

  • 抛出event的交易

  • 多合约互相调用

  • Token 与 NFT 数据区别

  • 交易、消息与调用(Message Call)的区别

介绍区块链交易

区块链是一种记录保存系统,在将条目添加到数据链之前会有多个源来验证该条目。数据一旦添加,便无法更改,记录随之分布到网络中的多个位置。向区块链序列添加新记录(称为区块)需要由连接到区块链网络的多个成员进行验证。这些数据区块相互链接而形成。区块链中的全部交易对其中的所有人公开,但所有个人身份都是隐藏的。

区块链技术使用算法为每个区块分配加密哈希(包含字母和数字的唯一字符串,有时也称为“数字指纹”)。除哈希以外,每个区块还包含带时间戳的先前交易的记录集,以及前一个区块的哈希。正是这种机制确保了在链中的连续区块之间建立起不可变的链接。

加密术和时间戳的组合确保了区块链技术能自动验证这个增长的哈希序列永远不会更改。

比特币交易流程:

交易的生成→交易的传播→整个网络节点验证→记录到区块链

第一步:所有者A利用他的私钥对前一次交易(比特货来源)和下一位所有者B签署一个数字签名,并将这个签名附加在这枚货币的末尾,制作成交易单,B以公钥作为接收方地址

第二步:A将交易单广播至全网,比特币就发送给了B,每个节点都将收到的交易信息纳入一个区块中。对B而言,该枚比特币会即时显示在比特币钱包中,但直到区块确认成功后才可用。确认这笔交易真实有效后,矿工即可将这条交易信息与其他交易信息一起放入某个区块

第三步:每个节点通过解一道数学难题,即找到数学难题的解, 但是答案并不唯一。这个过程也是尝试对这个区块进行“挖矿”, 从而去获得创建新区块权利,并争取得到比特币的奖励(新比特币会在此过程中产生)

第四步:当一个节点找到解时,它就向全网广播该区块记录的所有盖时间戳交易,并由全网其他节点核对

第五步:全网其他节点核对该区块记账的正确性,验证无误后,他们会将有效区块的信息加入自己的区块链,表明交易完成。这个过程中,其他矿工仍需将前一个区块的哈希值加入新区块,最终将所有区块相连,构成名副其实的“区块链”。

以太坊账户类型

  • 外部账户 (Externally owned account, EOA )

  • 合约账户 (Contract accounts)

外部账户(用户账户/普通账户)

  • 有对应的以太币余额

  • 可发送交易(转币或触发合约代码)

  • 由用户私钥控制

  • 没有关联代码

合约账户

  • 有对应的以太币余额

  • 有关联代码

  • 由代码控制

  • 可通过交易或来自其它合约的调用消息来触发代码执行

  • 执行代码时可以操作自己的存储空间,也可以调用其它合约

账户主要参数

Address: 20-bytes(160bit), 从公钥计算得来

nonce:如果是外部账户,表示从这个账户发出的交易个数;如果是合约账户,表示这个账户创建的合约个数

balance:账户余额

codeHash:如果是外部账户,它是空字符串的hash,如果是合约账户表示EVM代码的hash

以太坊交易类型

有两种类型的交易: 一种是能够产生消息调用的交易,另一种是能够生成新账户的交易(比如说生成合约)

交易Transaction指存储了消息的签名数据包,在区块链上从一个外部账户发送到另外一个外部账户。

消息Message指一些虚拟对象,他们不会被序列化,且仅存在于以太坊的执行环境中,他们可以被理解为函数调用。

0. 普通交易

转账是最常见的一种普通交易,这里转账是指从一个账户向另一个账户发送货币以太币。因为它是 EVM 原生指令,不需要使用智能合约。发送转账交易的时候只需要指定交易的发送者、接收者、转币的数量。

交易包含以下主要字段:

type:交易的类型,ContractCreation(创建合约)还是MessageCall(调用合约或转账)

nonce: 发送地址的交易计数,也可以理解为(“仅使用一次的数字”)是以太坊网络用来跟踪你的账户状态、避免多重支付和重放攻击的一个数值(可以理解成流水号)。当你的交易因为 gas fee 太低而暂时无法打包的时候,你可以使用同一个 nonce 但指定更高的 gas price 来 “替换” 你的那笔卡住的交易;一旦这笔 “更快” 的交易得以打包上链,你原来签名的那笔交易(因为使用了同一个 nonce)就会被以太坊的节点抛弃掉了。

gasPrice:为交易付出的Gas价格

gas: 为交易付出的gas

to:接受方地址, 若to为空,表示创建合约

value: 向目标账户发送的金额

Input:交易的附加数据

R, S, V:交易签名结构体

data: 编译的合约代码 或者是调用函数的签名和编码的参数;

1.JSON-RPC API

作用:为了让客户端连接以太坊节点的协议,通过使用RPC API来查询区块链参数,发送交易等

eth_signTransaction

对交易进行签名,随后用 eth_sendRawTransaction 提交到网络上

相关参数为:

  • from: 20字节,发送方地址;

  • to: 20字节,接收方地址,当为空时,为创建合约交易;

  • gas: 可选项,默认为90000;

  • gasPrice: 可选项;

  • value: 可选项,交易金额;

  • data: 编译的合约代码 或者是调用函数的签名和编码的参数;

  • nonce: 可选项, 可以覆盖同一nonce的pending交易。

返回值:

  • 签名名的交易对象

// Requestcurl -X POST --data '{"id": 1,"jsonrpc": "2.0","method": "eth_signTransaction","params": [{"data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675","from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155","gas": "0x76c0","gasPrice": "0x9184e72a000","to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567","value": "0x9184e72a"}]}'// Result{"id": 1,"jsonrpc": "2.0","result": "0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b"}

eth_sendTransaction

创建消息调用的交易,或者data域中包含代码的时候,为创建合约的交易

相关参数和eth_signTransaction差不多

返回值:

  • 交易的Hash值

eth_sendRawTransaction

创建消息调用的交易或者创建合约,已经签名的交易

参数:

dat: 签名的交易数据

返回值:

  • data: 32字节,交易的hash值。

eth_getTransactionByHash

  • 返回指定交易对应的交易信息

eth_getTransactionReceipt

  • 返回指定交易对应的收据信息

2.交易部署合约

从外部账户到合约账户的消息会激活合约账户的代码,执行各种操作,也就是我们常说的调用智能合约。可以通过向0地址发起交易来创建合约账户。

3.交易调用合约(ERC20 等)

对于驱动合约执行的交易,有几个关键点:

1、合约在创建时,会生成一个合约地址,所以,通过交易调用合约的时候,就以合约地址为目的地址

2、在交易的data域,会标明要调用合约的哪个函数,并且提供了该函数所需要的参数

3、调用合约的交易,同样可以发送一笔以太币给合约,金额在value字段显示

4.合约运行报错

5.合约的gas不足

什么是矿工费

矿工费是以太坊先提出来的,这也是以太坊和比特币的不同之处,以太坊引入了 gas 的概念,gas的目的是限制执行交易所需的工作量,同时为执行支付费用。gas 用来衡量你的这笔交易(或者合约代码调用)所消耗的资源(包括计算量,存储,带宽等)

矿工费怎么计算

当你在以太坊区块链上进行转账时,矿工要把你的交易打包并放上区块链,才能使交易完成,在这过程中会消耗区块链的运算资源,所以要支付费用。Gas由两部分组成:Gas Price(价格) * Gas limit(限制)。Gas Price(单位是Gwei) 指的是用户愿意花费于每个 Gas 单位的价钱,由用户自己决定。Gas Limit 是用户愿意为执行某个操作或确认交易支付的最大Gas量(最少21,000),不同时期、不同的操作默认值不同,在执行操作时可设置Gas Limit

矿工费不足会怎样

矿工会优先选取Gas合理,Gas Price较高的交易进行打包。如果用户交易时所支付的矿工费非常低,那么这笔交易可能不会被矿工打包, 从而造成交易失败

交易失败的特点

  • 失败的交易一旦被执行,就一定会被打包到区块链中,并且执行过程中消耗的gas也不会退还,交易的成功与失败可以使用交易的收据状态进行判断

  • 失败的交易如果没有打包到区块,那么可能的原因就有很多了,根据交易所处的阶段不同大概有这么几种可能:

  • a.交易gas过低或参数错误根本没有进入到pending队列

  • b.交易进入pending进行处理,然而在检查gas等参数时报错被丢弃

6.抛出event的交易

事件

当定义的事件触发时,我们可以将事件存储到EVM的交易日志中,日志是区块链中的一种特殊数据结构。日志与合约关联,与合约的存储合并存入区块链中。只要某个区块可以访问,其相关的日志就可以访问。但在合约中,我们不能直接访问日志和事件数据(即便是创建日志的合约)

事件和日志的主要用途有三种:

  1. 帮助用户客户端(web3.js)读取智能合约的返回值;

  1. 智能合约异步通知用户客户端(web3.js);

  1. 用于智能合约的存储(比Storage便宜得多)

使用时机

在交易中如果修改了状态数据时,就需要抛出event

pragma solidity ^0.4.0;contract Transfer{event transfer(address indexed _from, address indexed _to,uint indexedvalue);function deposit() payable {address current = this;uintvalue = msg.value;transfer(msg.sender, current,value);}function getBanlance() constantreturns(uint) {return this.balance;}/* fallback function */function(){}}

7.多合约互相调用

在 Solidity 中,call 函数簇可以实现跨合约的函数调用功能,其中包括 call、delegatecall 和 callcode 三种方式。

以下是 Solidity 中 call 函数簇的调用模型:

.call(…) returns (bool) .callcode(…) returns (bool) .delegatecall(…) returns (bool)

这些函数提供了灵活的方式与合约进行交互,并且可以接受任何长度、任何类型的参数,其传入的参数会被填充至 32 字节最后拼接为一个字符串序列,由 EVM 解析执行。

在函数调用的过程中, Solidity 中的内置变量 msg 会随着调用的发起而改变,msg 保存了调用方的信息包括:调用发起的地址,交易金额,被调用函数字符序列等。

三种调用方式的异同点

  • call: 最常用的调用方式,调用后内置变量 msg 的值会修改为调用者,执行环境为被调用者的运行环境(合约的 storage)。

  • delegatecall: 调用后内置变量 msg 的值不会修改为调用者,但执行环境为调用者的运行环境。

  • callcode: 调用后内置变量 msg 的值会修改为调用者,但执行环境为调用者的运行环境。

8.Token 与 NFT 数据区别

在区块链上,数字加密货币分为原生币和代币两大类。前者如大家熟悉的比特币、以太币等,拥有自己的主链,使用链上的交易来维护账本数据;代币则是依附于现有的区块链,使用智能合约来进行账本的记录,如依附于以太坊上而发布的token。代币之中又可分为同质化和非同质化两种

同质化代币,即FT(Fungible Token),互相可以替代、可接近无限拆分的token。例如,你手里有一个比特币与我手里的一个比特币,本质上没有任何区别,这就是同质化,就是同质化币。

而非同质化代币,即NFT,则是唯一的、不可拆分的token,如加密猫、token化的数字门票等。也就相当于带有编号的人民币,这个世界上不会有两张编号一样的人民币,也不会有两个完全一样的NFT

元数据(Metadata)是所有 NFT 合约的重要组成部分。

NFT 合约的元数据(Metadata)文件是存储在区块链之外某处的 JSON 文件。通过一些技巧,可以在链上执行此操作,也可以在 IPFS 上执行此操作,或者在自己构建的服务器上执行,可以考虑使用 CDN。这些文件可能以它们存储的令牌数据命名 tokenId

{"description": "Friendly OpenSea Creature that enjoys long swims in the ocean.", "image": "", "name": "Dave Starbelly","attributes": [{"trait_type": "Base", "value": "Starfish"}, {"trait_type": "Eyes", "value": "Big"}], }

9.为何交易已确认,Etherscan 上没有数据

通常来说交易确认了 ,浏览器节点是百分百可以查到。

  1. 浏览器中心化有问题,数据没有显示出来, 数据被过滤或者删除

  1. 网络延迟问题,数据在池中中排队

10.合约什么类型的代码最后会影响 Etherscan 上的数据,比如 emit Event?

11.交易、消息与调用(Message Call)的区别

交易Transaction指存储了消息的签名数据包,在区块链上从一个外部账户发送到另外一个外部账户。

消息Message指一些虚拟对象,他们不会被序列化,且仅存在于以太坊的执行环境中,他们可以被理解为函数调用。

合约中函数的调用创建的是调用还是交易?

考虑一下这四种情况:

  • 使用调用(call)直接对合约函数进行调用

  • 使用sendTransaction直接对合约函数进行调用

  • 使用调用(call)通过合约对合约函数进行调用

  • 使用sendTransaction通过合约对合约函数进行调用

第一种情况与第三种情况是很明显的调用,第二种情况由于使用的是sendTransaction方法,因此它创建了一笔交易。比较特殊的是第四种情况,它看似是生成了一笔交易,但是由于以太坊黄皮书中对交易的定义中提到,交易是需要外部参与者(External Actor)进行签名的消息,所以第四种情况没有生成交易。