主页 > 华为怎么安装imtoken > 窥探比特币核心的工作原理

窥探比特币核心的工作原理

华为怎么安装imtoken 2023-01-17 01:31:49

比特币真的很酷。当然,有人想知道它是否是一项有用的技术,我们目前是否处于加密货币泡沫中,或者它目前面临的治理问题是否会得到解决……但在纯粹的技术层面上,神秘的中本聪创造了令人印象深刻的技术。

不幸的是,虽然有大量资源可以对比特币的工作原理进行高级解释,但我强烈推荐的其中一个视频资源是 Anders Brownworth 的区块链视觉 101,但低级信息较少。在我看来,如果你看看 10000 英尺的景色,你就可以正确理解这一点。

作为一个新手,我发现自己渴望了解比特币的运作机制。幸运的是,由于比特币本质上是去中心化和点对点的,任何人都可以开发符合协议的客户端。为了更好地理解比特币的工作原理,我决定编写自己的小玩具比特币客户端,它能够将交易发布到比特币区块链。

这篇文章介绍了创建最小可行比特币客户端的过程,该客户端可以创建交易并将其提交到比特币点对点网络,以便它可以包含在区块链中。如果您只是阅读原始代码,请随时查看我的 Github 存储库。

地址生成

要成为比特币网络的一部分,您必须拥有一个可以发送和接收资金的地址。比特币使用公钥加密,地址基本上是从公钥私钥派生的公钥的散列版本。令人惊讶的是,与大多数公钥密码术不同,公钥在保存之前也是加密的,直到资金从地址发送出去——但以后会有更多的不同和惊喜。

快速浏览术语:在比特币中,客户使用术语钱包来指代地址集合。协议层面没有钱包的概念,只有地址。

比特币的地址使用椭圆曲线公钥加密。在超高层次上,椭圆曲线加密用于从私钥生成公钥,与 RSA 相同,但占用空间更小。如果您有兴趣了解一些有关其工作原理的数学知识,Cloudflare 的 Primer 是一个很好的资源。

从256位私钥开始,生成比特币地址的过程如下:

比特币地址生成

在 Python 中,我使用 ecsda 库来完成椭圆曲线加密的繁重工作。下面的代码片段通过非常容易记住(并且非常不安全)的私钥 0xFEEDB0BDEADBEEF(在前面填充足够的零以使其长度为 64 个十六进制字符或 256 位)获得一个公钥。如果您想在地址中存储任何实际值,则需要一种更安全的方式来生成私钥!

作为一个有趣的测试,我最初用私钥0xFACEBEEF创建了一个地址并发送它0.0005BTC,1个月后,有人偷走了我的0.0005BTC!我猜人们必须偶尔使用简单的公钥来搜索地址。您确实必须使用正确的密钥派生技术!

1
2
3
4
5
6
7
8
9
10
11
12

from ecdsa import SECP256k1, SigningKey

def get_private_key(hex_string):
return bytes.fromhex(hex_string.zfill(64)) # pad the hex string to the required 64 characters

def get_public_key(private_key):
# this returns the concatenated x and y coordinates for the supplied private address
# the prepended 04 is used to signify that it's uncompressed
return (bytes.fromhex("04") + SigningKey.from_string(private_key, curve=SECP256k1).verifying_key.to_string())

private_key = get_private_key("FEEDB0BDEADBEEF")
public_key = get_public_key(private_key)

运行此代码以获取私钥(十六进制)

1

0000000000000000000000000000000000000000000000000feedb0bdeadbeef

和公钥(十六进制)

1

04d077e18fd45c031e0d256d75dfa8c3c21c589a861c4c33b99e64cf613113fcff9fc9d90a9d81346bcac64d3c01e6e0ef0828543edad73c0e257b845812cc8d28

预设公钥的0x04表示这是一个未压缩的公钥,也就是说ECDSA的x和y坐标只是拼接起来的。由于 ECSDA 的工作方式,如果知道 x 值,y 值只能取两个值,一个偶数,一个奇数。使用此信息,可以使用 x 和 y 的极性来表示公钥。这将公钥大小从 65 位减少到 33 位,并且密钥(以及随后计算的地址)称为压缩。对于压缩的公钥,前置值将是 0x02 或 0x03,具体取决于 y 的极性。未压缩的公钥在比特币中最常用,所以我也在这里使用。

