| 115 | |
| 116 | |
| 117 | class VersionMessage: |
| 118 | command = b'version' |
| 119 | |
| 120 | def __init__(self, version=70015, services=0, timestamp=None, |
| 121 | receiver_services=0, |
| 122 | receiver_ip=b'\x00\x00\x00\x00', receiver_port=8333, |
| 123 | sender_services=0, |
| 124 | sender_ip=b'\x00\x00\x00\x00', sender_port=8333, |
| 125 | nonce=None, user_agent=b'/programmingbitcoin:0.1/', |
| 126 | latest_block=0, relay=False): |
| 127 | self.version = version |
| 128 | self.services = services |
| 129 | if timestamp is None: |
| 130 | self.timestamp = int(time.time()) |
| 131 | else: |
| 132 | self.timestamp = timestamp |
| 133 | self.receiver_services = receiver_services |
| 134 | self.receiver_ip = receiver_ip |
| 135 | self.receiver_port = receiver_port |
| 136 | self.sender_services = sender_services |
| 137 | self.sender_ip = sender_ip |
| 138 | self.sender_port = sender_port |
| 139 | if nonce is None: |
| 140 | self.nonce = int_to_little_endian(randint(0, 2**64), 8) |
| 141 | else: |
| 142 | self.nonce = nonce |
| 143 | self.user_agent = user_agent |
| 144 | self.latest_block = latest_block |
| 145 | self.relay = relay |
| 146 | |
| 147 | def serialize(self): |
| 148 | '''Serialize this message to send over the network''' |
| 149 | # version is 4 bytes little endian |
| 150 | result = int_to_little_endian(self.version, 4) |
| 151 | # services is 8 bytes little endian |
| 152 | result += int_to_little_endian(self.services, 8) |
| 153 | # timestamp is 8 bytes little endian |
| 154 | result += int_to_little_endian(self.timestamp, 8) |
| 155 | # receiver services is 8 bytes little endian |
| 156 | result += int_to_little_endian(self.receiver_services, 8) |
| 157 | # IPV4 is 10 00 bytes and 2 ff bytes then receiver ip |
| 158 | result += b'\x00' * 10 + b'\xff\xff' + self.receiver_ip |
| 159 | # receiver port is 2 bytes, big endian |
| 160 | result += self.receiver_port.to_bytes(2, 'big') |
| 161 | # sender services is 8 bytes little endian |
| 162 | result += int_to_little_endian(self.sender_services, 8) |
| 163 | # IPV4 is 10 00 bytes and 2 ff bytes then sender ip |
| 164 | result += b'\x00' * 10 + b'\xff\xff' + self.sender_ip |
| 165 | # sender port is 2 bytes, big endian |
| 166 | result += self.sender_port.to_bytes(2, 'big') |
| 167 | # nonce should be 8 bytes |
| 168 | result += self.nonce |
| 169 | # useragent is a variable string, so varint first |
| 170 | result += encode_varint(len(self.user_agent)) |
| 171 | result += self.user_agent |
| 172 | # latest block is 4 bytes little endian |
| 173 | result += int_to_little_endian(self.latest_block, 4) |
| 174 | # relay is 00 if false, 01 if true |
no outgoing calls