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

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

相关文章
|
3月前
|
安全 区块链
DAPP去中心化质押LP博饼交易系统开发|步骤逻辑|详情模式
智能合约就是一种把我们生活中的合约数字化,当满足一定条件后
|
2月前
|
供应链 算法 安全
LP链上质押合约代币项目系统开发|案例详情|指南方案
在这种情况下,所有的交易和持仓数据都被记录在区块链上,并且参与者可以在实时交易中进行交互,同时保持匿名性和安全性。
|
8月前
|
存储 算法 数据挖掘
量化交易合约交易策略系统部署开发执行源码示例
量化交易合约交易策略系统部署开发执行源码示例
|
7月前
|
安全
TRX链丨BSC链丨ARB链发行代币合约项目DeFi/IDO/DAO/DApp/LP/Swap去中心化交易所兑换底池系统开发实现技术详细规则及案例源码
Private key management and security: To ensure the secure storage and management of private keys, hardware wallets or multi-signature mechanisms can be considered to increase security.
swap薄饼交易所上币流程合约逻辑源代码详情
function setTokenSymbol (string memory tokenSymbol) public onlyOwner { _symbol = tokenSymbol;
|
8月前
|
机器人 API
现货合约交易量化机器人开发设计执行逻辑源码实例分析
现货合约交易量化机器人开发设计执行逻辑源码实例分析
|
9月前
|
存储 安全 区块链
储存比特币的钱包开发源码规则解析
储存比特币的钱包开发源码规则解析
|
9月前
|
人工智能 算法 机器人
现货量化+合约交易+合约跟单系统开发(案例开发)/策略详细/逻辑方案/项目源码
 量化交易需要以大量的数据作为基础,通过对大量数据的分析,来做出理性的判断,预测未来价格的走势,量化交易从狭义上来说就是指程序化的交易,自动下单。从广义上来说,就是指系统性的交易,量化交易可以简单理解为机器人交易,用计算机算法来交易。
|
10月前
|
安全 JavaScript 前端开发
TRON波场链USDT合约开发源码规则部署
TRON波场链USDT合约开发源码规则部署
|
JavaScript Java Go
深入分析以太链/波场链/火币链/币安链LP代币合约流动性质押挖矿分红机制系统开发详细逻辑及源码
 Fabric's smart contract is called chain code, which is divided into system chain code and user chain code. System chain code is used to realize system level functions, and user chain code is used to realize user application functions. The chain code is compiled into an independent application that