GO語(yǔ)言創(chuàng)建錢包并遍歷錢包(wallet)的實(shí)現(xiàn)代碼
基本知識(shí)
公鑰加密算法使用的是成對(duì)的密鑰:公鑰和私鑰,公鑰可以公開,私鑰不能被公開。比特幣錢包實(shí)際上是一個(gè)密鑰對(duì),當(dāng)你安裝 一個(gè)錢包應(yīng)用,或者是使用一個(gè)比特幣客戶端來(lái)生成一個(gè)新地址是,他就會(huì)為你生成一個(gè)密鑰對(duì)。
代碼實(shí)現(xiàn)
func (cli *CLI) createWallet(nodeID string) { //創(chuàng)建錢包的主函數(shù) wallets, _ := NewWallets(nodeID) address := wallets.CreateWallet() wallets.SaveToFile(nodeID) fmt.Printf("Your new address: %s\n", address) }
我們慢慢的分析這個(gè)程序,其中的NewWallets()函數(shù)如下,在這里先是定義了一個(gè)錢包集合,我們利用wallets結(jié)構(gòu)體存儲(chǔ)多個(gè)錢包,將他們保存到文件中或者從文件中進(jìn)行加載,每個(gè)錢包都保存了一堆公鑰和私鑰。創(chuàng)建出了一個(gè)空的錢包集合后,便開始加載以前的錢包集合文件
func NewWallets(nodeID string) (*Wallets, error) { wallets := Wallets{} wallets.Wallets = make(map[string]*Wallet) err := wallets.LoadFromFile(nodeID) return &wallets, err } type Wallets struct { Wallets map[string]*Wallet } type Wallet struct { PrivateKey ecdsa.PrivateKey PublicKey []byte } func (ws *Wallets) LoadFromFile(nodeID string) error { walletFile := fmt.Sprintf(walletFile, nodeID) if _, err := os.Stat(walletFile); os.IsNotExist(err) { //判斷文件是否存在 return err } fileContent, err := ioutil.ReadFile(walletFile) // ReadFile 讀取文件中的所有數(shù)據(jù),返回讀取的數(shù)據(jù)和遇到的錯(cuò)誤。 //如果讀取成功,則 err 返回 nil,而不是 EOF func ReadFile(filename string) ([]byte, error) if err != nil { log.Panic(err) } var wallets Wallets gob.Register(elliptic.P256()) //gob是Golang包自帶的一個(gè)數(shù)據(jù)結(jié)構(gòu)序列化的編碼/解碼工具。 decoder := gob.NewDecoder(bytes.NewReader(fileContent)) err = decoder.Decode(&wallets)//這里應(yīng)該是一個(gè)解碼的過(guò)程 if err != nil { log.Panic(err) } ws.Wallets = wallets.Wallets return nil }
再來(lái)看一看wallets.CreateWallet()方法,其中的NewWallet()如下, NewWallet()函數(shù)創(chuàng)建了一個(gè)錢包,我們可以根據(jù)公鑰打印出相應(yīng)的錢包對(duì)應(yīng)的地址,然后將錢包存儲(chǔ)到錢包集合結(jié)構(gòu)體中
unc (ws *Wallets) CreateWallet() string { wallet := NewWallet() address := fmt.Sprintf("%s", wallet.GetAddress()) ws.Wallets[address] = wallet //存儲(chǔ)到錢包集合中 return address } func NewWallet() *Wallet { private, public := newKeyPair() //得到公鑰和私鑰 wallet := Wallet{private, public} //存儲(chǔ)到錢包結(jié)構(gòu)體 return &wallet } func newKeyPair() (ecdsa.PrivateKey, []byte) { curve := elliptic.P256() private, err := ecdsa.GenerateKey(curve, rand.Reader) if err != nil { log.Panic(err) } pubKey := append(private.PublicKey.X.Bytes(), private.PublicKey.Y.Bytes()...) return *private, pubKey } //由公鑰得到地址,具體方法見(jiàn)我的博客用 [“go語(yǔ)言實(shí)現(xiàn)比特幣地址校驗(yàn)”](https://blog.csdn.net/m0_37719047/article/details/81945896) func (w Wallet) GetAddress() []byte { pubKeyHash := HashPubKey(w.PublicKey) versionedPayload := append([]byte{version}, pubKeyHash...) checksum := checksum(versionedPayload) fullPayload := append(versionedPayload, checksum...) address := Base58Encode(fullPayload) return address }
最后將創(chuàng)建好的錢包更新到存儲(chǔ)錢包集合的文件中去
func (ws Wallets) SaveToFile(nodeID string) { var content bytes.Buffer //開辟一個(gè)內(nèi)存空間 walletFile := fmt.Sprintf(walletFile, nodeID) gob.Register(elliptic.P256()) encoder := gob.NewEncoder(&content) //序列化結(jié)構(gòu)體 err := encoder.Encode(ws) if err != nil { log.Panic(err) } err = ioutil.WriteFile(walletFile, content.Bytes(), 0644) //將序列化的數(shù)據(jù)寫入到文件中去 if err != nil { log.Panic(err) } }
如果我們需要打印錢包集合中所有錢包對(duì)應(yīng)的地址,我們可以利用以下的函數(shù)進(jìn)行遍歷。
func (cli *CLI) listAddresses(nodeID string) { wallets, err := NewWallets(nodeID) //加載現(xiàn)有的錢包集合 if err != nil { log.Panic(err) } addresses := wallets.GetAddresses() for _, address := range addresses { fmt.Println(address) } } func (ws *Wallets) GetAddresses() []string { var addresses []string for address := range ws.Wallets { addresses = append(addresses, address) } return addresses }
通過(guò)以上的代碼,我們便完成了錢包,實(shí)現(xiàn)了 創(chuàng)建錢包和遍歷錢包的功能
參考
https://jeiwan.cc/
以上就是GO語(yǔ)言創(chuàng)建錢包并遍歷錢包(wallet)的實(shí)現(xiàn)代碼的詳細(xì)內(nèi)容,更多關(guān)于go語(yǔ)言遍歷錢包的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang中的三個(gè)點(diǎn) ''...''的用法示例詳解
這篇文章主要介紹了golang中的三個(gè)點(diǎn) '...' 的用法示例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11golang 并發(fā)編程之生產(chǎn)者消費(fèi)者詳解
這篇文章主要介紹了golang 并發(fā)編程之生產(chǎn)者消費(fèi)者詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05在Go程序中實(shí)現(xiàn)服務(wù)器重啟的方法
這篇文章主要介紹了在Go程序中實(shí)現(xiàn)服務(wù)器重啟的方法,由于很多人盲目崇拜谷歌"親爹",Go語(yǔ)言在國(guó)內(nèi)有著不尋常的人氣,需要的朋友可以參考下2015-06-06Go底層channel實(shí)現(xiàn)原理及示例詳解
這篇文章主要介紹了Go底層channel實(shí)現(xiàn)原理及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08淺析Go語(yǔ)言的數(shù)據(jù)類型及數(shù)組
Golang是一種靜態(tài)強(qiáng)類型、編譯型語(yǔ)言。Go?語(yǔ)言語(yǔ)法與?C?相近,但功能上有:內(nèi)存安全,GC(垃圾回收),結(jié)構(gòu)形態(tài)及?CSP-style?并發(fā)計(jì)算。本文主要和大家聊聊Go語(yǔ)言的數(shù)據(jù)類型及數(shù)組,希望對(duì)大家有所幫助2022-11-11Hugo?Config模塊構(gòu)建實(shí)現(xiàn)源碼剖析
這篇文章主要為大家介紹了Hugo?Config模塊構(gòu)建實(shí)現(xiàn)源碼剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02