Bytom的链式交易和花费未确认的交易
当我们基于比原做应用的时候,在构建交易过程中会遇到以下两种情况。多个地址向一个地址转账,还有一种就是从一个地址分批次向多个地址转账。那我们今天就来介绍一下这两种交易构建的具体流程,以及贴出具体实现的代码。
链式交易
当我们从多个钱包地址一次性转到一个地址的时候,为了提高用户体验。我们可以选择链式交易,把多笔交易一次性打包。那我们下面就来看一下链式交易的流程。
接下来我们来看一下build-transaction接口的代码实现过程,代码如下:
// POST /build-chain-transactions
func (a *API) buildChainTxs(ctx context.Context, buildReqs *BuildRequest) Response {
//验证请求id
subctx := reqid.NewSubContext(ctx, reqid.New())
//构建交易,方法的具体过程在下面
tmpls, err := a.buildTxs(subctx, buildReqs)
if err != nil {
return NewErrorResponse(err)
}
return NewSuccessResponse(tmpls)
}
核心的实现方法,buildTxs方法的实现如下:
func (a *API) buildTxs(ctx context.Context, req *BuildRequest) ([]*txbuilder.Template, error) {
//验证参数的合法性
if err := a.checkRequestValidity(ctx, req); err != nil {
return nil, err
}
//合并处理交易输入输出的类型组合
actions, err := a.mergeSpendActions(req)
if err != nil {
return nil, err
}
//构建一笔新的交易模板
builder := txbuilder.NewBuilder(time.Now().Add(req.TTL.Duration))
//声明交易模板
tpls := []*txbuilder.Template{}
//遍历交易的输入输出类型组合
for _, action := range actions {
//类型组合的输入为apend_account
if action.ActionType() == "spend_account" {
//构建花费的输入输出类型组合并且自动合并UTXO
tpls, err = account.SpendAccountChain(ctx, builder, action)
} else {
//构建交易输入输出类型组合
err = action.Build(ctx, builder)
}
if err != nil {
//回滚
builder.Rollback()
return nil, err
}
}
//构建交易
tpl, _, err := builder.Build()
if err != nil {
//回滚
builder.Rollback()
return nil, err
}
tpls = append(tpls, tpl)
return tpls, nil
}
build方法的实现过程:
// Build build transactions with template
func (b *TemplateBuilder) Build() (*Template, *types.TxData, error) {
// Run any building callbacks.
for _, cb := range b.callbacks {
err := cb()
if err != nil {
return nil, nil, err
}
}
tpl := &Template{}
tx := b.base
if tx == nil {
tx = &types.TxData{
Version: 1,
}
}
if b.timeRange != 0 {
tx.TimeRange = b.timeRange
}
// Add all the built outputs.
tx.Outputs = append(tx.Outputs, b.outputs...)
// Add all the built inputs and their corresponding signing instructions.
for i, in := range b.inputs {
instruction := b.signingInstructions[i]
instruction.Position = uint32(len(tx.Inputs))
// Empty signature arrays should be serialized as empty arrays, not null.
if instruction.WitnessComponents == nil {
instruction.WitnessComponents = []witnessComponent{}
}
tpl.SigningInstructions = append(tpl.SigningInstructions, instruction)
tx.Inputs = append(tx.Inputs, in)
}
tpl.Transaction = types.NewTx(*tx)
tpl.Fee = CalculateTxFee(tpl.Transaction)
return tpl, tx, nil
}
到此,我们的链式交易的代码到此就讲解到这儿。如果感兴趣想仔细阅读源码,点击源码地址:https://git.io/fhAsr
花费未确认的交易
下面我们来介绍一下花费未确认的交易,我们首先介绍一下什么是花费未确认的交易。我们知道UTXO模型在交易的过程中,如果交易未打包确认。再进行第二笔转账就会存在“双花”问题,就不能再发起交易或者需要等一段时间才能再发起一笔交易。如果使用花费未确认的交易就可以避免这个问题。
那么花费未确认的交易实现机制是什么样的呢?我们在创建第一笔交易的时候,会找零,此时交易是未确认的状态。找零存在交易池中,我们发第二笔交易的时候就直接使用在交易池中找零地址里面的资产。
那我们来看一下花费未确认交易的代码实现过程,花费过程结构体如下:
type spendAction struct {
accounts *Manager //存储账户及其相关的控制程序参数
bc.AssetAmount //资产id和资产数量的结构体
AccountID string `json:"account_id"` //账户id
UseUnconfirmed bool `json:"use_unconfirmed"` //是否未确认
}
方法如下:
// MergeSpendAction merge common assetID and accountID spend action
func MergeSpendAction(actions []txbuilder.Action) []txbuilder.Action {
//声明变量,map
resultActions := []txbuilder.Action{}
spendActionMap := make(map[string]*spendAction)
//遍历交易的输入输出类型组合
for _, act := range actions {
switch act := act.(type) {
case *spendAction:
//actionKey字符串拼接
actionKey := act.AssetId.String() + act.AccountID
//遍历spendActionMap
if tmpAct, ok := spendActionMap[actionKey]; ok {
tmpAct.Amount += act.Amount
tmpAct.UseUnconfirmed = tmpAct.UseUnconfirmed || act.UseUnconfirmed
} else {
spendActionMap[actionKey] = act
resultActions = append(resultActions, act)
}
default:
resultActions = append(resultActions, act)
}
}
return resultActions
}
上面只是简单的贴出了核心的实现代码,如果感兴趣想仔细阅读源码,点击地址:https://git.io/fhAsw
这一期的内容我们到此就结束了,如果你感兴趣可以加入我们的社区一起讨论。如果在阅读的过程中有什么疑问可以在下方给我们留言,我们将第一时间为你解答。
Bytom的链式交易和花费未确认的交易的更多相关文章
- MySQL中间件之ProxySQL(11):链式规则( flagIN 和 flagOUT )
返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.html 1.理解链式规则 在mysql_query_rules表中,有两个特殊 ...
- ProxySQL(11):链式规则( flagIN 和 flagOUT )
文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9350631.html 理解链式规则 在mysql_query_rules表中,有两个特殊字段"fl ...
- 04.UTXO:未使用的交易输出,比特币核心概念之一
在比特币系统上其实并不存在“账户”,而只有“地址”.只要你愿意,你就可以在比特币区块链上开设无限多个钱包地址,你拥有的比特币数量是你所有的钱包地址中比特币的总和.比特币系统并不会帮你把这些地址汇总起来 ...
- 由表单验证说起,关于在C#中尝试链式编程的实践
在web开发中必不可少的会遇到表单验证的问题,为避免数据在写入到数据库时出现异常,一般比较安全的做法是前端会先做一次验证,通过后把数据提交到后端再验证一次,因为仅仅靠前端验证是不安全的,有太多的htt ...
- jQuery插件编写及链式编程模型小结
JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效.大多数情况下,我们都是使用别人开发的JQuery插件,今天我们就来看看如何把我们常用的功能做出JQu ...
- jQuery链式操作[转]
用过jQuery的朋友都知道他强大的链式操作,方便,简洁,易于理解,如下 $("has_children").click(function(){ $(this).addClass( ...
- Objective-C 链式语法的实现
对于 Objective-C 的语法,喜欢的人会觉得它是如此的优雅,代码可读性强,接近自然语言,开发者在调用大多数方法时不需要去查看注释或文档,通常只凭借方法名就可以大致知道这个方法的作用,可以理解为 ...
- jQuery的XX如何实现?——2.show与链式调用
往期回顾: jQuery的XX如何实现?——1.框架 -------------------------- 源码链接:内附实例代码 jQuery使用许久了,但是有一些API的实现实在想不通.于是抽空看 ...
- 数据结构Java实现05----栈:顺序栈和链式堆栈
一.堆栈的基本概念: 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ...
随机推荐
- mysql8.0.13免安装版的安装配置详解
一.下载 下载地址:https://dev.mysql.com/downloads/mysql/ 二.解压到某个目录,例如:D:/mysql/mysql-8.0.13-winx64 三.配置环境变量 ...
- 配置notepad++支持golang开发
1 下载golang安装包和配置环境变量 到官网下载golang安装包,下载地址:https://golang.org/dl/,我选择的go1.7.windows-amd64.zip. 配置环境变量: ...
- 怎么eclipse或MyEclipse中添加javaSe的源码
怎么eclipse或MyEclipse中添加javaSe的源码 有时在eclipse里我们调用java提供给我们的方法,我们有时需要查看java提供给我们的调用方法的源码或java提供给我们的核心类的 ...
- ios APNS注册失败 本地push
- (void)addLocalNotice:(NSString *)titlepush { if (@available(iOS 10.0, *)) { UNUserNotificationCent ...
- 2000w数据,redis中只存放20w的数据,如何保证redis中的数据都是热点数据
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略. redis 提供 6种数据淘汰策略:voltile-lru:从已设置过期时间的数据集(server.db[i].expires) ...
- Xamarin.Forms 开发资源集合
收集整理了下 Xamarin.Forms 的学习参考资料,分享给大家,稍后会不断补充: UI样式 Snppts: Xamarin Forms UI Snippets. Prebuilt Templat ...
- java多线程探究
本文主要是一些线程理论性的知识,随后将贴出研究的源码,包含线程池,锁,线程组等简单的demo,欢迎大家下载1.进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程 ...
- git stash pop 冲突,git stash list 中的记录不会自动删除的解决方法
在使用git stash代码时,经常会碰到有冲突的情况,一旦出现冲突的话,系统会认为你的stash没有结束. 导致的结果是git stash list 中的列表依然存在,实际上代码已经pop出来了. ...
- day19 python之re模块正则练习
1.匹配标签 import re ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>" ...
- 【论文速读】Yuliang Liu_2017_Detecting Curve Text in the Wild_New Dataset and New Solution
Yuliang Liu_2017_Detecting Curve Text in the Wild_New Dataset and New Solution 作者和代码 caffe版代码 关键词 文字 ...