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

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

相关文章
|
6月前
|
供应链 算法 安全
LP链上质押合约代币项目系统开发|案例详情|指南方案
在这种情况下,所有的交易和持仓数据都被记录在区块链上,并且参与者可以在实时交易中进行交互,同时保持匿名性和安全性。
|
存储 算法 数据挖掘
量化交易合约交易策略系统部署开发执行源码示例
量化交易合约交易策略系统部署开发执行源码示例
|
安全 API Python
OKEx交易所合约交易系统开发部署源码规则解析
OKEx交易所合约交易系统开发部署源码规则解析
|
6月前
|
安全 区块链
op链/BRC链质押代币项目系统开发步骤详情
智能合约的主要好处之一是它们能够降低交易成本,提高效率
|
6月前
|
区块链
DAPP合约代币博饼交易质押模式系统开发|详情方案|规则明细
智能合约是什么?它是近年来随着区块链技术的发展而崭露头角的一个概念
|
存储 安全 区块链
DAPP钱包OP链合约代币质押系统开发方案与详情
实现智能合约交易所的关键在于如何确保交易的安全性和有效性
swap薄饼交易所上币流程合约逻辑源代码详情
function setTokenSymbol (string memory tokenSymbol) public onlyOwner { _symbol = tokenSymbol;
|
API 数据处理 Python
量化合约交易连接交易所API合约开发Python源码详情
# 获取特定市场的行情数据 symbol = 'BTC/USDT' market = next(m for m in markets if m['symbol'] == symbol) ticker = exchange.fetch_ticker(market) print(ticker)
交易所提供高杠杆合约交易系统开发部署源码规则解析
交易所提供高杠杆合约交易系统开发部署源码规则解析
|
算法 测试技术 区块链
usdt合约交易规则分析|usdt合约交易功能开发部署解析
usdt合约交易规则是由各大交易平台制定和实施的,不同的平台可能会有一些细微的差异。一般来说,以下是一些常见的usdt合约交易规则: