def connect(): peers = Peers() if peers.get_peers_count() < peers.MAX_PEERS: api_client = ApiClient(peers) body = request.json host = body['host'] network = body['network'] if network == config['network'] and api_client.ping_status(host): peers.add_peer(host) response.status = 202 return json.dumps({'success': True}) response.status = 403 return json.dumps({'success': False})
def full(): helptext = ''' Available commands: =================== balance <public key (optional)> history <public key (optional)> getnodes getblock <index (optional)> getblocks <start index (optional)> <stop index (optional)> mempoolcount getmempool getunconfirmedtx <tx hash> mine <start | stop> quit or exit ''' peers = Peers() api_client = ApiClient(peers) blockchain = Blockchain() mempool = Mempool() validator = Validator() ip = config['user']['ip'] public_key = config['user']['public_key'] if ip is None or public_key is None: print("\n\npublic key and IP must be provided.\n\n") sys.exit(1) else: print("\n\nfull node starting...\n\n") full_node = FullNode(peers, api_client, blockchain, mempool, validator) full_node.start() miner = Miner(blockchain, mempool) mining = False while True: cmd = input("{} ({}) full node > ".format( config['network']['name'], config['network']['ticker_symbol'])) cmd_split = cmd.split() try: if cmd_split[0] == "balance": if len(cmd_split) == 2: url = full_node.BALANCE_URL.format( "localhost", full_node.FULL_NODE_PORT, cmd_split[1]) else: url = full_node.BALANCE_URL.format( "localhost", full_node.FULL_NODE_PORT, public_key) response = requests.get(url) print(response.json()) elif cmd_split[0] == "history": if len(cmd_split) == 2: url = full_node.TRANSACTION_HISTORY_URL.format( "localhost", full_node.FULL_NODE_PORT, cmd_split[1]) response = requests.get(url) else: url = full_node.TRANSACTION_HISTORY_URL.format( "localhost", full_node.FULL_NODE_PORT, public_key) response = requests.get(url) print(response.json()) elif cmd_split[0] == "getnodes": url = full_node.NODES_URL.format("localhost", full_node.FULL_NODE_PORT) response = requests.get(url) print(response.json()) elif cmd_split[0] == "getblock": if len(cmd_split) == 2: url = full_node.BLOCKS_URL.format("localhost", full_node.FULL_NODE_PORT, cmd_split[1]) else: url = full_node.BLOCKS_URL.format("localhost", full_node.FULL_NODE_PORT, "latest") response = requests.get(url) print(response.json()) elif cmd_split[0] == "getblocks": if len(cmd_split) == 3: url = full_node.BLOCKS_INV_URL.format( "localhost", full_node.FULL_NODE_PORT, cmd_split[1], cmd_split[2]) else: url = full_node.BLOCKS_URL.format("localhost", full_node.FULL_NODE_PORT, "") response = requests.get(url) print(response.json()) elif cmd_split[0] == "mempoolcount": url = full_node.UNCONFIRMED_TRANSACTIONS_URL.format( "localhost", full_node.FULL_NODE_PORT, "count") response = requests.get(url) print(response.json()) elif cmd_split[0] == "getmempool": url = full_node.UNCONFIRMED_TRANSACTIONS_URL.format( "localhost", full_node.FULL_NODE_PORT, "") response = requests.get(url) print(response.json()) elif cmd_split[0] == "getunconfirmedtx": if len(cmd_split) == 2: url = full_node.UNCONFIRMED_TRANSACTIONS_URL.format( "localhost", full_node.FULL_NODE_PORT, cmd_split[1]) response = requests.get(url) print(response.json()) else: print("\nRequires tx hash\n") elif cmd_split[0] == "mine": if len(cmd_split) == 2: if cmd_split[1] == "start": if mining is False: print("\n\nminer starting...\n\n") mining = True miner.start() elif cmd_split[1] == "stop": if mining is True: print("\n\nminer shutting down...\n\n") mining = False miner.shutdown() else: print("\nRequires: start | stop") else: print("\nRequires: start | stop") elif cmd_split[0] in ("quit", "exit"): if mining is True: print("\n\nminer shutting down...\n\n") miner.shutdown() time.sleep(2) full_node.shutdown() time.sleep(2) sys.exit(0) else: # help print(helptext) except IndexError: pass
def client(): helptext = ''' Available commands: =================== balance <public key (optional)> send <destination> <amount> <fee> publickey privatekey history <public key (optional)> quit or exit ''' peers = Peers() api_client = ApiClient(peers) encrypted = config['user']['encrypted_private_key'] if encrypted is None: print( "\n\nNo private key provided. A new wallet will be generated for you...\n\n" ) wallet = Client(peers, api_client) else: passphrase = getpass("Enter passphrase: ") encrypted = codecs.decode(encrypted, 'hex') nonce = encrypted[0:16] tag = encrypted[16:32] ciphertext = encrypted[32:] hashedpass = hashlib.sha256(passphrase.encode('utf-8')).digest() cipher = AES.new(hashedpass, AES.MODE_EAX, nonce) try: private_key = cipher.decrypt_and_verify(ciphertext, tag) wallet = Client(peers, api_client, private_key) except ValueError as ve: logger.warn('Invalid passphrase') print("\n\nInvalid passphrase\n\n") sys.exit(1) while True: cmd = input("{} ({}) wallet > ".format( config['network']['name'], config['network']['ticker_symbol'])) cmd_split = cmd.split() try: if cmd_split[0] == "balance": if len(cmd_split) == 2: print(wallet.get_balance(cmd_split[1])) else: print(wallet.get_balance()) elif cmd_split[0] == "send": if len(cmd_split) == 4: print( wallet.create_transaction(cmd_split[1], float(cmd_split[2]), float(cmd_split[3]))) else: print("\nRequires destination, amount, fee\n") elif cmd_split[0] == "publickey": print(wallet.get_public_key()) elif cmd_split[0] == "privatekey": print(wallet.get_private_key()) elif cmd_split[0] == "history": if len(cmd_split) == 2: print(wallet.get_transaction_history(cmd_split[1])) else: print(wallet.get_transaction_history()) elif cmd_split[0] in ("quit", "exit"): sys.exit(0) else: # help print(helptext) except IndexError: pass
def setUp(self): self.mock_peers = Mock(Peers) self.subject = ApiClient(self.mock_peers) self.node = "1.2.3.4" self.port = 30013
class TestApiClient(TestCase): def setUp(self): self.mock_peers = Mock(Peers) self.subject = ApiClient(self.mock_peers) self.node = "1.2.3.4" self.port = 30013 def test_request_nodes_Returns_nodes(self): mock_response = Mock() mock_response.status_code = 200 mock_response.json.return_value = self.mock_peers with patch.object(requests, 'get', return_value=mock_response) as patched_requests: response = self.subject.request_nodes(self.node, self.port) self.assertEqual(response, self.mock_peers) def test_request_nodes_When_status_code_not_200_Returns_none(self): mock_response = Mock() mock_response.status_code = 400 mock_response.json.return_value = self.mock_peers with patch.object(requests, 'get', return_value=mock_response) as patched_requests: response = self.subject.request_nodes(self.node, self.port) self.assertIsNone(response) def test_ping_status_Returns_status(self): mock_response = Mock() mock_response.status_code = 200 mock_response.json.return_value = config['network'] with patch.object(requests, 'get', return_value=mock_response) as patched_requests: response = self.subject.ping_status(self.node) self.assertTrue(response) def test_ping_status_When_config_mismatch_Returns_false(self): mock_response = Mock() mock_response.status_code = 200 mock_response.json.return_value = dict() with patch.object(requests, 'get', return_value=mock_response) as patched_requests: response = self.subject.ping_status(self.node) self.assertFalse(response) def test_request_height_Returns_height(self): mock_response = Mock() mock_response.status_code = 200 mock_response.json.return_value = {'height': 125} with patch.object(requests, 'get', return_value=mock_response) as patched_requests: response = self.subject.request_height(self.node) self.assertEqual(response, 125) def test_request_height_When_status_code_not_200_Returns_none(self): mock_response = Mock() mock_response.status_code = 400 mock_response.json.return_value = {'height': 125} with patch.object(requests, 'get', return_value=mock_response) as patched_requests: response = self.subject.request_height(self.node) self.assertIsNone(response) @skip def test_broadcast_transaction(self): # TODO: Not testing this until implementation of a better broadcast pattern pass @skip def test_check_peers_light(self): # TODO: Not testing this until implementation of a better broadcast pattern pass @skip def test_check_peers_full(self): # TODO: Not testing this until implementation of a better broadcast pattern pass def test_get_balance_Returns_balance(self): mock_response = Mock() mock_response.status_code = 200 mock_response.json.return_value = 12500 with patch.object(requests, 'get', return_value=mock_response) as patched_requests: response = self.subject.get_balance(self.node) self.assertEqual(response, 12500)