图解以太坊交易

    更多关于区块链技术和投资的文章,请关注微信公众号“币梭”

https://mp.weixin.qq.com/s/xs14qDrSVb24Ifm_ei6FQg

    以太坊的交易主要是指一条外部账户把经过签名的数据包发送给区块链上另一账户,这个数据包包含发送者的签名、接收者的地址以及发送者转移给接收者的以太币数量等内容。以太坊上的每一笔交易都需要支付一定的费用,用于支付交易执行所需要的计算开销。计算开销的费用并不是以太币直接计算的,而是引入Gas作为执行开销的基本单位,通过Gas Price与以太币进行换算。

交易费用

    为了防止用户在区块链公有链中发送太多无意义交易,浪费矿工的计算资源,例如转账金额为0的转账交易,所以以太坊采用了交易收费的策略,要求交易的发送方为交易付出一定的代价。具体 来说,对于每一笔交易,交易的发送者都需要付出一定的交易费;这笔费用最终由将这个交易打包进主链的矿工收取。

    由于比特币中只存在转账交易,每笔交易所需的计算开销大体一致,因此每笔交易的发送者会以比特币的形式,付出固定的手续费。而以太坊引入了智能合约,涉及智能创建和调用的交易所消耗的计算差别巨大,因此引入相对复杂的Gas、Gas Price对交易所需的手续费进行定价。

1、Gas

    Gas是用来衡量一笔交易所消耗的计算资源的基本单位。以太坊的交易可能涉及很多计算步骤,图1常见操作的需要消耗的Gas。当交易所需计算步骤越多,越复杂,那么这笔交易消耗的Gas越多。一笔普通的转账交易会消耗21000Gas,而一个创建智能合约的交易可能会消耗几万,甚至几百万Gas。

 

2、Gas Price

    Gas Price是一单位Gas所需的手续费(以太币),目前以太坊钱包客户端默认的Gas Price是0.000000001 Ether/Gas(1Gwei)。也就说,如果一个交易需要消耗21000Gas,那么这笔交易的手续费为0.000021Ether。

    Gas Price不是固定的,可以根据需求自由调动。一般来说,矿工会对接受到的交易按照Gas Price或者按照 Gas * Gas Price从大到小进行排序,以便决定哪个交易先纳入到区块中。当以太坊公有链上某个时段交易量激增的情况下,为了尽早让矿工接受一笔交易,交易发送者可以提高这笔交易的Gas Price,以激励矿工。

3、Gas Limit

    Gas Limit是对Gas的进行限制。

    对于单个交易,Gas Limit 表示交易发送者愿意为这笔交易执行所支付的最大Gas数量。Gas Limit可以保护用户免受代码错误影响以致消耗过多的交易费。另外如果没有Gas Limit限制,那么某些恶意用户可能会发送一个数十亿步骤的交易,并且没有人能够处理他,因为处理这个交易甚至需要花费比出块间隔更长的时间,然而矿工事前并不知道,所以导致拒绝服务式攻击。

    对于区块来说,Gas Limit是单个区块所允许包含的最大Gas总量,这个是由矿工来决定,一般设置Gas Limit越大,那么矿工就可以获取更多的交易费,但是需要更多带宽,同时会加大叔区块出现的频率,造成挖出的区块无法形成最长的交易链。因此矿工也不能任意地更改区块的Gas Limit,根据以太坊协议,当前区块的Gas Limit只能基于上一个区块的Gas Limit上下波动1/1024。

交易内容

    一般一条交易可能包括下面的内容,

  • from:交易发送者的地址

  • to:交易接收者的地址

  • value:发送者要转移给接收者的以太币数量

  • data:数据字段,如果存在,则是表明该交易是一个创建或则调用智能合约交易

  • Gas Limit:表示这个交易允许消耗的最大Gas数量

  • GasPrice:表示发送者愿意支付给矿工的Gas价格

  • nonce:用来区别同一用户发出的不同交易的标记

  • hash:由以上信息生成的散列值(哈希值),作为交易的ID

  • r、s、v:交易签名的三个部分,由发送者的私钥对交易hash进行签名生成。

    按照场景,交易可以分为三种类型

