Py学习  »  区块链

用NBitcoin进行区块链开发

申龙斌的程序人生 • 5 年前 • 600 次点击  

Bitcoin Core是根正苗红的比特币全节点钱包软件,由创始人中本聪最早完成,编程语言是C++,对于一些现代程序员来说,理解起来有一定难度,所以有些开发者将这些代码移植为其它编程语言。


Bitcoin在.NET平台的一款实现就是今天要介绍的NBitcoin,项目站点:

https://github.com/MetacoSA/NBitcoin


我使用的软件集成开发平台是Visual Studio 2015,.Net Framework是4.5.2。



安装NBitcoin引用


我建立了一个控制台应用HelloBitcoin,需要添加NBitcoin类库的引用,最方便的办法是用NuGet,操作办法见下图,注意可能需要翻墙。


安装过程中,会对整个解决方案的依赖类库进行一系列修改, 并且让你接受软件许可授权,可能涉及到的类库:

Newtonsoft.Json 11.0.2

System.Buffers 4.5.0

System.Collections 4.0.11

System.Collections.Concurrent 4.0.12

System.Diagnostics.Debug 4.0.11

System.Globalization 4.0.11

System.Linq 4.1.0

System.Net.Http 4.3.3

System.Net.Requests 4.3.0

System.Reflection 4.1.0

System.Resources.ResourceManager 4.0.1

System.Runtime.Extensions 4.1.0

System.Runtime.InteropServices 4.1.0

Microsoft.Extensions.Logging.Abstractions 1.0.2


最后在调试输出窗口中出现这样一行:

已将“NBitcoin 4.1.1.71”成功安装到 HelloBitcoin

表示NBitcoin安装成功。



用私钥生成比特币地址


下面一段简单的代码用来将一串私钥生成为比特币地址,请与《我生成的比特币地址竟然与别人的重合了》这篇文章一起参考阅读。


程序开头不要忘记这一行:

using NBitcoin;


直接上代码:


简要解释说明一下:

privKeys是私钥,为256位二进制数,NBitcoin中与私钥对应的类是Key。


下面这行语句生成一个随机私钥。

Key k = new Key(); 


私钥可以生成公钥,再生成比特币地址,借用一下《精通比特币》中的这张原理图。


Network.Main表示使用比特币的真实主网络,直接用真金白银的BTC调试程序太奢侈,可以切换到测试网络Network.TestNet。


程序最终输出:

19t4GGYorFziM26CRMYvxqvDw6NPhuCRJS


对应于BitcoinExplorer工具的命令行是:

bx ec-to-public 3243......E6C8 | bx bitcoin160 | bx address-encode

可以看到,最后生成的比特币地址是一致的。



压缩公钥、非压缩公钥


一个私钥实际上可以产生出两种不同的比特币地址,这个问题有点迷惑人,但这是由于椭圆曲线的特性造成的,先看代码。

k1生成出来的是压缩公钥:

为了方便阅读,我人为插入了空格。

02 2e88d239fb78cee0c1c55943a96dcc8b70adf47e18b53f9ba110b6fb871e1f8b


k2对应于非压缩公钥:

请注意与上面的区别。

04 2e88d239fb78cee0c1c55943a96dcc8b70adf47e18b53f9ba110b6fb871e1f8b b119f9161df032167181d623a401dde4091c3e0be2001e4dea3e1f53f851aa3a


拆开说明这一长串数字的具体含义:

04 // 表示非压缩公钥

2e88d239fb78cee0c1c55943a96dcc8b70adf47e18b53f9ba110b6fb871e1f8b  // 椭圆曲线上点的X坐标

b119f9161df032167181d623a401dde4091c3e0be2001e4dea3e1f53f851aa3a // 椭圆曲线上点的Y坐标


椭圆曲线有一个重要特性,它是以X轴为对称轴的,这样记录一个点的坐标时,只需要记录X坐标,省略Y坐标,只需要知道Y坐标的正负号,就可以根据X计算出Y。

在二进制的椭圆曲线运算中,没有正负号,但有奇偶性,只记录X坐标及奇偶性,就是压缩公钥的表示法,刚才的那个公钥就可以节省一半的存储空间。

02 // 表示压缩公钥,Y坐标为偶数

2e88d239fb78cee0c1c55943a96dcc8b70adf47e18b53f9ba110b6fb871e1f8b  // 椭圆曲线上点的X坐标


两种公钥表现形式不一样,生成的比特币地址当然就不一样:

地址1: 

19t4GGYorFziM26CRMYvxqvDw6NPhuCRJS

地址2: 

17mKugcBDEJbu391Fq41AdwLeGHwJLPRDf


比特币的交易信息中经常存储公钥,压缩公钥节省了大量存储空间,意义重大,后来的钱包软件主要都使用压缩公钥,也就是常用上面的地址1

19t4GGYorFziM26CRMYvxqvDw6NPhuCRJS



WIF钱包导入格式


私钥是一长串数字,比如:3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C8,输入费劲,还容易出错,中本聪就规定了一种WIF格式,称为Wallet Import Format,这种格式的私钥可以非常方便地导入到Bitcoin Core等钱包软件中。


用GetWif()函数可以非常容易地得到WIF格式的私钥。

以K开头的为压缩表示法:

KxuRLWqnfcgs8ru7YiMBfP6T71jK9twCedaeBtHgRgzb8adnoZzH

以5开头的是非压缩表示法,但本质上两个私钥是一模一样的:

5JCRYcJrKGLTK6R3PbHopfY9BRdmtrq5TCTesx7x9mQUDeYDfZj



P2SH地址、隔离见证地址


前面见到的比特币地址都是以1开头的:

19t4GGYorFziM26CRMYvxqvDw6NPhuCRJS

17mKugcBDEJbu391Fq41AdwLeGHwJLPRDf


很多人现在看到的是以3开头的地址,这种地址术语是P2SH地址,即Pay-to-Script Hash地址,这类地址是由交易脚本创建的,具体原理先不用了解,代码很方便。

pk1.GetScriptAddress(Network.Main)

结果是这样的:

33yjfa31iqdDRqHqQRuvySB7SVV7wd77aj


后来又出来了隔离见证地址,采用Bech32格式编码。

pk1.GetSegwitAddress(Network.Main)

样子是这样的:
bc1qv950rspcgfqufasc29calr5qphh4ucl3ur7vnm

看到这样的地址别以为收到了假比特币。



以前在给多个人发币时,使用NBitcoin时踩了一些坑:

当时想参考NBitcoin的API文档:

https://metacosa.github.io/NBitcoin/api/index.html

可惜文档非常糟糕,还不如果直接看源代码,几乎是边google边试错完成了程序。


所以我准备把更详细的使用方法逐步整理出来,请留言或点赞,给我助力。


--- END ---



以前精彩文章:



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/jHtCCaqCy5
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/26972
 
600 次点击