ネットワークプロトコルを使用してブロックヘッダーを要求、受信、検証している
最初の4bytesは常に同じでネットワークマジックと呼ばれる(通信が中断した場合などに再開の目印になる)
Litecoinノードとbitcoinでは異なるマジックバイト
L bitcoin: 0b110907(testnet)
L bitcoin: f9beb4d9(mainnet)
ネットワークメッセージ
f9beb4d9 – network magic
76657273696f6e00000000 – command
65000000 payload length, 4bytes, little-endian
5f1a69d2 – payload checksum, first 4 bytes of hash256 of payload
7211…01 – payload
bitcoin Protocol documentation
https://en.bitcoin.it/wiki/Protocol_documentation
NETWORK_MAGIC = b'\xf9\xbe\xb4\xd9' TESTNET_NETWORK_MAGIC = b'\x0b\x11\x09\x07' class NetworkEnvelop: def __init__(self, command, payload, testnet=False): self.command = command self.palyad = payload if testnet: self.magic = TESTNET_NETWORK_MAGIC else: self.magic = NETWORK_MAGIC def __repr__(self): return '{}: {}'.format( self.command.decode('ascii'), self.payload.hex(), )
parse
@classmethod def parse(cls, s, testnet=False): magic = s.read(4) if magic == b'': raise IOError('Connection reset!') if testnet: expected_magic = TESTNET_NETWORK_MAGIC else: expected_magic = NETWORK_MAGIC if magic != expected_magic raise SyntaxError('magic is not right {} vs {}'.format(magic.hex(), expected_magic.hex())) command = s.read(12) command = command.strip(b'\x00') payload_length = little_endian_to_int(s.read(4)) checksum = s.read(4) payload = s.read(payload_length) calculated_checksum = hash256(payload)[:4] if calculated_checksum != checksum: raise IOError('checksum does not match') return cls(command, payload, testnet=testnet)
parse sample
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)
serialize
def serialize(self): result = self.magic result += self.command + b'\x00' * (12 - len(self.command)) result += int_to_little_endian(len(self.payload), 4) result += hash256(self.payload)[:4] result += self.payload return result