1)转账交易。转账是最简单的一种交易,从一个账户向另一账户发送以太币。

web3.eth.sendTransaction({

    from:

    to:

    value:

})

2)创建智能合约的交易。

web3.eth.sendTransaction({

    from:

    value:

})

    创建合约是指将合约部署在区块链上,这也是通过发送交易来实现的。在创建合约的交易中,“to”字段是一个空字符串,在“data”字段中指定初始化合约的二进制代码,之后合约被调用是,该代码的执行结果将作为合约代码。

3)执行智能合约的交易。

web3.eth.sendTransaction({

from:

to:

value:

})

该交易是为了执行已经部署在区块链上的智能合约,在该交易中,from是合约地址,to是要调用智能合约的地址。

交易过程

    在以太坊中,交易的处理是一个过程,从账户发起交易请求开始,到包含该交易的区块被共识节点同步为止(一般来说,出于安全性考虑,会等到该区块后面再“挖”出一些块,这笔交易才算确定),满足这一个过程才算完成一笔交易。

1、一笔普通的转账或合约调用的交易过程

1)发送交易请求。发送者(用户A)按照格式要求在以太坊网络中发起一个交易请求,该请求被传向用户A的对等节点,如图2所示。

 

2)交易请求验证和广播。网络上的节点(用户B)同步到此交易,检查交易是否有效、格式是否正确。如果符合要求,计算可能的最大交易费用,确定发送方的地址,并在本地的区块链上减去相应的费用,如果账户余额不足,则返回错误,这条交易废弃。对符合要求的交易请求,用户B将其放在交易存储池中,并且转发给其他节点。其他收到交易请求的节点重复用户B的处理过程。如图3所示。

3)记账节点打包交易和执行合约。对于转账交易,获得记账权的节点将该交易和其他交易一起打包到区块中;对于合约交易,矿工将该交易和其他交易一起打包到区块中,并在本地的EVM上运行被调用的合约代码,直到代码运行结束或Gas用完。如果代码并未结束而Gas已经用完,那么代码运行而改变的状态回滚到代码运行之前,但是已经支付的交易费用不可收回,交易费用有获得记账权的矿工获得。如果代码运行结束Gas还有剩余,那么矿工也只会获得消耗Gas x GasPrice作为手续费,不会收取剩余Gas对应的手续费。如图4所示。

4)区块广播。用户B把包含用户A的交易请求的区块发送至对等节点,并在全网传播。如图5所示。

5)区块验证同步。其他节点收到该区块后,验证区块,如果区块通过验证,节点将内存池中原来用户A的交易请求删除,同时同步该区块,将其添加到本地的区块链中。对于区块中的执行智能合约的交易,其他节点会在本地的EVM上运行该智能合约,并互相验证运行的结果。如图6所示。

    通过上面五个步骤,整个交易的过程已经结束。但是一般来说,当包含交易的区块链被同步到区块链后,出于安全性的需求,还需要再挖掘一些块,这笔交易才能算是真正地被确认。

2、一个创建智能合约的交易过程

    注:有些步骤和普通转账的一样,交易的图就不画了

1)发送创建智能合约请求。发送者(用户A)按照一定的格式要求,在以太坊中发起一个创建智能合约的交易请求,如图7所示

2)交易请求验证和广播。网络上的节点(用户B)同步到此交易,检查交易是否有效、格式是否正确。如果符合要求,计算可能的最大交易费用,确定发送方的地址,并在本地的区块链上减去相应的费用,如果账户余额不足,则返回错位,这条交易废弃。对符合要求的交易请求,用户B将其放在交易存储池中,并且转发给其他节点。其他收到交易请求的节点重复用户B的处理过程。

