錢包基礎概念
- 廣義上,錢包是一個應用程式,為用戶提供互動界面,錢包控制用戶訪問權限、管理位元比地址及秘鑰、跟蹤余額、創建交易和簽名交易
- 狹義上,即從程式員角度來看,“錢包”是指用于存盤和管理用戶秘鑰的資料結構
- 錢包是私鑰的容器,一般是通過結構化檔案或簡單資料庫來實作的
- 錢包中并不包含位元幣,位元幣是被記錄在位元幣網路的區塊鏈中,用戶通過錢包中的密鑰簽名交易,從而控制網路中的位元幣,在某種意義上,位元幣錢包就是密鑰鏈
錢包結構體
type Wallet struct {
//私鑰
Private *ecdsa.PrivateKey
//約定,這里的PubKey不存盤原始的公鑰,而是存盤X和Y拼接的字串,在校驗端重新拆分(參考r,s傳遞)
PubKey []byte
}
創建錢包
func NewWallet() *Wallet {
//創建曲線
curve := elliptic.P256()
//生成私鑰
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
log.Panic(err)
}
//生成公鑰
pubKeyOrig := privateKey.PublicKey
//拼接X, Y
pubKey := append(pubKeyOrig.X.Bytes(), pubKeyOrig.Y.Bytes()...)
return &Wallet{Private: privateKey, PubKey: pubKey}
}
錢包集結構體
//定一個 Wallets結構,它保存所有的wallet以及它的地址
type Wallets struct {
//map[地址]錢包
WalletsMap map[string]*Wallet
}
創建錢包集
func NewWallets() *Wallets {
var ws Wallets
ws.WalletsMap = make(map[string]*Wallet)
//加載本地錢包,把新建的錢包保存到本地
ws.loadFile()
return &ws
}
創建錢包到錢包集
func (ws *Wallets) CreateWallet() string {
//創建一個錢包
wallet := NewWallet()
address := wallet.NewAddress()
//添加到錢包集
ws.WalletsMap[address] = wallet
//保存包本地
ws.saveToFile()
//回傳創建錢包的地址
return address
}
保存錢包到本地
func (ws *Wallets) saveToFile() {
var buffer bytes.Buffer
gob.Register(elliptic.P256())
encoder := gob.NewEncoder(&buffer)
err := encoder.Encode(ws)
//一定要注意校驗!!!
if err != nil {
log.Panic(err)
}
ioutil.WriteFile(walletFile, buffer.Bytes(), 0600)
}
讀取錢包集里的錢包
func (ws *Wallets) loadFile() {
//在讀取之前,要先確認檔案是否在,如果不存在,直接退出
_, err := os.Stat(walletFile)
if os.IsNotExist(err) {
return
}
//讀取內容
content, err := ioutil.ReadFile(walletFile)
if err != nil {
log.Panic(err)
}
//解碼
gob.Register(elliptic.P256())
decoder := gob.NewDecoder(bytes.NewReader(content))
var wsLocal Wallets
err = decoder.Decode(&wsLocal)
if err != nil {
log.Panic(err)
}
ws.WalletsMap = wsLocal.WalletsMap
}
列出所有錢包的地址
func (ws *Wallets) ListAllAddresses() []string {
var addresses []string
//遍歷錢包,將所有的key取出來回傳
for address := range ws.WalletsMap {
addresses = append(addresses, address)
}
return addresses
}
生成錢包地址
- 隨機選取32byte的數字作為私鑰
- 使用橢圓曲線加密演算法(ECDSA-secp256k1)計算私鑰對應的非壓縮公鑰
- 計算公鑰的SHA-256哈希值
- 取上一步結果,計算RIPEMD-160哈希值
- 取上一步結果,前面加上版本號(位元幣主網版本號“0x00”)
- 取上一步結果,計算SHA-256哈希值
- 取上一步結果,計算SHA-256哈希值
- 取上一步結果的前4個位元組(8位十六進制)
- 把這4個位元組加在第五步的結果后面,作為校驗(這就是位元幣地址的十六進制形態)
- 用base58表示法變換一下地址(這就是常見的位元幣地址形態)
//生成地址
func (w *Wallet) NewAddress() string {
//錢包公鑰
pubKey := w.PubKey
//計算公鑰哈希和ripe160
rip160HashValue := HashPubKey(pubKey)
//主網版本號為0x00
version := byte(00)
//拼接version
payload := append([]byte{version}, rip160HashValue...)
//校驗碼checksum
checkCode := CheckSum(payload)
//拼接版本、哈希值、校驗碼、25位元組資料
payload = append(payload, checkCode...)
//base58編碼
address := base58.Encode(payload)
return address
}
結束
原始碼:https://gitee.com/xiaoshengdada/go_bitcoin/tree/master/v5
如果有任何問題可以來微信群交流,另外群里有學習資料,可以自行下載,一起學習進步,

最最后,推薦一位大佬的公眾號:區塊鏈技術堆疊,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/272940.html
標籤:區塊鏈
下一篇:Mac Fabric 安裝
