From ed52b41464e701947290730d6555f281844b092a Mon Sep 17 00:00:00 2001 From: Dmitri Bogomolov <4glitch@gmail.com> Date: Tue, 20 Jul 2021 20:16:04 +0300 Subject: [PATCH 1/5] Add a test for base58 and use samples everywhere in test_addresses --- src/tests/samples.py | 3 +++ src/tests/test_addresses.py | 30 ++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/tests/samples.py b/src/tests/samples.py index c6cef927..ff2dfa93 100644 --- a/src/tests/samples.py +++ b/src/tests/samples.py @@ -27,5 +27,8 @@ sample_point = ( sample_seed = 'TIGER, tiger, burning bright. In the forests of the night' # Deterministic addresses with stream 1 and versions 3, 4 +sample_deterministic_ripe = b'00cfb69416ae76f68a81c459de4e13460c7d17eb' sample_deterministic_addr3 = 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN' sample_deterministic_addr4 = 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK' +sample_daddr3_512 = 18875720106589866286514488037355423395410802084648916523381 +sample_daddr4_512 = 25152821841976547050350277460563089811513157529113201589004 diff --git a/src/tests/test_addresses.py b/src/tests/test_addresses.py index e37e2854..a706f2f6 100644 --- a/src/tests/test_addresses.py +++ b/src/tests/test_addresses.py @@ -4,7 +4,13 @@ from binascii import unhexlify from pybitmessage import addresses -from .samples import sample_address, sample_ripe +from .samples import ( + sample_address, sample_daddr3_512, sample_daddr4_512, + sample_deterministic_addr4, sample_deterministic_addr3, + sample_deterministic_ripe, sample_ripe) + +sample_addr3 = sample_deterministic_addr3.split('-')[1] +sample_addr4 = sample_deterministic_addr4.split('-')[1] class TestAddresses(unittest.TestCase): @@ -17,19 +23,35 @@ class TestAddresses(unittest.TestCase): ('success', 2, 1, unhexlify(sample_ripe))) status, version, stream, ripe1 = addresses.decodeAddress( - '2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK') + sample_deterministic_addr4) self.assertEqual(status, 'success') self.assertEqual(stream, 1) self.assertEqual(version, 4) - status, version, stream, ripe2 = addresses.decodeAddress( - '2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN') + status, version, stream, ripe2 = addresses.decodeAddress(sample_addr3) self.assertEqual(status, 'success') self.assertEqual(stream, 1) self.assertEqual(version, 3) self.assertEqual(ripe1, ripe2) + self.assertEqual(ripe1, unhexlify(sample_deterministic_ripe)) def test_encode(self): """Encode sample ripe and compare the result to sample address""" self.assertEqual( sample_address, addresses.encodeAddress(2, 1, unhexlify(sample_ripe))) + ripe = unhexlify(sample_deterministic_ripe) + self.assertEqual( + addresses.encodeAddress(3, 1, ripe), + 'BM-%s' % addresses.encodeBase58(sample_daddr3_512)) + + def test_base58(self): + """Check Base58 encoding and decoding""" + self.assertEqual( + addresses.decodeBase58(sample_addr4), sample_daddr4_512) + self.assertEqual( + addresses.decodeBase58(sample_addr3), sample_daddr3_512) + + self.assertEqual( + sample_addr4, addresses.encodeBase58(sample_daddr4_512)) + self.assertEqual( + sample_addr3, addresses.encodeBase58(sample_daddr3_512)) -- 2.45.1 From a94ff1efd3161981b50a8329390109e4923acfe0 Mon Sep 17 00:00:00 2001 From: Dmitri Bogomolov <4glitch@gmail.com> Date: Tue, 20 Jul 2021 21:18:47 +0300 Subject: [PATCH 2/5] New test case for packets data, so far here are the tests for: varint, protocol.encodeHost(), protocol.CreatePacket() - only checks magic --- src/tests/samples.py | 3 ++ src/tests/test_packets.py | 68 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/tests/test_packets.py diff --git a/src/tests/samples.py b/src/tests/samples.py index ff2dfa93..17ec03bd 100644 --- a/src/tests/samples.py +++ b/src/tests/samples.py @@ -3,6 +3,8 @@ from binascii import unhexlify +magic = 0xE9BEB4D9 + # These keys are from addresses test script sample_pubsigningkey = unhexlify( '044a367f049ec16cb6b6118eb734a9962d10b8db59c890cd08f210c43ff08bdf09d' @@ -14,6 +16,7 @@ sample_privsigningkey = \ b'93d0b61371a54b53df143b954035d612f8efa8a3ed1cf842c2186bfd8f876665' sample_privencryptionkey = \ b'4b0b73a54e19b059dc274ab69df095fe699f43b17397bca26fdf40f4d7400a3a' + sample_ripe = b'003cd097eb7f35c87b5dc8b4538c22cb55312a9f' # stream: 1, version: 2 sample_address = 'BM-onkVu1KKL2UaUss5Upg9vXmqd3esTmV79' diff --git a/src/tests/test_packets.py b/src/tests/test_packets.py new file mode 100644 index 00000000..65ee0d44 --- /dev/null +++ b/src/tests/test_packets.py @@ -0,0 +1,68 @@ + +import unittest +from binascii import unhexlify +from struct import pack + +from pybitmessage import addresses, protocol + +from .samples import magic + + +class TestSerialize(unittest.TestCase): + """Test serializing and deserializing packet data""" + + def test_varint(self): + """Test varint encoding and decoding""" + data = addresses.encodeVarint(0) + self.assertEqual(data, b'\x00') + data = addresses.encodeVarint(42) + self.assertEqual(data, b'*') + data = addresses.encodeVarint(252) + self.assertEqual(data, unhexlify('fc')) + data = addresses.encodeVarint(253) + self.assertEqual(data, unhexlify('fd00fd')) + data = addresses.encodeVarint(100500) + self.assertEqual(data, unhexlify('fe00018894')) + data = addresses.encodeVarint(65535) + self.assertEqual(data, unhexlify('fdffff')) + data = addresses.encodeVarint(4294967295) + self.assertEqual(data, unhexlify('feffffffff')) + data = addresses.encodeVarint(4294967296) + self.assertEqual(data, unhexlify('ff0000000100000000')) + data = addresses.encodeVarint(18446744073709551615) + self.assertEqual(data, unhexlify('ffffffffffffffffff')) + + with self.assertRaises(addresses.varintEncodeError): + addresses.encodeVarint(18446744073709551616) + + value, length = addresses.decodeVarint(b'\xfeaddr') + self.assertEqual(value, protocol.OBJECT_ADDR) + self.assertEqual(length, 5) + value, length = addresses.decodeVarint(b'\xfe\x00tor') + self.assertEqual(value, protocol.OBJECT_ONIONPEER) + self.assertEqual(length, 5) + + def test_packet(self): + """Check the packet created by protocol.CreatePacket()""" + head = unhexlify(b'%x' % magic) + self.assertEqual( + protocol.CreatePacket(b'ping')[:len(head)], head) + + def test_encodehost(self): + """Check the result of protocol.encodeHost()""" + self.assertEqual( + protocol.encodeHost('127.0.0.1'), + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + + pack('>L', 2130706433)) + self.assertEqual( + protocol.encodeHost('191.168.1.1'), + unhexlify('00000000000000000000ffffbfa80101')) + self.assertEqual( + protocol.encodeHost('1.1.1.1'), + unhexlify('00000000000000000000ffff01010101')) + self.assertEqual( + protocol.encodeHost('0102:0304:0506:0708:090A:0B0C:0D0E:0F10'), + unhexlify('0102030405060708090a0b0c0d0e0f10')) + self.assertEqual( + protocol.encodeHost('quzwelsuziwqgpt2.onion'), + unhexlify('fd87d87eeb438533622e54ca2d033e7a')) -- 2.45.1 From 8a5d90f2007916dca2475bc2a48a0bda5e9d8c69 Mon Sep 17 00:00:00 2001 From: Dmitri Bogomolov <4glitch@gmail.com> Date: Wed, 21 Jul 2021 20:36:33 +0300 Subject: [PATCH 3/5] protocol: bytes everywhere in CreatePacket and assembleVersionMessage --- src/protocol.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/protocol.py b/src/protocol.py index 2868d828..1934d9cc 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -284,7 +284,7 @@ def isProofOfWorkSufficient( # Packet creation -def CreatePacket(command, payload=''): +def CreatePacket(command, payload=b''): """Construct and return a packet""" payload_length = len(payload) checksum = hashlib.sha512(payload).digest()[0:4] @@ -302,7 +302,7 @@ def assembleVersionMessage( Construct the payload of a version message, return the resulting bytes of running `CreatePacket` on it """ - payload = '' + payload = b'' payload += pack('>L', 3) # protocol version. # bitflags of the services I offer. payload += pack( @@ -337,7 +337,7 @@ def assembleVersionMessage( ) # = 127.0.0.1. This will be ignored by the remote host. # The actual remote connected IP will be used. - payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + pack( + payload += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + pack( '>L', 2130706433) # we have a separate extPort and incoming over clearnet # or outgoing through clearnet @@ -359,7 +359,7 @@ def assembleVersionMessage( payload += nodeid[0:8] else: payload += eightBytesOfRandomDataUsedToDetectConnectionsToSelf - userAgent = '/PyBitmessage:' + softwareVersion + '/' + userAgent = ('/PyBitmessage:%s/' % softwareVersion).encode('utf-8') payload += encodeVarint(len(userAgent)) payload += userAgent @@ -373,7 +373,7 @@ def assembleVersionMessage( if count >= 160000: break - return CreatePacket('version', payload) + return CreatePacket(b'version', payload) def assembleErrorMessage(fatal=0, banTime=0, inventoryVector='', errorText=''): @@ -387,7 +387,7 @@ def assembleErrorMessage(fatal=0, banTime=0, inventoryVector='', errorText=''): payload += inventoryVector payload += encodeVarint(len(errorText)) payload += errorText - return CreatePacket('error', payload) + return CreatePacket(b'error', payload) # Packet decoding -- 2.45.1 From 93c7cfbf63d13b4d735c0d08b69f80c310f3bfac Mon Sep 17 00:00:00 2001 From: Dmitri Bogomolov <4glitch@gmail.com> Date: Wed, 3 Nov 2021 17:14:18 +0200 Subject: [PATCH 4/5] test_base58: added tests for a single character, zero and invalid data --- src/tests/test_addresses.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tests/test_addresses.py b/src/tests/test_addresses.py index a706f2f6..8f9c283d 100644 --- a/src/tests/test_addresses.py +++ b/src/tests/test_addresses.py @@ -46,11 +46,15 @@ class TestAddresses(unittest.TestCase): def test_base58(self): """Check Base58 encoding and decoding""" + self.assertEqual(addresses.decodeBase58('1'), 0) + self.assertEqual(addresses.decodeBase58('!'), 0) self.assertEqual( addresses.decodeBase58(sample_addr4), sample_daddr4_512) self.assertEqual( addresses.decodeBase58(sample_addr3), sample_daddr3_512) + self.assertEqual(addresses.encodeBase58(0), '1') + self.assertEqual(addresses.encodeBase58(-1), None) self.assertEqual( sample_addr4, addresses.encodeBase58(sample_daddr4_512)) self.assertEqual( -- 2.45.1 From b3577a09e5d72170a0a9092e0bfe92bed2f10ba8 Mon Sep 17 00:00:00 2001 From: Dmitri Bogomolov <4glitch@gmail.com> Date: Thu, 4 Nov 2021 15:33:54 +0200 Subject: [PATCH 5/5] Return None from addresses.encodeBase58() for negative number --- src/addresses.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/addresses.py b/src/addresses.py index 560849df..abeeeb49 100644 --- a/src/addresses.py +++ b/src/addresses.py @@ -20,6 +20,8 @@ def encodeBase58(num, alphabet=ALPHABET): num: The number to encode alphabet: The alphabet to use for encoding """ + if num < 0: + return None if num == 0: return alphabet[0] arr = [] -- 2.45.1