class AddressToUrlTestCase(unittest.TestCase): def setUp(self): with open('compiled.evm') as f: compiled = f.read().rstrip() self.c = EthJsonRpc() self.c._call('evm_reset') self.cb = self.c.eth_coinbase() self.contract_addr = self.AddressToUrl(self.cb, compiled) def tearDown(self): pass def test_set(self): url = 'http://www.yahoo.com' self.set_url(self.cb, self.contract_addr, url) result = self.get_url(self.contract_addr, self.cb[2:]) self.assertEqual(url, result) def test_set_clear(self): url = 'http://www.yahoo.com' self.set_url(self.cb, self.contract_addr, url) result = self.get_url(self.contract_addr, self.cb[2:]) self.assertEqual(url, result) self.set_url(self.cb, self.contract_addr, '') result = self.get_url(self.contract_addr, self.cb[2:]) self.assertEqual('', result) def test_get(self): result = self.get_url(self.contract_addr, self.cb[2:]) self.assertEqual('', result) ################################################################################ def AddressToUrl(self, sender, compiled): ''' constructor ''' sig = 'AddressToUrl()' args = [] tx = self.c.create_contract(sender, compiled, 300000, sig, args) return self.c.get_contract_address(tx) def set_url(self, sender, contract_addr, ip): sig = 'set_url(string)' args = [ip] self.c.call_with_transaction(sender, contract_addr, sig, args) def get_url(self, contract_addr, addr): sig = 'get_url(address)' args = [addr] result_types = ['string'] return self.c.call(contract_addr, sig, args, result_types)[0]
class Ipv4TestCase(unittest.TestCase): def setUp(self): with open('compiled.evm') as f: compiled = f.read().rstrip() self.c = EthJsonRpc() self.c._call('evm_reset') self.cb = self.c.eth_coinbase() self.contract_addr = self.AddressToIPv4(self.cb, compiled) def tearDown(self): pass ################################################################################ def test_read(self): result = self.get_ip(self.contract_addr, self.cb[2:]) unchained_ip = self.ip_from_chain(result) self.assertEqual('0.0.0.0', unchained_ip) def test_set_read(self): ip = u'192.168.1.1' chained_ip = self.ip_to_chain(ip) self.set_ip(self.cb, self.contract_addr, chained_ip) result = self.get_ip(self.contract_addr, self.cb[2:]) unchained_ip = self.ip_from_chain(result) self.assertEqual(ip, unchained_ip) def test_set_delete_read(self): ip = u'192.168.1.1' chained_ip = self.ip_to_chain(ip) self.set_ip(self.cb, self.contract_addr, chained_ip) self.delete_ip(self.cb, self.contract_addr) result = self.get_ip(self.contract_addr, self.cb[2:]) unchained_ip = self.ip_from_chain(result) self.assertEqual('0.0.0.0', unchained_ip) ################################################################################ def ip_to_chain(self, ip): return int(IPv4Address(ip)) def ip_from_chain(self, ip): return str(IPv4Address(ip)) ################################################################################ def AddressToIPv4(self, sender, compiled): ''' constructor ''' sig = 'AddressToIPv4()' args = [] tx = self.c.create_contract(sender, compiled, sig, args) return self.c.get_contract_address(tx) def set_ip(self, sender, contract_addr, ip): sig = 'set_ip(uint32)' args = [ip] self.c.call_with_transaction(sender, contract_addr, sig, args) def delete_ip(self, sender, contract_addr): sig = 'delete_ip()' args = [] self.c.call_with_transaction(sender, contract_addr, sig, args) def get_ip(self, contract_addr, addr): sig = 'get_ip(address)' args = [addr] result_types = ['uint32'] return self.c.call(contract_addr, sig, args, result_types)[0]
class LiteIDContract: def __init__(self, ip='127.0.0.1', port=8545, contract_id=None): self.connection = EthJsonRpc(ip, port) self.contract_id = contract_id self.abi_def = [{ "constant": False, "inputs": [], "name": "dumpSaltedHashArray", "outputs": [{ "name": "Hashes", "type": "bytes32[]" }, { "name": "Salts", "type": "bytes32[]" }, { "name": "Timestamps", "type": "uint256[]" }], "payable": False, "type": "function" }, { "constant": False, "inputs": [{ "name": "Hash", "type": "bytes32" }, { "name": "Salt", "type": "bytes32" }], "name": "addHash", "outputs": [], "payable": False, "type": "function" }, { "inputs": [{ "name": "Hash", "type": "bytes32" }, { "name": "Salt", "type": "bytes32" }], "payable": False, "type": "constructor" }] @staticmethod def _calculate_hash(data_to_hash): salt = SHA256.new() salt.update(bytes(random.getrandbits(256))) original_hash = SHA256.new() original_hash.update(data_to_hash) salted_hash = SHA256.new() salted_hash.update(original_hash.digest() + salt.digest()) salt = salt.hexdigest().decode("hex") original_hash = original_hash.hexdigest().decode("hex") salted_hash = salted_hash.hexdigest().decode("hex") return salted_hash, salt, original_hash, data_to_hash def unlock_account(self, account, password): self.connection._call('personal_unlockAccount', params=[account, password, 36000]) def add_hash(self, data): if self.contract_id is None: raise IOError salted_hash, salt, original_hash, _ = self._calculate_hash(data) tx = self.connection.call_with_transaction( self.connection.eth_coinbase(), self.contract_id, 'addHash(bytes32,bytes32)', [salted_hash, salt]) print("Waiting for addHash to be mined") while self.connection.eth_getTransactionReceipt(tx) is None: time.sleep(1) return original_hash def create_contract(self, data): if not hasattr(self, 'byte_code'): contract_file = open(__file__[:-11] + '\LiteID-Contract.sol') code_data = self.connection.eth_compileSolidity( contract_file.read()) self.byte_code = code_data['ID']['code'] self.abi_def = code_data['ID']['info']['abiDefinition'] salted_hash, salt, original_hash, _ = self._calculate_hash(data) tx_id = self.connection.create_contract(self.connection.eth_coinbase(), self.byte_code, 300000, sig='addHash(bytes32,bytes32)', args=[salted_hash, salt]) print("Waiting for contract to be mined") while self.connection.eth_getTransactionReceipt(tx_id) is None: time.sleep(1) self.contract_id = self.connection.eth_getTransactionReceipt( tx_id)['contractAddress'] return self.contract_id def dump_hashes(self): return_types = list() for item in self.abi_def: try: if item['name'] == 'dumpSaltedHashArray': for i in item['outputs']: return_types.append(i['type']) except KeyError: pass return_types = ['bytes32[]', 'bytes32[]', 'uint256[]'] return self.connection.call(self.contract_id, 'dumpSaltedHashArray()', [], return_types)