### ネットワークハンドシェイク
ネットワークハンドシェイクの方法
– 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)