评论

收藏

[Go语言] GO语言创建钱包并遍历钱包(wallet)的实现代码

编程语言 编程语言 发布于:2021-06-29 21:50 | 阅读数:183 | 评论:0

基本知识
  公钥加密算法使用的是成对的密钥:公钥和私钥,公钥可以公开,私钥不能被公开。比特币钱包实际上是一个密钥对,当你安装 一个钱包应用,或者是使用一个比特币客户端来生成一个新地址是,他就会为你生成一个密钥对。
代码实现
func (cli *CLI) createWallet(nodeID string) {   //创建钱包的主函数
  wallets, _ := NewWallets(nodeID)   
  address := wallets.CreateWallet()
  wallets.SaveToFile(nodeID)
  fmt.Printf("Your new address: %s\n", address)
}
  我们慢慢的分析这个程序,其中的NewWallets()函数如下,在这里先是定义了一个钱包集合,我们利用wallets结构体存储多个钱包,将他们保存到文件中或者从文件中进行加载,每个钱包都保存了一堆公钥和私钥。创建出了一个空的钱包集合后,便开始加载以前的钱包集合文件
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 读取文件中的所有数据,返回读取的数据和遇到的错误。
  //如果读取成功,则 err 返回 nil,而不是 EOF
func ReadFile(filename string) ([]byte, error)
  if err != nil {
    log.Panic(err)
  }
  var wallets Wallets
  gob.Register(elliptic.P256())
  //gob是Golang包自带的一个数据结构序列化的编码/解码工具。
  decoder := gob.NewDecoder(bytes.NewReader(fileContent))
  err = decoder.Decode(&wallets)//这里应该是一个解码的过程
  if err != nil {
    log.Panic(err)
  }
  ws.Wallets = wallets.Wallets
  return nil
}
  再来看一看wallets.CreateWallet()方法,其中的NewWallet()如下, NewWallet()函数创建了一个钱包,我们可以根据公钥打印出相应的钱包对应的地址,然后将钱包存储到钱包集合结构体中
unc (ws *Wallets) CreateWallet() string {
  wallet := NewWallet()
  address := fmt.Sprintf("%s", wallet.GetAddress())
  ws.Wallets[address] = wallet  //存储到钱包集合中
  return address
}
func NewWallet() *Wallet {
  private, public := newKeyPair()   //得到公钥和私钥
  wallet := Wallet{private, public}  //存储到钱包结构体
  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
}
//由公钥得到地址,具体方法见我的博客用 [“go语言实现比特币地址校验”](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
}
  最后将创建好的钱包更新到存储钱包集合的文件中去
func (ws Wallets) SaveToFile(nodeID string) {
  var content bytes.Buffer   //开辟一个内存空间
  walletFile := fmt.Sprintf(walletFile, nodeID)
  gob.Register(elliptic.P256())
  encoder := gob.NewEncoder(&content)  //序列化结构体
  err := encoder.Encode(ws)
  if err != nil {
    log.Panic(err)
  }
  err = ioutil.WriteFile(walletFile, content.Bytes(), 0644)  //将序列化的数据写入到文件中去
  if err != nil {
    log.Panic(err)
  }
}
  如果我们需要打印钱包集合中所有钱包对应的地址,我们可以利用以下的函数进行遍历。
func (cli *CLI) listAddresses(nodeID string) {
  wallets, err := NewWallets(nodeID)   //加载现有的钱包集合
  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
}
  通过以上的代码,我们便完成了钱包,实现了 创建钱包和遍历钱包的功能
参考
  https://jeiwan.cc/
  以上就是GO语言创建钱包并遍历钱包(wallet)的实现代码的详细内容,更多关于go语言遍历钱包的资料请关注脚本之家其它相关文章!

关注下面的标签,发现更多相似文章