Bytom交易说明(UTXO用户自己管理模式)
比原项目仓库:
Github地址:https://github.com/Bytom/bytom
Gitee地址:https://gitee.com/BytomBlockchain/bytom
该部分主要针对用户自己管理私钥和地址,并通过utxo来构建和发送交易。
注意事项:
以下步骤以及功能改造仅供参考,具体代码实现需要用户根据实际情况进行调试,具体可以参考单元测试案例代码blockchain/txbuilder/txbuilder_test.go#L255
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 func
type 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 txinput
func 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 struct
func 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 template
func 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 witness
func 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的功能即可

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
威胁情报| DockerKiller:首个针对Docker的批量攻击与利用实例
随着微服务的热度不断上升,越来越多的企业选择容器来部署自己的应用。而Docker作为实现微服务首选容器,在大规模部署的同时其安全性却没有引起足够的重视。 近期阿里云安全团队发现首个针对Docker批量攻击与利用实例,攻击者对Docker攻击后利用IRC后门、webshell多种手段实现持久化,在主机上执行挖矿、DDoS等恶意行为。随着攻防对抗成本的逐步增加,未来此类攻击利用行为可能会越来越直接,其利用套现方式也会变得多重。建议企业加强对其边缘应用的管理,防范因不当配置而导致的威胁风险。 Docker是一个开源的应用容器引擎,允许开发者将其应用和依赖包打包到一个可移植的容器中,并发布到任何流行的Linux机器上,以实现虚拟化。由于有非常好的移植性,Docker被广泛应用到简化配置、快速部署、多租户环境中,并逐步使用到生产环境中,且广泛部
-
下一篇
开发者论坛一周精粹(第五十五期) 全站HTTPS之OSS教程 一次可以备案几个网站?
开发者论坛每周选取精华内容总结,精选论坛优质贴,每周更新一期,方便大家阅读! 本期是两周合一,更多的干货给你分享。全线HTTPS 阿里云OSS一键签发绑定免费SSL证书图文教程 51干警网摘要:阿里云OSS自定义域名也能一键申请SSL证书了?如何一键签发了?教程>>https://bbs.aliyun.com/read/586871.html 七夕送你最特别的礼物 限时竞拍咯~ 泡椒肥喵摘要:七夕来临之际,为表达我们对大家浓浓的爱意,特准备精美礼品奉上,准备好你的云币了吗?回顾>>https://bbs.aliyun.com/read/586775.html 连续四天!2018杭州·云栖大会你可以... 泡椒肥喵摘要:9月19日~9月22日杭城6万人大Party即将开启!提前看>>https://bbs.aliyun.com/read/586854.html 计算机专业 就业OR考研? 李沃晟摘要:校招和考研同时来临,作为计算机专业的你是选择就业还是考研呢?讨论>>https://bbs.aliyun.com/read/586774.ht...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- MySQL数据库在高并发下的优化方案
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题