### ネットワークハンドシェイク
ネットワークハンドシェイクの方法
– AがBに接続するためにversionメッセージを送信
– Bがversionメッセージを受信し、verackメッセージで応答し、自身のversionメッセージを送信
※verackはボディー(ペイロード)が無く、メッセージ名だけのメッセージ
– Aはversionメッセージとverackメッセージを受信し、verackメッセージを送信
– Bはverackメッセージを受信し、通信を継続
ハンドシェイク後に通信できる
不正なトランザクションまたはブロックを送信した場合、通信が禁止または切断される可能性がある
### ネットワークへの接続
import socket from network immport NetworkEnvelop, VersionMessage host = '' port = 18333 socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket.connect((host, port)) stream = socket.makefile('rb', None) version = VersionMessage() envelop = NetworkEnvelop(version.command, version.serialize()) socket.sendall(envelop.serialize()) while True: new_message = NetworkEnvelope.parse(stream) print(new_message)
class VerAckMessage: command = b'verack' def __init__(self): pass @classmethod def parse(cls, s): return cls() def serialize(self): return b''
SimpleNone
class SimpleNone: def __init__(self, host, port=None, testnet=False, logging=False): if port is None: if testnet: port = 18333 else: port = 8333 self.testnet = testnet self.logging = logging self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((host, port)) self.stream = self.socket.makefile('rb', None) def send(self, message): envelope = NetworkEnvelop( message.command, message.serialize(), testnet=self.testnet) if self.logging: print('sending: {}'.format(envelop)) self.socket.sendall(envelope.serialize()) def read(self): envelop = NetworkEnvelop.parse(self.stream, testnet=self.testnet) if self.logging: print('receiving: {}'.format(envelop)) return envelope def wait_for(self, *message_classes): command = None command_to_class = {m.command: m for m in message_classes} while command not in command_to_class.keys(): envelope = self.read() command = envelop.command if command == VersionMessage.command: self.send(VerAckMessage()) elif command == PingMessage.command: self.send(PongMessage(envelope.payload)) return command_to_class[command].parse(envelope.stream())
他のNodeとのハンドシェイク
from network import SimpleNode, VersionMessage node = SimpleNone('', testnet=True) version = VersionMessage() node.send(version) verack_received = False version_received = False while not verack_received and not version_received: message = node.wait_for(VersionMessage, VerArckMessage) if message.command == VerArckMessage.command: verack_received = True else: version_received = True node.sed(VerAckMessage())
handshake
def handshake(self): version = VersionMessage() node.send(version) self.wait_for(VerAckMessage)