ネットワークプロトコルを使用してブロックヘッダーを要求、受信、検証している
最初の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