【以太坊源码】交易(一)
交易是区块链中最基本也是最核心的一个概念,在以太坊中,交易更是重中之重,因为以太坊是一个智能合约平台,以太坊上的应用都是通过智能合约与区块链进行交互,而智能合约的执行是由交易触发的,没有交易,智能合约就是一段死的代码,可以说在以太坊中,一切都源于交易。下面就来看看在以太坊中交易是什么样的,交易里面都有什么。
交易的数据结构
在core/types/transaction.go
中定义了交易的数据结构:
type Transaction struct {data txdata// cacheshash atomic.Valuesize atomic.Valuefrom atomic.Value
}
在这个结构体里面只有一个data
字段,它是txdata
类型的,其他的三个字段hash
size
from
是缓存字段,txdata
也是一个结构体,它里面定义了交易的具体的字段:
type txdata struct {AccountNonce uint64Price, GasLimit *big.IntRecipient *common.Address `rlp:"nil"` // nil means contract creationAmount *big.IntPayload []byteV *big.Int // signatureR, S *big.Int // signature
}
各字段的含义如下:
AccountNonce
:此交易的发送者已发送过的交易数Price
:此交易的gas priceGasLimit
:本交易允许消耗的最大gas数量Recipient
:交易的接收者,是一个地址Amount
:交易转移的以太币数量,单位是wei
Payload
:交易可以携带的数据,在不同类型的交易中有不同的含义V R S
:交易的签名数据
注意:这里并没有一个字段来指明交易的发送者,因为交易的发送者地址可以从签名中得到。
在transaction.go
中还定义了一个jsonTransaction
结构体,这个结构体用于将交易进行json序列化和反序列化,具体的序列化和反序列化可以参照MarshalJSON
和UnmarshalJSON
函数。以太坊节点会向外部提供JSON RPC服务,供外部调用,RPC服务通过json格式传输数据,节点收到json数据后,会转换成内部的数据结构来使用。jsonTransaction
结构体使用go语言的struct tag
特性指定了内部数据结构与json数据各字段的对应关系,例如内部的AccountNonce
对应json的nonce
,Amount
对应json的value
。web3.js的eth.getTransaction()
和eth.sendTransaction()
使用的数据就是json格式的,根据这个结构体就可以知道在web3.js中交易的各个字段与程序内部的各个字段的对应关系。
type jsonTransaction struct {Hash *common.Hash `json:"hash"`AccountNonce *hexutil.Uint64 `json:"nonce"`Price *hexutil.Big `json:"gasPrice"`GasLimit *hexutil.Big `json:"gas"`Recipient *common.Address `json:"to"`Amount *hexutil.Big `json:"value"`Payload *hexutil.Bytes `json:"input"`V *hexutil.Big `json:"v"`R *hexutil.Big `json:"r"`S *hexutil.Big `json:"s"`
}
注:Payload
这个字段在eth.sendTransaction()
中对应的是data
字段,在eth.getTransaction()
中对应的是input
字段。
交易的Hash
下面是计算交易Hash的函数,它是先从缓存tx.hash
中取,如果取到,就直接返回,如果缓存中没有,就调用rlpHash
计算hash,然后把hash值加入到缓存中。
// Hash hashes the RLP encoding of tx.
// It uniquely identifies the transaction.
func (tx *Transaction) Hash() common.Hash {if hash := tx.hash.Load(); hash != nil {return hash.(common.Hash)}v := rlpHash(tx)tx.hash.Store(v)return v
}
rlpHash
的代码在core/types/block.go
中:
func rlpHash(x interface{}) (h common.Hash) {hw := sha3.NewKeccak256()rlp.Encode(hw, x)hw.Sum(h[:0])return h
}
从rlpHash
函数可以看出,计算hash的方法是先对交易进行RLP编码,然后计算RLP编码数据的hash,具体的hash算法是Keccak256
。
那么到底是对交易中的哪些字段计算的hash呢?这就要看rlp.Encode
对哪些字段进行了编码。rlp.Encode
代码在rlp/encode.go
中,不用看具体的实现,在注释中有这么一段:
// If the type implements the Encoder interface, Encode calls
// EncodeRLP. This is true even for nil pointers, please see the
// documentation for Encoder.
就是说如果一个类型实现了Encoder
接口,那么Encode
函数就会调用那个类型所实现的EncodeRLP
函数。所以我们就要看Transaction
这个结构体是否实现了EncodeRLP
函数。回到core/types/transaction.go
中,可以看到Transaction
确实实现了EncodeRLP
函数:
// DecodeRLP implements rlp.Encoder
func (tx *Transaction) EncodeRLP(w io.Writer) error {return rlp.Encode(w, &tx.data)
}
从这可以看出交易的hash实际上是对tx.data
进行hash计算得到的:txhash=Keccak256(rlpEncode(tx.data))
。
交易的类型
在源码中交易只有一种数据结构,如果非要给交易分个类的话,我认为交易可以分为三种:转账的交易、创建合约的交易、执行合约的交易。web3.js提供了发送交易的接口:
web3.eth.sendTransaction(transactionObject [, callback])
参数是一个对象,在发送交易的时候指定不同的字段,区块链节点就可以识别出对应类型的交易。
转账的交易
转账是最简单的一种交易,这里转账是指从一个账户向另一个账户发送以太币。发送转账交易的时候只需要指定交易的发送者、接收者、转币的数量。使用web3.js发送转账交易应该像这样:
web3.eth.sendTransaction({from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155",to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567",value: 10000000000000000
});
value
是转移的以太币数量,单位是wei
,对应的是源码中的Amount
字段。to
对应的是源码中的Recipient
。
创建合约的交易
创建合约指的是将合约部署到区块链上,这也是通过发送交易来实现。在创建合约的交易中,to
字段要留空不填,在data
字段中指定合约的二进制代码,from
字段是交易的发送者也是合约的创建者。
web3.eth.sendTransaction({from: "contract creator's address",data: "contract binary code"
});
data
字段对应的是源码中的Payload
字段。
执行合约的交易
调用合约中的方法,需要将交易的to
字段指定为要调用的合约的地址,通过data
字段指定要调用的方法以及向该方法传递的参数。
web3.eth.sendTransaction({from: "sender's address",to: "contract address",data: "hash of the invoked method signature and encoded parameters"
});
data
字段需要特殊的编码规则,具体细节可以参考Ethereum Contract ABI。自己拼接字段既不方便又容易出错,所以一般都使用封装好的SDK(比如web3.js)来调用合约。
【以太坊源码】交易(一)相关推荐
- 以太坊源码分析-交易
以太坊源码分析-交易 机理 先说一点区块链转账的基本概念和流程 用户输入转账的地址和转入的地址和转出的金额 系统通过转出的地址的私钥对转账信息进行签名(用于证明这 笔交易确实有本人进行) 系统对交易信 ...
- 以太坊源码学习 -- EVM
以太坊源码学习 – EVM 学习文档链接:here 一.虚拟机外 主要功能: 执行前将Transaction类型转化成Message,创建虚拟机(EVM)对象,计算一些Gas消耗,以及执行交易完毕后创 ...
- 以太坊源码学习(一) 正本清源
以太坊源码学习(一)正本清源 背景 geth源码一直在不断增加,优化,发展到现在已经非常庞大,第一次看geth源码,会有不小的难度.虽然如此,还是可以从geth仓库的第一个commit开始,这时的代码 ...
- 以太坊源码阅读3——MPT原理
以太坊源码阅读3--MPT原理 介绍 MPT(Merkel-Patricia Tree),翻译为梅克尔-帕特里夏树 MPT提供了一个基于密码学验证的底层数据结构,用来存储键值对( key-value) ...
- 以太坊源码分析(2)——以太坊APP对象
前言 从这一节开始,我将开始以太坊代码全覆盖讲解,讲解的流程是: 以太坊程序入口 基本框架 以太坊协议 发送一笔交易后发生了什么 启动挖矿 以太坊共识 p2p 网络 阅读本系列文章,将默认读者具备一定 ...
- 以太坊源码阅读5——POW源码分析
以太坊源码阅读5--POW源码分析 介绍 POW,proof of work,即工作量证明,是著名公bitcoin所采用的共识算法.简单来说,pow就是一个证明,由矿工使用算力进行计算(挖矿),竞争记 ...
- 3 v4 中心节点固定_死磕以太坊源码分析之p2p节点发现
死磕以太坊源码分析之p2p节点发现 在阅读节点发现源码之前必须要理解kadmilia算法,可以参考:KAD算法详解. 节点发现概述 节点发现,使本地节点得知其他节点的信息,进而加入到p2p网络中. 以 ...
- php区块链以太坊,兄弟连区块链教程以太坊源码分析CMD深入分析(一)
兄弟连区块链教程以太坊源码分析CMD深入分析. cmd包分析 cmd下面总共有13个子包,除了util包之外,每个子包都有一个主函数,每个主函数的init方法中都定义了该主函数支持的命令,如 geth ...
- 以太坊源码阅读2——RLP编码
以太坊源码阅读2--RLP编码 RLP介绍 目前网上的资料都是RLP(Recursive Length prefix),叫递归长度前缀编码,但目前源码的doc.go的第20行里面的注释写的是 The ...
- kademlia java_死磕以太坊源码分析之Kademlia算法
死磕以太坊源码分析之Kademlia算法 KAD 算法概述 Kademlia是一种点对点分布式哈希表(DHT),它在容易出错的环境中也具有可证明的一致性和性能.使用一种基于异或指标的拓扑结构来路由查询 ...
最新文章
- Linux 播放网易云音乐(树莓派)
- python表达式_python表达式是什么
- 反沙箱——SetErrorMode
- qq浏览器主页_安卓浏览器哪家强?这些小众好用的手机浏览器你知道吗
- python for语句_从零开始py个thon3:循环语句(1)
- Ngnix中的fastcgi參数性能优化和解释
- Maven打包时报Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.2:war解决方案
- pta 编程题10 Root of AVL Tree
- 界面原型创建工具Axure使用教程
- vue datepicker 动态控制时分秒 当前时间以后可选
- 基因组代谢网络(GEMS)与全基因组模型从入门到实践系列-----(1)模型构建环境的布置
- 2021-07-27-
- python求和函数1-n_python 用for循环实现1~n求和的实例
- vue uniapp 折叠功能实现
- 奥塔在线:在win10下安装Mysql
- 【coarse-to-fine:基于频谱和空间损失约束】
- 畅玩7X会用上鸿蒙系统吗,荣耀畅玩7X怎么样?值不值得买看完你就知道了
- 对“芝诺悖论”的思考
- TCP多线程实现文件上传
- Nvidia GPU虚拟化性能测试
热门文章
- ping 丢包 网络摄像头_FIFA21 新加入网络连接监测功能
- java颠倒字符串_Java经典实例:按字符颠倒字符串
- fancyupload java_javascript-如何在内部Windows身份验证Intranet上...
- pushpop指令的操作数必须是字操作数_MCS-51单片机指令系统(1)
- 使用Golang搭建web服务
- 「一入 Java 深似海 」系列课程
- 20181213-python1119作业郭恩赐
- 轻松学SQL Server数据库pdf
- ffmpeg rtmp 推流错误WriteN, RTMP send error 10053 10038
- Python筛选法(算出十亿之内所有的质数之和)