从这里,从公钥生成比特币地址,公钥是sha256哈希,然后是cookedmd160哈希。这种双重散列提供了额外的安全层,而成熟的 160 散列提供了 sha256 的 256 位散列的 160 位散列,缩短了地址的长度。一个有趣的结果是两个不同的公钥可以散列到同一个地址!但是,由于有 2^160 个不同的地址,这不太可能很快发生。

1
2
3
4
5
6
7
8
9
10
11
12

import hashlib

def get_public_address(public_key):
address = hashlib.sha256(public_key).digest()

h = hashlib.new('ripemd160')
h.update(address)
address = h.digest()

return address

public_address = get_public_address(public_key)

以上代码生成一个公共地址c8db639c24f6dc026378225e40459ba8a9e54d1a。这有时称为哈希 160 地址。

如前所述,有趣的一点是,从私钥到公钥的转换以及从公钥到公共地址的转换都是单向转换。如果您有地址,则反向查找关联公钥的唯一方法是求解 SHA256 哈希。这与大多数公钥密码术略有不同,例如在公钥中发布公钥并隐藏您的私钥。在这种情况下,隐藏公钥和私钥,并公布地址(散列公钥)。

隐藏公钥是有充分理由的。虽然从相应的公钥计算私钥通常是不可行的,但如果生成私钥的方法受到损害,访问公钥可以更容易地推断出私钥。 2013年,这个臭名昭著的Android比特币钱包事件。 Android 在随机数生成方面有一个严重的弱点,这为攻击者从公钥中找到私钥打开了一个向量。这也是不鼓励在比特币中重复使用地址的原因——在签署交易时,你需要透露你的公钥。如果您在发送交易后不重用地址,则无需担心该地址的公钥被泄露。

表示比特币地址的标准方法是使用其 Base58Check 编码。编码只是地址的表示(因此可以解码/反转)。 Base58Check 生成 1661HxZpSy5jhcJ2k6av2dxuspa8aafDac 格式的地址。 Base58Check 编码提供了更短的地址来表达,并且还具有允许检测错误地址的内置校验和。在几乎每个比特币客户端中,您的地址的 Base58Check 编码就是您将看到的地址。 Base58Check 还包含一个版本号,我在下面的代码中将其设置为 0 - 这意味着该地址是一个 pubkey 哈希。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 58 character alphabet used
BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'

def base58_encode(version, public_address):
"""
Gets a Base58Check string
See https://en.bitcoin.it/wiki/base58Check_encoding
"""
version = bytes.fromhex(version)
checksum = hashlib.sha256(hashlib.sha256(version + public_address).digest()).digest()[:4]
payload = version + public_address + checksum

result = int.from_bytes(payload, byteorder="big")

print(result)

# count the leading 0s
padding = len(payload) - len(payload.lstrip(b'\0'))
encoded = []

while result != 0:
result, remainder = divmod(result, 58)
encoded.append(BASE58_ALPHABET[remainder])

return padding*"1" + "".join(encoded)[::-1]

bitcoin_address = base58_encode("00", public_address)

毕竟从我的私钥feedb0bdeadbeef(前面补零)开始,我的比特币地址是1KK2xni6gmTtdnSGRiuAf94jciFgRjDj7W!。

有了地址,您现在可以赚取一些比特币!为了将比特币送到我的地址,我从 btcmarkets 以澳元购买了 0.0045BTC(在撰写本文时,约为 11 美元)。通过btcmarket的交易门户,我将其转移到上述地址,在此过程中损失了0.0005BTC的交易费用。您可以在区块链上的交易 95855ba9f46c6936d7b5ee6733c81e715ac92199938ce30ac3e1214b8c2cd8d7 中看到此交易。

连接到 p2p 网络

现在我有了一个包含一些比特币的地址,事情变得更有趣了。如果我想将比特币发送到其他地方,我需要连接到比特币节点网络。

简介

我第一次了解比特币时遇到的一个困难是,考虑到网络的去中心化程度,网络中的节点如何找到其他节点?如果没有中央权威,比特币客户端如何知道如何引导并开始与网络的其余部分通信?

事实证明比特币核心,理想主义在初始对等发现过程中以最少的集中化程度提出实用性。新客户端查找要连接的节点的主要方法是使用 DNS 查找来查找由比特币社区成员维护的任意数量的 DNS 种子服务器。

DNS 非常适合引导客户端,因为 DNS 协议在 UDP 上运行并且很轻,因此很难用于 DDoS。 IRC 被用作以前的引导方法,但由于其对 DDoS 攻击的弱点而被终止。

种子是硬编码的,但可以由核心开发人员更改。

