当我们基于比原做应用的时候,在构建交易过程中会遇到以下两种情况。多个地址向一个地址转账,还有一种就是从一个地址分批次向多个地址转账。那我们今天就来介绍一下这两种交易构建的具体流程,以及贴出具体实现的代码。

链式交易

当我们从多个钱包地址一次性转到一个地址的时候,为了提高用户体验。我们可以选择链式交易,把多笔交易一次性打包。那我们下面就来看一下链式交易的流程。

接下来我们来看一下build-transaction接口的代码实现过程,代码如下:

// POST /build-chain-transactions
func (a *API) buildChainTxs(ctx context.Context, buildReqs *BuildRequest) Response {//验证请求idsubctx := 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_accountif action.ActionType() == "spend_account" {//构建花费的输入输出类型组合并且自动合并UTXOtpls, 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"`  //账户idUseUnconfirmed bool   `json:"use_unconfirmed"`  //是否未确认
}

方法如下:

// MergeSpendAction merge common assetID and accountID spend action
func MergeSpendAction(actions []txbuilder.Action) []txbuilder.Action {//声明变量,mapresultActions := []txbuilder.Action{}spendActionMap := make(map[string]*spendAction)//遍历交易的输入输出类型组合for _, act := range actions {switch act := act.(type) {case *spendAction://actionKey字符串拼接actionKey := act.AssetId.String() + act.AccountID//遍历spendActionMapif tmpAct, ok := spendActionMap[actionKey]; ok {tmpAct.Amount += act.AmounttmpAct.UseUnconfirmed = tmpAct.UseUnconfirmed || act.UseUnconfirmed} else {spendActionMap[actionKey] = actresultActions = append(resultActions, act)}default:resultActions = append(resultActions, act)}}return resultActions
}

上面只是简单的贴出了核心的实现代码,如果感兴趣想仔细阅读源码,点击地址:https://git.io/fhAsw

这一期的内容我们到此就结束了,如果你感兴趣可以加入我们的社区一起讨论。如果在阅读的过程中有什么疑问可以在下方给我们留言,我们将第一时间为你解答。

转载于:https://www.cnblogs.com/bytom/p/10457914.html

Bytom的链式交易和花费未确认的交易相关推荐

  1. MySQL中间件之ProxySQL(11):链式规则( flagIN 和 flagOUT )

    返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.html 1.理解链式规则 在mysql_query_rules表中,有两个特殊 ...

  2. 区块链:对链式结构型 PoS 系统的 “虚假权益” 攻击

    编者注:本文为 Decentralized Systems Lab 发表的讨论使用最长链规则的 PoS 系统安全性的文章.按照某种划分方法,PoS 系统可以分为链式结构型(chain-based)和拜 ...

  3. 对链式结构型 PoS 系统的 “虚假权益” 攻击

    编者注:本文为 Decentralized Systems Lab 发表的讨论使用最长链规则的 PoS 系统安全性的文章.按照某种划分方法,PoS 系统可以分为链式结构型(chain-based)和拜 ...

  4. UTXO:未使用的交易输出

    在比特币系统上其实并不存在"账户",而只有"地址".只要你愿意,你就可以在比特币区块链上开设无限多个钱包地址,你拥有的比特币数量是你所有的钱包地址中比特币的总和 ...

  5. 理解区块链之“链式结构”

    区块链有两个明显特点,一个是区块,另一个就是"链",即"链式结构".在"链式结构"下,它衍生出:链/Chain.链上/On-chain.链下 ...

  6. 数据结构-线性表的链式存储(包含代码实现)

    线性表的链式表示和实现 链式存储结构 结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻 线性表的链式存储结构又称为非顺序映像或链式映像. 用一组物理位置任意的存储单元来存放线性表 ...

  7. 数据结构和算法:(3)3.2线性表的链式存储结构

    线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素也就是说你这个可以放在A地点,这个可以放在E地点,A地点和E地点中间可以隔开一个C地点和D地点,这样是允许的),这组存储单元可以存在 ...

  8. 链表list(链式存储结构实现)_5 线性表的链式存储结构

    系列文章参考资料为<大话数据结构>,源码为个人私有,未经允许不得转载 线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,可以使连续的,也可以不连续,也就意味这些元素可以 ...

  9. BP算法双向传_链式求导最缠绵(深度学习入门系列之八)

    摘要: 说到BP(Back Propagation)算法,人们通常强调的是反向传播,其实它是一个双向算法:正向传播输入信号,反向传播误差信息.接下来,你将看到的,可能是史上最为通俗易懂的BP图文讲解, ...

最新文章

  1. 清华大学大数据研究中心“RONG”奖学金申请通知
  2. 《RPA、AI、.NET Core 与未来》-中国.NET开发者峰会
  3. Luogu 4514 上帝造题的七分钟
  4. word java api,是否有可以创建丰富Word文档的Java API?
  5. 按钮开关java代码,Android自定义实现开关按钮代码
  6. 高性能服务器模型分类
  7. python服务端编程_python网络编程示例(客户端与服务端)
  8. 推荐模型之:跨会话信息感知的推荐模型探索与实践
  9. c 语言重载参数类型不同重载和,C/C++函数重载与缺省参数
  10. android开发我的新浪微博客户端-载入页面UI篇(1.1)
  11. 2018年4月28日笔记
  12. 圣经闪卡 - Holy Bible Flash Cards
  13. 数字集成电路_5.延时
  14. vant 个人中心头像修改
  15. Android icon图标网站
  16. RTKLIB源码之单点定位/相对定位后处理简化版—第一版
  17. 系统提速,Windows Ready Boost,使用闪存设备提高性能
  18. 汽车操作系统的前世今生
  19. android自定义锁屏界面设置,android 锁屏壁纸和桌面壁纸的设置实现
  20. JS—— 常用图片后缀正则校验

热门文章

  1. 带有.NET Core App的Identity Server 4
  2. Vue学习笔记(一)—— 常用特性
  3. 使用实体框架核心创建简单的审计跟踪
  4. 微软 Edge 浏览器加入对 ARM64 的原生支持
  5. .NET Framework 4.8 的 Microsoft 更新目录更新
  6. GitHub 回应突然断供:身不由己,无权提前通知预警
  7. 抗锯齿_电竞屏+AI抗锯齿,雷神911 Pro游戏本给你更好游戏体验
  8. VUE 2 无法监听数组和对象的某些变化
  9. coreldraw凹槽_CorelDRAW教程 打造逼真静物写生油画
  10. 关于ionic打包出错:ionic Unable to start the daemon process