go语言实现简易比特币系统钱包的原理解析

钱包基础概念

  • 广义上,钱包是一个应用程序,为用户提供交互界面。钱包控制用户访问权限、管理比特比地址及秘钥、跟踪余额、创建交易和签名交易
  • 狭义上,即从程序员角度来看,“钱包”是指用于存储和管理用户秘钥的数据结构
  • 钱包是私钥的容器,一般是通过结构化文件或简单数据库来实现的
  • 钱包中并不包含比特币。比特币是被记录在比特币网络的区块链中,用户通过钱包中的密钥签名交易,从而控制网络中的比特币,在某种意义上,比特币钱包就是密钥链

钱包结构体

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

到此这篇关于go语言实现简易比特币系统钱包的原理解析的文章就介绍到这了,更多相关go实现比特币钱包内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang之数据校验的实现代码示例

    目前大都是使用 validator 安装 go get gopkg.in/go-playground/validator.v9 原理 当然只能通过反射来实现了,之前写过一篇反射的文章 golang之反射和断言 ,里面有写到怎么通过反射获取struct tag. 读取struct tag之后就是对里面的标识符进行识别,然后进行验证了.具体可以去看源码. demo 简单使用: package main import ( "fmt" "gopkg.in/go-playground/

  • 使用go实现简易比特币区块链公链功能

    使用go语言实现具备以下功能的简易区块链 区块与区块链 共识机制 数据库 Cli命令行操作 交易管理 密码学 数字签名 交易缓存池 P2P网络管理 由于平时还要进行论文工作,项目不定时更新 2021.1.1实现了区块结构.区块链结构.工作量证明pow,剩下部分陆续更新 1.实现区块结构 package BLC import ( "bytes" "crypto/sha256" "time" ) //实现一个最基本的区块结构 type Block s

  • Go语言实现IP段范围校验示例

    背景 近期做了一个需求,是检测某个 IP 是否在若干 IP 段内,做固定地点 IP 筛查,满足特定业务需求. 解决方案 PLAN A 点分十进制范围区分 简单来讲,就是将 IPv4 原有的四段,分别对比 IP 地址,查看每一段是否在 IP 段范围内,可以用于段控制在每一个特定段 0 - 255 内筛选,例如: 192.123.1.0 - 192.123.156.255 这样的比较规范的特定段可以实现简单的筛选,但是问题来了,不规则的连续 IP 段怎么排除? 如下: IP段:192.168.1.0

  • go语言实现简易比特币系统之交易签名及校验功能

    介绍 签名的输入: 待签名的交易数据,包括输入和输出 引用的UTXO信息 私钥 签名的输出: 数字数字签名 公钥 签名的目的 证明交易所引用的UTXO的确属于付款人 证明交易的所有数据的确是付款人提供的,且未被修改过 签名中需要的数据 UTXO中的PubKeyHash,这描述了付款人 新生成UTXO中的PubKeyHash,这描述了收款人 由于每一笔交易都可能引用多个UTXO,因为多个UTXO可能存在于多条交易中.所以我们需要遍历所以的引用交易,并对他们逐个签名 签名过程 用解锁脚本解锁对应的U

  • Django框架登录加上验证码校验实现验证功能示例

    本文实例讲述了Django框架登录加上验证码校验实现验证功能.分享给大家供大家参考,具体如下: 验证码生成函数 pip install Pillow # /verify_code def verif_ycode(request): #引入绘图模块 from PIL import Image, ImageDraw, ImageFont #引入随机函数模块 import random #定义变量,用于画面的背景色.宽.高 bgcolor = (random.randrange(20, 100), r

  • Django之form组件自动校验数据实现

    一.form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度和格式等正不正确.如果用户输入的内容有错误就需要在页面上相应的位置显示对应的错误信息.. Django form组件就实现了上面所述的功能. 总结一下,其实form组件的主要功能如下: 生成页面可用的HTML标签 对用户提交的数据进行校验 保留上次输入内容 二.普通方式手写注册功

  • go语言实现简易比特币系统钱包的原理解析

    钱包基础概念 广义上,钱包是一个应用程序,为用户提供交互界面.钱包控制用户访问权限.管理比特比地址及秘钥.跟踪余额.创建交易和签名交易 狭义上,即从程序员角度来看,"钱包"是指用于存储和管理用户秘钥的数据结构 钱包是私钥的容器,一般是通过结构化文件或简单数据库来实现的 钱包中并不包含比特币.比特币是被记录在比特币网络的区块链中,用户通过钱包中的密钥签名交易,从而控制网络中的比特币,在某种意义上,比特币钱包就是密钥链 钱包结构体 type Wallet struct { //私钥 Pri

  • C语言实现简易订餐系统

    本文实例为大家分享了C语言实现简易订餐系统的具体代码,供大家参考,具体内容如下 主要功能: (1)菜单维护(餐厅管理人员使用)采用顺序表实现 1.添加新菜 2.删除菜品 3.修改菜品信息 4.打印现有的菜品信息 (2)点餐(客户使用)  采用链表实现 1.订单菜品添加.删除.显示 2.计算显示订单总价......... 对此我们可以创建一个结构体类型,并将其重命名为ElemType,结构体里面存放有id,name,price分别表示菜品的id号,菜名和价格.接着分别定义一个顺序表和链表.接着我们

  • C语言实现简易扫雷游戏

    本文实例为大家分享了C语言实现简易扫雷游戏的具体代码,供大家参考,具体内容如下 扫雷 楔子: 扫雷游戏是我们小时候无聊时消磨时间的小玩意,虽然更新到Win10系统后经典的扫雷游戏不再了,不过它现在仍以一种抓虫子的游戏形式存在于Windows这个系统平台,不禁感慨游戏还是那个游戏,不过人已经不是那些人了啊. 其实扫雷游戏的实现也主要运用了数组和函数封装与调用的知识,具体请看程序. 以下为程序主体: #define _CRT_SECURE_NO_WARNINGS #include <stdio.h>

  • C语言实现小学生考试系统

    本文实例为大家分享了C语言实现小学生考试系统的具体代码,供大家参考,具体内容如下 问题及代码: /*烟台大学计算机学院 题目描述:做一个小学生考试系统,功能包括: (1)利用随机数出10道加法题: (2)小学生用户答题给出每道题的答案: (3)对小学生的答题进行评判: (4)计算出小学生答题正确率. 作者:景怡乐 完成时间:2016年12月29日 */ #include <stdio.h> #include <stdlib.h> #include <time.h> in

  • C语言实现学生选课系统完整版

    本文实例为大家分享了C语言实现学生选课系统的具体代码,供大家参考,具体内容如下 #include<stdio.h> #include<stdlib.h> int N1,N2,kk1,kk2,kk3; struct couse * head1; struct student * head2; struct couse//课程信息结构体 { int num1; char name1[20]; int score; int nelepeo;//课程已选人数 int Melepeo;//课

  • C语言实现学生选课系统

    本文实例为大家分享了C语言实现学生选课系统的具体代码,供大家参考,具体内容如下 代码: #include<stdio.h> #include<windows.h> #include<stdlib.h> #include<conio.h> typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #define CLASS_CLS

  • C语言实现文本编辑器系统

    本文实例为大家分享了C语言实现文本编辑器系统的具体代码,供大家参考,具体内容如下 /*文本编辑器editor源代码*/ #include <stdio.h> #include <conio.h> #include <bios.h> #include <math.h> #define LEFT 0x4b00 /*←:光标左移*/ #define RIGHT 0x4d00 /*→:光标右移*/ #define DOWN 0x5000 /*↓键:光标下移*/ #d

  • Java简易抽奖系统小项目

    本文实例为大家分享了Java简易抽奖系统的具体代码,供大家参考,具体内容如下 需求: 实现一个抽奖系统 1 注册 2 登录 3 抽奖 必须先注册  再登陆  再抽奖 随机产生4个随机数作为幸运卡号 用户注册后 登录的时候  用户名密码输入判断只有三次机会 需要做到  还有2次   还有1次  三次输入错误 不能再登录 产生10个随机数  将用户注册得到的随机数作为判断 代码如下: import java.util.*; public class Homeworktest { public sta

随机推荐