下面的 Python 代码连接到 DNS 种子 DNS 种子并任意选择要连接的第一个节点。使用套接字库,代码基本上执行 nslookup 并在对种子节点 seed.bitcoin.sipa.be 运行查询时返回第一个结果的 ipv4 地址。

1
2
3
4
5
6
7

import socket

# use a dns request to a seed bitcoin DNS server to find a node
nodes = socket.getaddrinfo("seed.bitcoin.sipa.be", None)

# arbitrarily choose the first node
node = nodes[0][4][0]

运行后返回地址为208.67.251.126,这是我可以连接的友好节点!

向新节点问好

节点之间的比特币连接通过 TCP。连接节点时,比特币协议的开始握手消息是版本消息。在节点交换消息之前不接受其他消息。

比特币协议消息在比特币开发者参考中有详细记录。使用开发人员参考作为指南,可以在 Python 中构建版本消息,如下面的代码片段所示。大多数数据是相当无趣的,用于建立节点连接的管理数据。如果您对附件中的详细信息感兴趣,请阅读开发者参考。

1
2
3
4
5
6
7
8
9
10
11
12
13

version = 70014
services = 1 # not a full node, cant provide any data
timestamp = int(time.time())
addr_recvservices = 1
addr_recvipaddress = socket.inet_pton(socket.AF_INET6, "::ffff:127.0.0.1") #ip address of receiving node in big endian
addr_recvport = 8333
addr_transservices = 1
addr_transipaddress = socket.inet_pton(socket.AF_INET6, "::ffff:127.0.0.1")
addr_transport = 8333
nonce = 0
user_agentbytes = 0
start_height = 329167
relay = 0

使用Python的struct库,将版本payload数据打包成正确的格式,特别注意数据的字节顺序和字节宽度。将数据打包成正确的格式很重要,否则接收节点将无法理解它接收到的原始字节。

1
2
3
4
5
6
7
8
9
10
11
12

