前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用NBitcoin进行区块链开发(5)

用NBitcoin进行区块链开发(5)

作者头像
申龙斌
发布2019-05-08 16:49:30
7980
发布2019-05-08 16:49:30
举报

请参考以下文章一起阅读:

  • 我生成的比特币地址竟然与别人的重合了
  • 用NBitcoin进行区块链开发(1) : 私钥、公钥、WIF
  • 用NBitcoin进行区块链开发(2) : 公钥哈希、地址
  • 用NBitcoin进行区块链开发(3) : ScriptPubKey
  • 用NBitcoin进行区块链开发(4) : 交易

BTC的区块链(blockchain)存储着许多交易(transaction),transaction简单来讲是指BTC从某个地址到某个地址的转移记录。与我们平常的交易记录方式不太一样,一个交易主要由输入(value input)和输出(value output)构成。

你的BTC不是凭空来的,input总是来源于以前某笔交易的某个输出项(PrevOut),这样一层一层地追查下去,总能找到BTC的源头(即挖矿产生的BTC)。而output比较容易理解,就是给张三多少BTC,给李四多少BTC。

transaction实际上就是一串二进制数值,在比特币的协议中有严格的定义,满足一系列规则的交易可以被矿工打包确认,不符合规则的交易会被直接抛弃,手工构造一笔交易,剖析其二进制表示可以更深入地了解区块链的内部原理。

本文尝试用NBitcoin构建一笔交易,其中的例子来源于下面这篇文章:

https://klmoney.wordpress.com/bitcoin-dissecting-transactions-part-2-building-a-transaction-by-hand/

从下面这个网址可以看到这笔交易的详细信息:

https://blockchair.com/bitcoin/transaction/5d42b45d5a3ddcf2421b208885871121551acf6ea5cc1c1b4e666537ab6fcbef

先直接上代码:

Step 1. 构建一个transaction

Transaction tx = Transaction.Create(Network.Main);

需要注意一点的是以前的 new Transaction()方法已经被弃用。

Step 2. 构建输入项

TxIn vin = new TxIn(); uint256 prevTX = new uint256("7e3ab0ea65b60f7d1ff4b231016fc958bc0766a46770410caa0a1855459b6e41"); vin.PrevOut = new OutPoint(prevTX, 0); tx.Inputs.Add(vin);

这里的例子只有一个输入项,来自于以前一笔transaction(TXID是7e3...e41)的输出项(正好是第0项)。在NBitcoin里有一个专门的类OutPoint,这个类的定义处于源代码Transaction.cs中。内部实际上就是记录了hash(交易ID)和n(输出序号)。

构建好一个输入项之后,不要忘了用 tx.Inputs.Add() 添加进去。

Step 3. 构建输出项

TxOut vout = new TxOut(); vout.Value = Money.Satoshis(20000); var destination = BitcoinAddress.Create("1NAK3za9MkbAkkSBMLcvmhTD6etgB4Vhpr", Network.Main); vout.ScriptPubKey = destination.ScriptPubKey; tx.Outputs.Add(vout);

给地址1NAK...hpr这个地址发送20000聪的BTC。

以前介绍过,比特币交易的内部细节并不会使用比特币地址,而是使用ScriptPubKey。

最后用 tx.Outputs.Add() 添加输出项。

Step 4. 签名交易

交易经过签名之后,才能发送到比特币网络上被所有节点进行确认,这一步较为复杂,后面再说。

二进制表示

交易就是一串二进制数字,没有被签名,也可以看到内部构成,可以输出 tx.ToHex() 看到这个结果。

0100000001416e9b4555180aaa0c417067a46607bc58c96f0131b2f41f7d0fb665eab03a7e0000000000ffffffff01204e0000000000001976a914e81d742e2c3c7acd4c29de090fc2c4d4120b2bf888ac00000000

内容比较长,拆开仔细看一下。

前4个字节表示比特币协议的版本号:00000001,即1。

后面1个字节表示输入项的个数:1,这个例子只有一项输入,对于每个输入项:

  • 32个字节,41 6e ... 3a 7e,表示前面某笔交易的ID,注意这里是TXID(7e3a...6e41)反序表示,计算机术语称为 little endian 表示法。
  • 4个字节,输出项的序号,这里为0。
  • 由于这笔交易未签名,Script Length为0,以后这里会有内容。

然后是输出项个数:1,对于每个输出项:

  • Value,转帐的BTC个数,单位是聪,这里的 20 4e 00 ... 反序表示即为4e2a,转换为十进制即为20000
  • Script Length:十进制数25
  • ScriptPubKey:76 a9 14 e8 1d 74 2e 2c 3c 7a cd 4c 29 de 09 0f c2 c4 d4 12 0b 2b f8 88 ac

专门解释一下ScriptPubKey那一行的意思,实际上是下面这一笔代码:

OP_DUP OP_HASH160 e81d742e2c3c7acd4c29de090fc2c4d4120b2bf8 OP_EQUALVERIFY OP_CHECKSIG

e8 1d ... 2b f8 是以前介绍过的公钥哈希,20个字节。

关于OP_DUP、OP_HASH160、OP_EQUALVERIFY和OP_CHECKSIG这些代码的二进制表示,就是76、a9、88、ac,可以在下面网址查到:

https://en.bitcoin.it/wiki/Script

跟在0x76(OP_DUP)和0xa9(OP_HASH160)之后的0x14,表示十进制数20,用来将随后的20个字节的公钥哈希压入堆栈。

--- END ---

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 申龙斌的程序人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
区块链
云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档