3)打包,创建合约账户,部署合约。获得记账权的节点将该交易和其他交易一起打包到区块中,获得记账权的节点会根据其提供的交易费用和合约代码,创建合约账户,并在账户空间中部署合约。智能合约账户的地址是由发送者的地址(address)和交易随机数(nonce)作为输入,通过加密算法生成的、交易确认后智能合约的地址返回给发送者。如图8所示。

4)区块广播。用户B把包含用户A的交易请求的区块发送至对等节点,并在全网传播

5)验证区块,并部署智能合约到本地。共识节点接收到该区块,验证区块,如果区块通过验证,节点从内存池将原来用户A创建智能合约的交易请求删除掉,同步区块链,并将智能合约部署在各自的本地区块链中。如图9所示。

    经过上面的五步,创建智能合约的交易完成。但是一般来说,当包含交易的区块链被同步到区块链后,出于安全性的需求,还需要再挖掘一些块,这笔交易才能算是真正地被确认。

 

更多区块链技术和投资文章,请关注微信公众号“币梭”

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于backtrader是一个Python开源框架,可以用于量化交易,因此可以通过编程来实现量化交易策略。下面是一个简单的backtrader量化交易案例图解。 假设我们有一些历史股票价格数据,我们想要用backtrader来实现一个简单的均线策略。具体来说,当股票价格上穿均线时,我们会买入股票;当股票价格下穿均线时,我们会卖出股票。 首先,我们需要导入backtrader库: ``` import backtrader as bt ``` 接下来,我们需要定义一个backtrader策略类。在该类中,我们需要定义以下方法: 1. __init__(): 初始化策略。 2. next(): 定义策略的逻辑。 具体代码如下: ``` class MyStrategy(bt.Strategy): def __init__(self): self.sma = bt.indicators.SimpleMovingAverage(self.data.close, period=10) self.order = None def next(self): if self.order: return if not self.position: if self.data.close[0] > self.sma[0]: self.order = self.buy() else: if self.data.close[0] < self.sma[0]: self.order = self.sell() ``` 在__init__()方法中,我们定义了一个简单移动平均指标(SMA),并将其计算在每个数据点上。我们还定义了一个空的订单变量,该变量将在接下来的逻辑中用于检查我们是否已经下了订单。 在next()方法中,我们首先检查我们是否有未完成的订单。如果我们有未完成的订单,我们就返回,等待订单完成后再继续。如果我们没有未完成的订单并且我们没有持仓,我们就检查当前价格是否高于SMA。如果是,我们就下单买入。如果我们已经持有了仓位,我们就检查当前价格是否低于SMA。如果是,我们就下单卖出。 接下来,我们需要加载我们的数据。假设我们有一个名为“data.csv”的文件,其中包含了我们的股票价格数据。我们可以使用以下代码来加载数据: ``` data = bt.feeds.GenericCSVData( dataname='data.csv', fromdate=datetime(2019, 1, 1), todate=datetime(2020, 1, 1), dtformat=('%Y-%m-%d'), open=1, high=2, low=3, close=4, volume=5, openinterest=-1 ) ``` 在这里,我们使用了backtrader的GenericCSVData源,该源允许我们从CSV文件中加载数据。我们还指定了数据的时间范围,以及每个数据点的格式和位置。 接下来,我们需要实例化我们的策略并运行回测。我们可以使用以下代码来完成这个过程: ``` cerebro = bt.Cerebro() cerebro.addstrategy(MyStrategy) cerebro.adddata(data) cerebro.run() ``` 在这里,我们使用backtrader的Cerebro类来实例化我们的交易引擎。我们还向引擎中添加了我们的策略和数据。最后,我们运行回测并输出结果。 总的来说,backtrader是一个非常强大的Python框架,可以用于快速实现量化交易策略。在上面的例子中,我们演示了如何使用backtrader来实现一个简单的均线策略。当然,您可以根据自己的需求和想法来设计和实现不同的量化交易策略。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值