1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| import time import rlp import secrets from eth_hash.auto import keccak from eth_keys import KeyAPI from eth_keys.datatypes import PrivateKey
class BasicPacket: private_key = None public_key = None packet = None packet_header = None packet_data = None hash = None signature = None packet_type = None expiration = int(time.time())
def __init__(self): self.private_key = PrivateKey(secrets.token_bytes(32)) self.public_key = self.private_key.public_key self.signature = KeyAPI().ecdsa_sign( keccak(b"".join((self.packet_type, self.packet_data))), self.private_key ).to_bytes() self.hash = keccak(b"".join((self.signature, self.packet_type, self.packet_data))) self.packet_header = b"".join((self.hash, self.signature, self.packet_type)) self.packet = b"".join((self.packet_header, self.packet_data))
def to_bytes(self): return b"".join((self.packet_header, self.packet_data))
@classmethod def unpack(cls, packet): if len(packet) < 98: return False, "packet长度不足" raw_hash = packet[:32] new_hash = keccak(packet[32:]) if raw_hash != new_hash: return False, "packet hash校验失败" packet_type = packet[97] if packet_type == 1: return True, "Ping Packet" elif packet_type == 2: return True, "Pong Packet" elif packet_type == 3: return True, "FindNode Packet" elif packet_type == 4: return True, "Neighbors Packet" else: return False, "类型无法解析"
class PingPacket(BasicPacket): packet_type = b'\x01' sender_ip = None sender_port = None recipient_ip = None recipient_port = None version = 4
def __init__(self, sender_ip='localhost', sender_port=30303, recipient_ip='localhost', recipient_port=30303): self.sender_ip = sender_ip self.sender_port = sender_port self.recipient_ip = recipient_ip self.recipient_port = recipient_port sender = [self.sender_ip, self.sender_port, 0] recipient = [self.recipient_ip, self.recipient_port, 0] before_packet_data = [self.version, sender, recipient, self.expiration] self.packet_data = rlp.encode(before_packet_data) super().__init__()
class PongPacket(BasicPacket): packet_type = b'\x02' recipient_ip = None recipient_port = None ping_hash = None
def __init__(self, ping_hash, recipient_ip='localhost', recipient_port=30303): self.recipient_ip = recipient_ip self.recipient_port = recipient_port self.ping_hash = ping_hash recipient = [self.recipient_ip, self.recipient_port, 0] before_packet_data = [recipient, self.expiration] self.packet_data = rlp.encode(before_packet_data) super().__init__()
class FindNodePacket(BasicPacket): packet_type = b'\x03' target = None
def __init__(self, target): self.target = target before_packet_data = [self.target, self.expiration] self.packet_data = rlp.encode(before_packet_data) super().__init__()
class NeighborsPacket(BasicPacket): packet_type = b'\x04' nodes = None
def __init__(self, nodes=None): if nodes is None: nodes = [] before_packet_data = [self.nodes, self.expiration] self.packet_data = rlp.encode(before_packet_data) super().__init__()
|