日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

区块链项目 - 9 UTXO优化

發布時間:2024/1/1 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 区块链项目 - 9 UTXO优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

9 UTXO優化

9.1 查找未花費輸出

之前我們要查詢 某個地址的余額需要遍歷整個數據庫,隨著數據量的增大,這個工作量會很大,我們現在來嘗試優化

/Users/xxx/go/src/publicChain/part63-UTXOSet/BLC/UTXO_Set.go

const utxoTableName = "utxoTableName"type UTXOSet struct {Blockchain *Blockchain }func (utxoSet *UTXOSet) ResetUTXOSet() {err := utxoSet.Blockchain.DB.Update(func(tx *bolt.Tx) error {b := tx.Bucket([]byte(utxoTableName))if b != nil {tx.DeleteBucket([]byte(utxoTableName))b, _ := tx.CreateBucket([]byte(utxoTableName))if b != nil {}}return nil})if err != nil {log.Panic(err)} }

/Users/xxx/go/src/publicChain/part62-UTXOSet/BLC/Transaction_TXOutputs.go

type TXOutputs struct {TxOutputs []*TXOutput }

/Users/xxx/go/src/publicChain/part62-UTXOSet/BLC/Blockchain.go

func (blockchain *Blockchain) FindUTXOMap() map[string]*TXOutputs {//define an Iterator variable to attain blockblockchainIterator := blockchain.Iterator()//store all UTXOs have been spentspentableUTXOsMap := make(map[string][]*TXInput)utxoMaps := make(map[string]*TXOutputs)for {//attain blocksblock := blockchainIterator.Next()//range all index of Txs slicefor i := len(block.Txs) - 1; i >= 0; i-- {//attain Txstx := block.Txs[i]//judging if tx is in coinbase and put all txInput into sliceif tx.IsCoinbaseTransaction() == false {for _, txInput := range tx.Vins {//convert []byte to stringtxHash := hex.EncodeToString(txInput.TxHash)spentableUTXOsMap[txHash] = append(spentableUTXOsMap[txHash], txInput)}}//define an instance of &TXOutputstxOutputs := &TXOutputs{[]*TXOutput{}}//convert []byte to stringtxHash := hex.EncodeToString(tx.TxHash)workOutLoop://range if a value has been spentfor index, out := range tx.Vouts {//convert []byte to stringtxHash := hex.EncodeToString(tx.TxHash)//attain []*TXInputtxInputs := spentableUTXOsMap[txHash]//judging and put out into sliceif len(txInputs) > 0 {isSpent := falsefor _, in := range txInputs {outPublicKey := out.Ripemd160HashinPublicKey := in.PublicKeyif bytes.Compare(outPublicKey, Ripemd160Hash(inPublicKey)) == 0 {if index == in.Vouts {isSpent = truecontinue workOutLoop}}}if isSpent == false {txOutputs.TxOutputs = append(txOutputs.TxOutputs, out)}} else {txOutputs.TxOutputs = append(txOutputs.TxOutputs, out)}}//set key-value pairsutxoMaps[txHash] = txOutputs}var hashInt big.InthashInt.SetBytes(block.PreBlockHash)if hashInt.Cmp(big.NewInt(0)) == 0 {break}}return utxoMaps }

相應的命令行工具也改一下,編譯并運行,結果能夠正常輸出

./bc test map[8e578e4d1d1ef2f5101bdd72e5bd922cb8d85956333977e03c4260975db0223c:0xc00000ca50] ./bc send -from '["1Eubsorq2zfZ1vmuA8NRcNxPwptSG6c8BJ"]' -to '["1B5y2naPTzkXLztVk2ffLPd3wbpoQg6723"]' -amount '["2"]' ./bc getBalance -address "1Eubsorq2zfZ1vmuA8NRcNxPwptSG6c8BJ" 1Eubsorq2zfZ1vmuA8NRcNxPwptSG6c8BJ has 18 token ./bc send -from '["1Eubsorq2zfZ1vmuA8NRcNxPwptSG6c8BJ","1B5y2naPTzkXLztVk2ffLPd3wbpoQg6723"]' -to '["1B5y2naPTzkXLztVk2ffLPd3wbpoQg6723","1Eubsorq2zfZ1vmuA8NRcNxPwptSG6c8BJ"]' -amount '["3","4"]'

嘗試進行多筆轉賬會出錯,我們下一節會詳細講解

9.2 多筆交易中的數字簽名

我們完善一下相關函數

func NewSimpleTransaction(from, to string, amount int, blockchain *Blockchain, txs []*Transaction) *Transaction {--//signatureblockchain.SignTransaction(tx, wallet.PrivateKey, txs)return tx } func (blockchain *Blockchain) SignTransaction(tx *Transaction, privateKey ecdsa.PrivateKey, txs []*Transaction) {--for _, vin := range tx.Vins {prevTX, err := blockchain.FindTransaction(vin.TxHash, txs)-- } func (blockchain *Blockchain) FindTransaction(ID []byte, txs []*Transaction) (Transaction, error) {for _, tx := range txs {if bytes.Compare(tx.TxHash, ID) == 0 {return *tx, nil}}bci := blockchain.Iterator()for {block := bci.Next()for _, tx := range block.Txs {if bytes.Compare(tx.TxHash, ID) == 0 {return *tx, nil}}var hashInt big.InthashInt.SetBytes(block.PreBlockHash)if big.NewInt(0).Cmp(&hashInt) == 0 {break}}return Transaction{}, nil }

最后重新編譯運行

./bc send -from '["1Eubsorq2zfZ1vmuA8NRcNxPwptSG6c8BJ"]' -to '["1B5y2naPTzkXLztVk2ffLPd3wbpoQg6723"]' -amount '["2"]' ./bc getBalance -address "1Eubsorq2zfZ1vmuA8NRcNxPwptSG6c8BJ" 1Eubsorq2zfZ1vmuA8NRcNxPwptSG6c8BJ has 29 token ./bc getBalance -address "1B5y2naPTzkXLztVk2ffLPd3wbpoQg6723" 1B5y2naPTzkXLztVk2ffLPd3wbpoQg6723 has 1 token

9.3 遍歷并存儲UXTO

/Users/xxx/go/src/publicChain/part63-UTXOSet/BLC/Transaction_TXOutputs.go

//SerializeBlockfunc (txOutput *TXOutputs) Serialize() []byte {var result bytes.Bufferencoder := gob.NewEncoder(&result)err := encoder.Encode(txOutput)if err != nil {log.Panic(err)}return result.Bytes() }//DeserializeBlockfunc DeserializeTXOutputs(txOutputsBytes []byte) *TXOutputs {var txOutputs TXOutputsdecoder := gob.NewDecoder(bytes.NewReader(txOutputsBytes))err := decoder.Decode(&txOutputs)if err != nil {log.Panic()}return &txOutputs }

/Users/xxx/go/src/publicChain/part63-UTXOSet/BLC/UTXO_Set.go

const utxoTableName = "utxoTableName"type UTXOSet struct {Blockchain *Blockchain }func (utxoSet *UTXOSet) ResetUTXOSet() {err := utxoSet.Blockchain.DB.Update(func(tx *bolt.Tx) error {b := tx.Bucket([]byte(utxoTableName))if b != nil {err := tx.DeleteBucket([]byte(utxoTableName))if err != nil {log.Panic(err)}}b, _ = tx.CreateBucket([]byte(utxoTableName))if b != nil {txOutputMap := utxoSet.Blockchain.FindUTXOMap()for keyHash, outs := range txOutputMap {txHash, _ := hex.DecodeString(keyHash)b.Put(txHash, outs.Serialize())}}return nil})if err != nil {log.Panic(err)} }

在終端中運行,程序能夠正常運行

9.3 FindUTXOMap方法優化

我們直接通過utxoSet來獲取余額

func (cli CLI) getBalance(address string) {fmt.Println("Address:" + address)blockchain := BlockChainObject()defer blockchain.DB.Close()utxoSet := &UTXOSet{blockchain}amount := utxoSet.GetBalance(address)fmt.Printf("%s has %d token\n", address, amount) }

我們再來完善一下需要調用的方法

func (utxoSet *UTXOSet) FindUTXOForAddress(address string) []*UTXO {} func (utxoSet *UTXOSet) GetBalance(address string) int64 {// }

我們再改為下列結構體,其他文件相應的也變更

type TXOutputs struct {UTXOS []*UTXO }

/Users/xxx/go/src/publicChain/part63-UTXOSet/BLC/UTXO_Set.go

func (utxoSet *UTXOSet) GetBalance(address string) int64 {UTXOS := utxoSet.FindUTXOForAddress(address)var amount int64for _, utxo := range UTXOS {amount += utxo.Output.Value}return amount } func (utxoSet *UTXOSet) FindUTXOForAddress(address string) []*UTXO {var utxos []*UTXOutxoSet.Blockchain.DB.View(func(tx *bolt.Tx) error {//assume bucket exists and has keysb := tx.Bucket([]byte(utxoTableName))c := b.Cursor()for k,v := c.First();k != nil; k,v = c.Next() {fmt.Printf("key=%s, value=%s\n",k,v)txOutputs := DeserializeTXOutputs(v)for _,utxo := range txOutputs.UTXOS {if utxo.Output.UnlockScriptPublicKeyWithAddress(address) {utxos = append(utxos,utxo)}}}return nil})return utxos }

在終端中的重新創建區塊并查詢余額,結果能夠正常輸出,現在我們每次查詢余額就不需要遍歷數據庫了

./bc creatBlockChain -address "1JfaJ6AtBCSop8npzv1UBhayhM9AxNnu9N" ./bc getBalance -address "1JfaJ6AtBCSop8npzv1UBhayhM9AxNnu9N" 1JfaJ6AtBCSop8npzv1UBhayhM9AxNnu9N has 10 token

9.4 修改CoinbaseTransaction交易哈希導致的bug

我們修改一下如下代碼,調用ResetUTOXSet方法重置UTOX

func (cli *CLI) testMethod() {//attain blockchainblockchain := BlockChainObject()defer blockchain.DB.Close()//attain utxoSetutxoSet := &UTXOSet{blockchain}//call method utxoSet.ResetUTXOSet() }

? 接著我們在終端中編譯并運行

./bc send -from '["1Dh46KP31Gfkd55wqdmnpqy2TQh1cvwpzY"]' -to '["17pGGPVzFrzvLLoHWJoJ926Eemwm1DJKRN"]' -amount '["2"]'

我們發現在終端轉賬不能正常運行,我們修改一下部分代碼

func (tx *Transaction) HashTransaction() {var result bytes.Bufferencoder := gob.NewEncoder(&result)err := encoder.Encode(tx)if err != nil {log.Panic(err)}resultBytes := bytes.Join([][]byte{IntToHex(time.Now().Unix()), result.Bytes()}, []byte{})hash := sha256.Sum256(resultBytes)tx.TxHash = hash[:] }

改好之后在次編譯重置即可查詢余額

./bc getBalance -address "17pGGPVzFrzvLLoHWJoJ926Eemwm1DJKRN" 17pGGPVzFrzvLLoHWJoJ926Eemwm1DJKRN has 2 token ./bc getBalance -address "1Dh46KP31Gfkd55wqdmnpqy2TQh1cvwpzY" 1Dh46KP31Gfkd55wqdmnpqy2TQh1cvwpzY has 18 token ./bc send -from '["1Dh46KP31Gfkd55wqdmnpqy2TQh1cvwpzY","17pGGPVzFrzvLLoHWJoJ926Eemwm1DJKRN"]' -to '["17pGGPVzFrzvLLoHWJoJ926Eemwm1DJKRN","1Dh46KP31Gfkd55wqdmnpqy2TQh1cvwpzY"]' -amount '["3","4"]' 17pGGPVzFrzvLLoHWJoJ926Eemwm1DJKRN has 1 token 1Dh46KP31Gfkd55wqdmnpqy2TQh1cvwpzY has 29 token

一次性轉多筆也是能夠實現的

總結

以上是生活随笔為你收集整理的区块链项目 - 9 UTXO优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。