《区块链编程》第十章

《区块链编程》第十章

比特币通信网络

练习1

p168

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-15 10:46:13
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-15 11:18:29


class NetworkEnvelope:
...
@classmethod
def parse(cls, s, testnet=False):
    '''Takes a stream and creates a NetworkEnvelope'''
    # check the network magic
    magic = s.read(4)
    if magic == b'':
        raise RuntimeError('Connection reset!')
    if testnet:
        expected_magic = TESTNET_NETWORK_MAGIC
    else:
        expected_magic = NETWORK_MAGIC
    if magic != expected_magic:
        raise RuntimeError('magic is not right {} vs {}' /
                           .format(magic.hex(), expected_magic.hex()))
    # command 12 bytes
    command = s.read(12)
    # strip the trailing 0's
    command = command.strip(b'\x00')
    # payload length 4 bytes, little endian
    payload_length = little_endian_to_int(s.read(4))
    # checksum 4 bytes, first four of hash256 of payload
    checksum = s.read(4)
    # payload is of length payload_length
    payload = s.read(payload_length)
    calculated_checksum = hash256(payload)[:4]
    # verify checksum
    if calculated_checksum != checksum:
        raise IOError('checksum dose not match')
    # return an instance of the class
    return cls(command, payload, testnet=testnet)

测试

练习2

p168

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-15 11:18:08
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-15 11:20:12
from network import NetworkEnvelope
from io import BytesIO
message_hex = 'f9beb4d976657261636b000000000000000000005df6e0e2'
stream = BytesIO(bytes.fromhex(message_hex))
envelope = NetworkEnvelope.parse(stream)
print(envelope.command)
print(envelope.payload)
        

测试

b'verack'
b''
[Finished in 365ms]

练习3

p168

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-15 11:23:57
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-15 11:23:57
class NetworkEnvelope:
...
    def serialize(self):
        '''Returns the byte serialization of the entire network message'''
        # add the network magic
        result = self.magic
        # command 12 bytes
        # fill with 0's
        result += self.command + b'\x00' * (12 - len(self.command))
        # payload length 4 bytes, little endian
        result += int_to_little_endian(len(self.payload), 4)
        # checksum 4 bytes, first four of hash256 of payload
        result += hash256(self.payload)[:4]
        # payload
        result += self.payload
        return result
        

测试

练习4

p169

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-15 11:27:40
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-15 11:27:40
class VersionMessage:
...
    def serialize(self):
        '''Serialize this message to send over the network'''
        # version is 4 bytes little endian
        result = int_to_little_endian(self.version, 4)
        # services is 8 bytes little endian
        result += int_to_little_endian(self.services, 8)
        # timestamp is 8 bytes little endian
        result += int_to_little_endian(self.timestamp, 8)
        # receiver services is 8 bytes little endian
        result += int_to_little_endian(self.receiver_services, 8)
        # IPV4 is 10 00 bytes and 2 ff bytes then receiver ip
        result += b'\x00' * 10 + b'\xff\xff' + self.receiver_ip
        # receiver port is 2 bytes, big endian
        result += int_to_little_endian(self.receiver_port, 2)
        # sender services is 8 bytes little endian
        result += int_to_little_endian(self.sender_services, 8)
        # IPV4 is 10 00 bytes and 2 ff bytes then sender ip
        result += b'\x00' * 10 + b'\xff\xff' + self.sender_ip
        # sender port is 2 bytes, big endian
        result += int_to_little_endian(self.sender_port, 2)
        # nonce should be 8 bytes
        result += self.nonce
        # useragent is a variable string, so varint first
        result += encode_varint(len(self.user_agent))
        result += self.user_agent
        # latest block is 4 bytes little endian
        result += int_to_little_endian(self.latest_block, 4)
        # relay is 00 if false, 01 if true
        if self.relay:
            result += b'\x01'
        else:
            result += b'\x00'
        return result

运行结果

练习5

p172

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-15 11:36:28
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-15 11:36:28
class SimpleNode:
...
    def handshake(self):
        '''Do a handshake with the other node.
        Handshake is sending a version message and getting a verack back.'''
        # create a version message
        version = VersionMessage()
        # send the command
        self.send(version)
        # wait for a verack message
        self.wait_for(VerAckMessage)

运行结果

练习6

p174

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-15 11:37:20
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-15 11:37:20
class GetHeadersMessage:
...
    def serialize(self):
        '''Serialize this message to send over the network'''
        # protocol version is 4 bytes little-endian
        result = int_to_little_endian(self.version, 4)
        # number of hashes is a varint
        result += encode_varint(self.num_hashes)
        # start block is in little-endian
        result += self.start_block[::-1]
        # end block is also in little-endian
        result += self.end_block[::-1]
        return result

运行结果

おすすめ

転載: blog.csdn.net/qq_42182429/article/details/122507483
おすすめ