payload = struct.pack("
payload += struct.pack("
payload += struct.pack("
payload += struct.pack("
payload += struct.pack("16s", addr_recvipaddress)
payload += struct.pack(">H", addr_recvport)
payload += struct.pack("
payload += struct.pack("16s", addr_transipaddress)
payload += struct.pack(">H", addr_transport)
payload += struct.pack("
payload += struct.pack("
payload += struct.pack("

同样,开发人员参考提供了有关如何打包此数据的信息。最后,在比特币网络上传输的每个有效载荷都需要附有一个标头,该标头包含有效载荷的长度、校验和以及有效载荷的消息类型。标头还包含为所有主要比特币消息设置的神奇常数 0xF9BEB4D9。以下函数获取带有标头的比特币消息。

1
2
3
4
5
6
7

def get_bitcoin_message(message_type, payload):
header = struct.pack(">L", 0xF9BEB4D9)
header += struct.pack("12s", bytes(message_type, 'utf-8'))
header += struct.pack("
header += hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4]

return header + payload

将数据打包成正确的格式并附上header,就可以发送给我们的Peer了!

1
2
3
4

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((node, 8333))
s.send(get_bitcoin_message("version", payload))
print(s.recv(1024))

比特币协议要求当接收到版本消息时,节点应响应 Verack 确认消息。因为我是为了好玩而构建一个小客户端,而且如果我不这样做,同行也不会区别对待我,所以我会忽略他们的版本消息而不向他们发送确认。在我连接时发送版本消息足以让我以后发送更有意义的消息。

运行上述代码段会打印以下内容。它确实看起来很有希望 - Satoshi 和 Verack 在垃圾场看到的好词!如果我的版本消息格式错误,节点根本不会响应。

1

b'\xf9\xbe\xb4\xd9version\x00\x00\x00\x00\x00f\x00\x00\x00\xf8\xdd\x9aL\x7f\x11\x01\x00\r\x00\x00\x00\x00\x00\x00\x00\xddR1Y\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xcb\xce\x1d\xfc\xe9j\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\xb8>*\x88@I\x8e\x10/Satoshi:0.14.0/t)\x07\x00\x01\xf9\xbe\xb4\xd9verack\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\xf6\xe0\xe2'

比特币交易

要转移比特币,您必须发送 Coin 网络广播交易。

至关重要的是,要理解的最重要的概念是,比特币地址的余额仅由地址可以花费的“未花费交易输出”(UTXO)的数量组成。当 Bob 向 Alice 发送比特币时,他实际上只是创建了一个 UTXO,Alice(并且只有 Alice)以后可以使用它来创建另一个 UTXO 并发送比特币。因此,一个比特币地址的余额是由它可以转移到另一个地址的比特币数量来定义的,而不是它持有的比特币数量。

需要强调的是,当有人说他们有 X 个比特币时,他们实际上是在说他们可以花费的所有 UTXO 加起来就是 X 个比特币的价值。区别是微妙但重要的,比特币地址的余额不会直接记录在任何地方,但可以通过将其可以花费的 UTXO 相加来找到。当我意识到这绝对是一个“哦,这就是它的工作原理!”时刻。

这样做的副作用是交易输出可以未使用(UTXO)或完全使用。不可能只花别人已经花在你身上的一半产出,然后再花剩下的。如果您确实想花费您收到的输出的一小部分,您可以发送您想要发送的分数,而将其余部分发回给您自己。简化版如下所示。

比特币交易

在创建交易输出时,会使用锁定条件来创建交易输出,以便将来有人可以通过所谓的交易脚本使用它。最常见的锁定条件是:“要花费此输出,您需要证明您拥有与特定公共地址对应的私钥”。这称为 Pay-to-Public-Key-Hash 脚本。但是,使用比特币脚本,其他类型的条件也是可能的。例如,可以创建任何可以解决某个哈希的人都可以使用的输出,或者可以创建任何人都可以使用的交易。

使用脚本,可以创建简单的基于合约的交易。脚本是一种基本的基于堆栈的语言,具有许多专注于检查哈希相等性和验证签名的操作。脚本不是图灵完备的,也没有能力进行任何循环。基于此的竞争加密货币以太坊能够拥有智能合约,它具有图灵完备的语言。关于在加密货币中加入图灵完备语言的实用性、必要性和安全性存在很多争论,但我将把争论留给其他人!

在标准术语中,比特币交易由输入和输出组成。输入是一个 UTXO(现在正在使用),输出是新的 UTXO。单个输入可以有多个输出,但输入需要完全用于交易。矿工提出的任何输入的其余部分是采矿费。

对于我玩的这个客户,我希望能够将以前从交易所转移的比特币发送到我的 FEEDB0BDEADBEEF 地址。使用与以前相同的过程,我使用私钥(在填充之前)生成另一个地址 BADCAFEFABC0FFEE。这会产生地址 1QGNXLzGXhWTKF3HTSjuBMQQyUYFkWfgVC。

创建原生事务

创建交易是先将“原生交易”打包,再对原生交易进行签名。同样,文献描述了交易的内容。构成交易的内容如下所示,但首先要注意几点:

为简单起见,一个输出和一个输入的交易如下所示。可以以相同的方式创建具有多个输入和输出的更复杂的事务。

暂时忽略签名脚本和公钥脚本,很容易看出本机交易的其他字段应该包含哪些内容。要将资金从我的 FEEDB0BDEADBEEF 地址发送到我的 BADCAFEFABC0FFEE 地址,我查看了交易所创建的交易。这给了我:

对于我们交易的 Pubkey 脚本,我们使用(或 p2pk)该脚本。该脚本确保只有拥有散列到提供的比特币地址的公钥的人才能使用创建的输出,并且提供的签名由持有公钥对应私钥的人生成。

要解锁已被 p2pk 脚本锁定的交易,用户将提供其公钥和本机交易的哈希签名。对公钥进行哈希处理并与创建脚本的地址进行比较,并验证提供的公钥以进行签名。如果公钥和地址的hash相等,并且签名验证通过,就可以使用输出了。

在比特币脚本操作数中,p2pk 脚本如下所示。

1
2
3
4
5
6

OP_DUP
OP_HASH160


OP_EQUALVERIFY
OP_CHECKSIG

将操作数转换为它们的值(可以在wiki上找到)并输入公共地址(在Base58Check编码之前)给出以下十六进制脚本:

1
2
3
4
5
6

0x76
0xA9
0x14
0xFF33195EC053D6E58D5FD3CC67747D3E1C71B280
0x88
0xAC

为我们发送到 0xBADCAFEFABC0FFEE 的私钥,使用前面显示的代码从私钥导出地址中找到。

签署交易

在 (p2pk) 交易中签署脚本有两种不同但又有些相关的用途:

但是,原生交易包含签名脚本,应该包含原生交易的签名!这个先有鸡还是先有蛋的问题是通过在签署本机交易之前将我们正在使用的 UTXO 的 Pubkey 脚本放入签名脚本槽中来解决的。据我所知,使用 Pubkey 作为占位符似乎没有任何合理的理由,它实际上可能是任意数据。

Hashtype 值也需要在对本机事务进行散列之前附加。最常见的 hashtype 值是 SIGHASH_ALL比特币核心,它对整个结构进行签名,这样就不能修改输入或输出。链接的 wiki 页面列出了其他哈希类型,这些哈希类型可以允许在交易签署后修改输入和输出的组合。

以下函数总结了原始交易值的 Python 字典。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

def get_p2pkh_script(pub_key):
"""
This is the standard 'pay to pubkey hash' script
"""
# OP_DUP then OP_HASH160 then 20 bytes (pub address length)
script = bytes.fromhex("76a914")

# The address to pay to
script += pub_key

# OP_EQUALVERIFY then OP_CHECKSIG
script += bytes.fromhex("88ac")

return script

def get_raw_transaction(from_addr, to_addr, transaction_hash, output_index, satoshis_spend):
"""
Gets a raw transaction for a one input to one output transaction
"""
transaction = {}
transaction["version"] = 1
transaction["num_inputs"] = 1

# transaction byte order should be reversed:
# https://bitcoin.org/en/developer-reference#hash-byte-order
transaction["transaction_hash"] = bytes.fromhex(transaction_hash)[::-1]
transaction["output_index"] = output_index

# temporarily make the signature script the old pubkey script
# this will later be replaced. I'm assuming here that the previous
# pubkey script was a p2pkh script here
transaction["sig_script_length"] = 25
transaction["sig_script"] = get_p2pkh_script(from_addr)

transaction["sequence"] = 0xffffffff
transaction["num_outputs"] = 1
transaction["satoshis"] = satoshis_spend
transaction["pubkey_length"] = 25
transaction["pubkey_script"] = get_p2pkh_script(to_addr)
transaction["lock_time"] = 0
transaction["hash_code_type"] = 1

return transaction

使用以下值调用代码会创建一个我有兴趣进行的本机事务。

1
2
3
4
5
6
7
8
9
10

private_key = address_utils.get_private_key("FEEDB0BDEADBEEF")
public_key = address_utils.get_public_key(private_key)
from_address = address_utils.get_public_address(public_key)
to_address = address_utils.get_public_address(address_utils.get_public_key(address_utils.get_private_key("BADCAFEFABC0FFEE")))

transaction_id = "95855ba9f46c6936d7b5ee6733c81e715ac92199938ce30ac3e1214b8c2cd8d7"
satoshis = 380000
output_index = 1

raw = get_raw_transaction(from_address, to_address, transaction_id, output_index, satoshis)

看到我使用私钥生成 to_address 可能会令人困惑。这只是为了方便,并展示了如何找到 to_address。如果您与其他人进行交易,您是在询问他们的公共地址并转移到该地址,您不需要知道他们的私钥。

为了能够签署并最终将交易传输到网络,本地交易需要被适当地打包。这是在 get_packed_transaction 函数中实现的,我不会在这里复制它,因为它实际上只是更多的 struct 打包代码。如果您有兴趣,可以在我的 Github 存储库中的 bitcoin_transaction_utils.pyPython 文件中找到它。

这允许我定义一个生成签名脚本的函数。签名脚本生成后,应替换占位符签名脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

def get_transaction_signature(transaction, private_key):
"""
Gets the sigscript of a raw transaction
private_key should be in bytes form
"""
packed_raw_transaction = get_packed_transaction(transaction)
hash = hashlib.sha256(hashlib.sha256(packed_raw_transaction).digest()).digest()
public_key = address_utils.get_public_key(private_key)
key = SigningKey.from_string(private_key, curve=SECP256k1)
signature = key.sign_digest(hash, sigencode=util.sigencode_der)
signature += bytes.fromhex("01") #hash code type

sigscript = struct.pack("
sigscript += signature
sigscript += struct.pack("
sigscript += public_key

return sigscript

本质上,签名脚本充当我尝试使用的最后一个交易的公钥脚本。提供输入是为了证明我可以将现在用作输入的输出用作输入。它的工作原理如下所示,它来自比特币维基。从上到下,每一行都是脚本的一个迭代。这是对 pubkey hash pubkey 的付费,如前所述,这是最常见的脚本。这也是我用于我正在创建的交易和我正在交换的交易的脚本。

如果提供的公钥没有散列到脚本中的公钥散列,或者提供的签名与提供的公钥不匹配,那么这个脚本就会失败。这确保只有持有 pubkey 脚本中地址的私钥的人才能使用输出。

您可以看到这是我第一次需要在任何地方提供我的公钥。到目前为止,只有我的公共地址被公布。必须在此处提供公钥,因为它可以验证交易已签署的签名。

使用 get_transaction_signature 函数,我们现在可以对我们的交易进行签名和打包,以备传输!这涉及将占位符签名脚本替换为真实签名脚本,并从交易中删除 hash_code_type,如下所示。

1
2
3
4
5
6
7

signature = get_transaction_signature(raw, private_key )

raw["sig_script_length"] = len(signature)
raw["sig_script"] = signature
del raw["hash_code_type"]

transaction = get_packed_transaction(raw)

发布交易

当交易被打包和签名时,这是告诉网络它的问题。使用本文前面在 bitcoin_p2p_message_utils.py 中定义的一些函数,下面的代码将比特币消息头放在传输器上并将其传输到节点。前面说过,需要先向节点发送一个版本消息,这样节点才能接受后续的消息。

1
2
3
4

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((get_bitcoin_peer(), 8333))
s.send(get_bitcoin_message("version", get_version_payload())
s.send(get_bitcoin_message("tx", transaction

发送交易是工作中最烦人的部分。如果我提交了一个结构不佳或签名不佳的交易,对等方通常会断开连接,或者在稍微好一点的情况下,会发回一条神秘的错误消息。一个这样的(非常烦人的)错误消息是 S 值过高,这是由于使用 sigencode_der 的 ECSDA 编码方法对交易哈希进行签名造成的。尽管签名有效,但很明显,比特币矿工不喜欢 ECSDA 签名的格式允许网络中出现垃圾邮件。解决方案是使用sigencode_der_canonize函数,该函数负责将签名格式化为其他格式。一个简单但非常难以调试的问题!

不管怎样,当我看到我的交易进入区块链时,我终于拿到了,超级兴奋!知道我手工制作的微小交易现在将永远成为比特币分类账的一部分,这是一种巨大的成就感。

当我提交交易时,与中位数相比,我的交易费用实际上非常低(我使用比特币费用网站]() 检查),因此矿工花了大约 5 个小时才决定将其包含在一个区块中我通过查看交易确认的数量来检查这一点——这是衡量交易块有多深的指标。在撰写本文时,这是 190 次确认......这意味着我的交易在区块之后,还有 190 个区块。这可以被认为是非常安全的确认,因为它会对网络进行一次令人印象深刻的攻击,重写 190 个区块以删除我的交易。

结论

我希望您通过阅读这篇文章对比特币的工作原理有所了解,我知道当我花了几个月的时间将它们放在一起时,我做到了!虽然这里提供的大多数信息并不完全适用——您通常只使用一个为您完成所有工作的客户端——我认为更深入地了解事情的运作方式可以让您更好地了解幕后发生的事情发生的事情。并让您更放心地使用该技术。

如果您想仔细阅读代码或了解有关玩具示例的更多信息,请查看我的相关 Github 存储库。比特币世界还有很多进一步探索的空间,我只是真正关注比特币的一个非常常见的用例。除了在两个地址之间传递值之外,还有更酷的利用空间!我也没有提到挖矿,将交易添加到区块链的过程是如何工作的。这是另一个兔子洞。

如果你读过这篇文章,你可能已经意识到我搬到 1QGNXLzGXhWTKF3HTSjuBMpQyUYFkWfgVC 的 380000Satoshi(或 0.0038BTC)可以足够聪明,任何人都可以使用..因为这个地址的私钥存在于本文。我很想知道转移需要多长时间,并希望接受转移的人可以使用我在此处详细介绍的一些技术来实现它!如果你只是将私钥加载到钱包应用程序中,那是相当糟糕的,但我认为我无法阻止你!在撰写本文时,这个金额大约值 10 美元,但如果比特币“登上月球”,谁知道它可能值多少钱! (编辑:它现在已经消失了!这篇文章发布几个小时后,由 1KgoPFVDNcx7H2VY9bB2dxxP9yNM2Nar1N 拍摄。玩得开心!)

如果您正在寻找发送比特币的地址、正在玩这些东西,或者如果您认为这篇文章足够有价值,值得给小费 - 我的地址 18uKa5c9S84tkN1ktuG568CR23vmeU7F5H 很乐意接受任何小额捐款!或者,如果你想对我说错话,我很乐意听到。

更多资源

如果您觉得这篇文章很有趣,请查看其他一些资源:

================================================ ================== ==========

分享一些比特币、以太坊、EOS等区块链相关的互动在线编程教程: