溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Bytom的UTXO用戶管理模式怎么創(chuàng)建

發(fā)布時(shí)間:2021-12-20 17:46:05 來源:億速云 閱讀:125 作者:iii 欄目:互聯(lián)網(wǎng)科技

這篇文章主要講解了“Bytom的UTXO用戶管理模式怎么創(chuàng)建”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Bytom的UTXO用戶管理模式怎么創(chuàng)建”吧!

1.創(chuàng)建私鑰和公鑰

該部分功能可以參考代碼crypto/ed25519/chainkd/util.go#L11,可以通過 NewXKeys(nil) 創(chuàng)建主私鑰和主公鑰

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.根據(jù)公鑰創(chuàng)建接收對象

接收對象包含兩種形式:address形式和program形式,兩者是一一對應(yīng)的,任選其一即可。其中創(chuàng)建單簽地址參考代碼account/accounts.go#L267進(jìn)行相應(yīng)改造為:

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
}

創(chuàng)建多簽地址參考代碼account/accounts.go#L294進(jìn)行相應(yīng)改造為:

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.找到可花費(fèi)的utxo

找到可花費(fèi)的utxo,其實(shí)就是找到接收地址或接收program是你自己的unspend_output。其中utxo的結(jié)構(gòu)為:(參考代碼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構(gòu)造交易的相關(guān)字段說明如下:

  • SourceID 前一筆關(guān)聯(lián)交易的mux_id, 根據(jù)該ID可以定位到前一筆交易的output

  • AssetID utxo的資產(chǎn)ID

  • Amount utxo的資產(chǎn)數(shù)目

  • SourcePos 該utxo在前一筆交易的output的位置

  • ControlProgram utxo的接收program

  • Address utxo的接收地址

上述這些utxo的字段信息可以從get-block接口返回結(jié)果的transaction中找到,其相關(guān)的結(jié)構(gòu)體如下:(參考代碼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返回結(jié)果的字段對應(yīng)關(guān)系如下:

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

4.通過utxo構(gòu)造交易

通過utxo構(gòu)造交易就是使用spend_account_unspent_output的方式來花費(fèi)指定的utxo。

第一步,通過utxo構(gòu)造交易輸入TxInput和簽名需要的數(shù)據(jù)信息SigningInstruction,該部分功能可以參考代碼account/builder.go#L169進(jìn)行相應(yīng)改造為:

// 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構(gòu)造交易輸出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構(gòu)成交易模板

通過上面已經(jīng)生成的交易信息構(gòu)造交易txbuilder.Template,該部分功能可以參考blockchain/txbuilder/builder.go#L92進(jìn)行改造為:

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.對構(gòu)造的交易進(jìn)行簽名

賬戶模型是根據(jù)密碼找到對應(yīng)的私鑰對交易進(jìn)行簽名,這里用戶可以直接使用私鑰對交易進(jìn)行簽名,可以參考簽名代碼blockchain/txbuilder/txbuilder.go#L82進(jìn)行改造為:(以下改造僅支持單簽交易,多簽交易用戶可以參照該示例進(jìn)行改造)

// 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.提交交易上鏈

該步驟無需更改任何內(nèi)容,直接參照wiki中提交交易的APIsubmit-transaction的功能即可

感謝各位的閱讀,以上就是“Bytom的UTXO用戶管理模式怎么創(chuàng)建”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Bytom的UTXO用戶管理模式怎么創(chuàng)建這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI