千家信息网

Bytom的UTXO用户管理模式怎么创建

发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,这篇文章主要讲解了"Bytom的UTXO用户管理模式怎么创建",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Bytom的UTXO用户管理模式怎么创建"吧
千家信息网最后更新 2025年02月23日Bytom的UTXO用户管理模式怎么创建

这篇文章主要讲解了"Bytom的UTXO用户管理模式怎么创建",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Bytom的UTXO用户管理模式怎么创建"吧!

1.创建私钥和公钥

该部分功能可以参考代码crypto/ed25519/chainkd/util.go#L11,可以通过 NewXKeys(nil) 创建主私钥和主公钥

func NewXKeys(r io.Reader) (xprv XPrv, xpub XPub, err error) {        xprv, err = NewXPrv(r)        if err != nil {                return        }        return xprv, xprv.XPub(), nil}

2.根据公钥创建接收对象

接收对象包含两种形式:address形式和program形式,两者是一一对应的,任选其一即可。其中创建单签地址参考代码account/accounts.go#L267进行相应改造为:

func (m *Manager) createP2PKH(xpub chainkd.XPub) (*CtrlProgram, error) {        pubKey := xpub.PublicKey()        pubHash := crypto.Ripemd160(pubKey)        // TODO: pass different params due to config        address, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)        if err != nil {                return nil, err        }        control, err := vmutil.P2WPKHProgram([]byte(pubHash))        if err != nil {                return nil, err        }        return &CtrlProgram{                Address:        address.EncodeAddress(),                ControlProgram: control,        }, nil}

创建多签地址参考代码account/accounts.go#L294进行相应改造为:

func (m *Manager) createP2SH(xpubs []chainkd.XPub) (*CtrlProgram, error) {        derivedPKs := chainkd.XPubKeys(xpubs)        signScript, err := vmutil.P2SPMultiSigProgram(derivedPKs, len(derivedPKs))        if err != nil {                return nil, err        }        scriptHash := crypto.Sha256(signScript)        // TODO: pass different params due to config        address, err := common.NewAddressWitnessScriptHash(scriptHash, &consensus.ActiveNetParams)        if err != nil {                return nil, err        }        control, err := vmutil.P2WSHProgram(scriptHash)        if err != nil {                return nil, err        }        return &CtrlProgram{                Address:        address.EncodeAddress(),                ControlProgram: control,        }, nil}

3.找到可花费的utxo

找到可花费的utxo,其实就是找到接收地址或接收program是你自己的unspend_output。其中utxo的结构为:(参考代码account/reserve.go#L39)

// UTXO describes an individual account utxo.type UTXO struct {        OutputID bc.Hash        SourceID bc.Hash        // Avoiding AssetAmount here so that new(utxo) doesn't produce an        // AssetAmount with a nil AssetId.        AssetID bc.AssetID        Amount  uint64        SourcePos      uint64        ControlProgram []byte        AccountID           string        Address             string        ControlProgramIndex uint64        ValidHeight         uint64        Change              bool}

涉及utxo构造交易的相关字段说明如下:

  • SourceID 前一笔关联交易的mux_id, 根据该ID可以定位到前一笔交易的output

  • AssetID utxo的资产ID

  • Amount utxo的资产数目

  • SourcePos 该utxo在前一笔交易的output的位置

  • ControlProgram utxo的接收program

  • Address utxo的接收地址

上述这些utxo的字段信息可以从get-block接口返回结果的transaction中找到,其相关的结构体如下:(参考代码api/block_retrieve.go#L26)

// BlockTx is the tx struct for getBlock functype BlockTx struct {        ID         bc.Hash                  `json:"id"`        Version    uint64                   `json:"version"`        Size       uint64                   `json:"size"`        TimeRange  uint64                   `json:"time_range"`        Inputs     []*query.AnnotatedInput  `json:"inputs"`        Outputs    []*query.AnnotatedOutput `json:"outputs"`        StatusFail bool                     `json:"status_fail"`        MuxID      bc.Hash                  `json:"mux_id"`}//AnnotatedOutput means an annotated transaction output.type AnnotatedOutput struct {        Type            string             `json:"type"`        OutputID        bc.Hash            `json:"id"`        TransactionID   *bc.Hash           `json:"transaction_id,omitempty"`        Position        int                `json:"position"`        AssetID         bc.AssetID         `json:"asset_id"`        AssetAlias      string             `json:"asset_alias,omitempty"`        AssetDefinition *json.RawMessage   `json:"asset_definition,omitempty"`        Amount          uint64             `json:"amount"`        AccountID       string             `json:"account_id,omitempty"`        AccountAlias    string             `json:"account_alias,omitempty"`        ControlProgram  chainjson.HexBytes `json:"control_program"`        Address         string             `json:"address,omitempty"`}

utxo跟get-block返回结果的字段对应关系如下:

`SourceID`       - `json:"mux_id"``AssetID`        - `json:"asset_id"``Amount`         - `json:"amount"``SourcePos`      - `json:"position"``ControlProgram` - `json:"control_program"``Address`        - `json:"address,omitempty"`

4.通过utxo构造交易

通过utxo构造交易就是使用spend_account_unspent_output的方式来花费指定的utxo。

第一步,通过utxo构造交易输入TxInput和签名需要的数据信息SigningInstruction,该部分功能可以参考代码account/builder.go#L169进行相应改造为:

// UtxoToInputs convert an utxo to the txinputfunc UtxoToInputs(xpubs []chainkd.XPub, u *UTXO) (*types.TxInput, *txbuilder.SigningInstruction, error) {        txInput := types.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)        sigInst := &txbuilder.SigningInstruction{}        if u.Address == "" {                return txInput, sigInst, nil        }        address, err := common.DecodeAddress(u.Address, &consensus.ActiveNetParams)        if err != nil {                return nil, nil, err        }        switch address.(type) {        case *common.AddressWitnessPubKeyHash:                derivedPK := xpubs[0].PublicKey()                sigInst.WitnessComponents = append(sigInst.WitnessComponents, txbuilder.DataWitness([]byte(derivedPK)))        case *common.AddressWitnessScriptHash:                derivedPKs := chainkd.XPubKeys(xpubs)                script, err := vmutil.P2SPMultiSigProgram(derivedPKs, len(derivedPKs))                if err != nil {                        return nil, nil, err                }                sigInst.WitnessComponents = append(sigInst.WitnessComponents, txbuilder.DataWitness(script))        default:                return nil, nil, errors.New("unsupport address type")        }        return txInput, sigInst, nil}

第二步,通过utxo构造交易输出TxOutput 该部分功能可以参考代码protocol/bc/types/txoutput.go#L20:

// NewTxOutput create a new output structfunc NewTxOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *TxOutput {        return &TxOutput{                AssetVersion: 1,                OutputCommitment: OutputCommitment{                        AssetAmount: bc.AssetAmount{                                AssetId: &assetID,                                Amount:  amount,                        },                        VMVersion:      1,                        ControlProgram: controlProgram,                },        }}

5.组合交易的input和output构成交易模板

通过上面已经生成的交易信息构造交易txbuilder.Template,该部分功能可以参考blockchain/txbuilder/builder.go#L92进行改造为:

type InputAndSigInst struct {        input *types.TxInput        sigInst *SigningInstruction}// Build build transactions with templatefunc BuildTx(inputs []InputAndSigInst, outputs []*types.TxOutput) (*Template, *types.TxData, error) {        tpl := &Template{}        tx := &types.TxData{}        // Add all the built outputs.        tx.Outputs = append(tx.Outputs, outputs...)        // Add all the built inputs and their corresponding signing instructions.        for _, in := range inputs {                // Empty signature arrays should be serialized as empty arrays, not null.                in.sigInst.Position = uint32(len(inputs))                if in.sigInst.WitnessComponents == nil {                        in.sigInst.WitnessComponents = []witnessComponent{}                }                tpl.SigningInstructions = append(tpl.SigningInstructions, in.sigInst)                tx.Inputs = append(tx.Inputs, in.input)        }        tpl.Transaction = types.NewTx(*tx)        return tpl, tx, nil}

6.对构造的交易进行签名

账户模型是根据密码找到对应的私钥对交易进行签名,这里用户可以直接使用私钥对交易进行签名,可以参考签名代码blockchain/txbuilder/txbuilder.go#L82进行改造为:(以下改造仅支持单签交易,多签交易用户可以参照该示例进行改造)

// Sign will try to sign all the witnessfunc Sign(tpl *Template, xprv chainkd.XPrv) error {        for i, sigInst := range tpl.SigningInstructions {                h := tpl.Hash(uint32(i)).Byte32()                sig := xprv.Sign(h[:])                rawTxSig := &RawTxSigWitness{                        Quorum: 1,                        Sigs:   []json.HexBytes{sig},                }                sigInst.WitnessComponents = append([]witnessComponent(rawTxSig), sigInst.WitnessComponents...)        }        return materializeWitnesses(tpl)}

7.提交交易上链

该步骤无需更改任何内容,直接参照wiki中提交交易的APIsubmit-transaction的功能即可

感谢各位的阅读,以上就是"Bytom的UTXO用户管理模式怎么创建"的内容了,经过本文的学习后,相信大家对Bytom的UTXO用户管理模式怎么创建这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

交易 参考 代码 改造 用户 功能 模式 管理模式 管理 地址 部分 信息 公钥 内容 字段 就是 形式 学习 对象 结构 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 演化模式是软件开发模式吗 网络安全与信息化杂志官网 蓝凌软件开发能力 军事电子网络安全概念股 湖南hp服务器续保维护 数据库中的库存分析 网络安全有哪些理论 服务器显示的字体怎么调整 软件开发第一年工作年终总结 大话西游2哪个服务器贫民好混队 广州erp软件开发机构 网络技术与安全专业有什么区别 浪潮服务器设置启动raid 电脑无法连接域名服务器dns 不履行网络安全法定义务 数据库高级和安卓移动开发技术 辽宁gps卫星授时服务器 渝汇软件开发公司 福州康乐网络技术有限公司 病毒可以入侵服务器吗 网络安全包含哪些产品内容 软件开发大学毕业职称 温州嵌入式软件开发费用 fuchsia+软件开发 申万宏源证券软件开发 推荐我的世界切糕战争服务器 浙江java软件开发项目 软件开发估计活动流程 网络安全是个大问题 三级数据库技术报名条件
0