def __init__(self, *args, **kwargs): super(TestCoin, self).__init__(*args, **kwargs) self.network = testNetwork() self.ec_keys = [random_sk() for _ in range(10)] self.public_keys = [make_fake_public_key(secret_key=sk) for sk in self.ec_keys] self.addresses = [address_from_public_key(public_key) for public_key in self.public_keys] for address in self.addresses: for value in [10000, 1000, 500, 100]: self.network.add_coin(address, value, tx_hash = fake_hash(address, value)) self.coin = Coin(self.network)
def start_protocol(self): coin = Coin(self.network) crypto = Crypto() self.messages.clear_packets() begin_phase = Phase('Announcement') # Make Round self.protocol = Round_wrong_outputs( coin, crypto, self.messages, self.outcome, self.income, self.logger, self.session, begin_phase, self.amount , self.fee, self.sk, self.vk, self.players, self.addr_new, self.change) self.executionThread = threading.Thread(target = self.protocol.protocol_loop) self.executionThread.start() self.done.wait() self.executionThread.join()
def test_002_insufficient_funds(self): from electroncash_plugins.shuffle.coin import Coin coin = Coin(self.network) protocolThreads = self.make_clients_threads(with_print = True) coins_1 = coin.get_coins(protocolThreads[0].inputs) for pubkey in coins_1: bad_addr = public_key_to_p2pkh(bytes.fromhex(pubkey)) for coin in coins_1[pubkey]: coin['value'] = 0 self.network.coins[bad_addr] = coins_1[pubkey] self.start_protocols(protocolThreads) done = False while not done: completes = [self.is_protocol_complete(p) for p in protocolThreads[1:]] done = all(completes) self.stop_protocols(protocolThreads) tx = protocolThreads[1].protocol.tx.raw for pThread in protocolThreads[2:]: self.assertEqual(tx, pThread.protocol.tx.raw) print(protocolThreads[-1].protocol.tx.raw) print(protocolThreads[-1].protocol.change_addresses)
password = args.password wallet_path = args.wallet storage = WalletStorage(wallet_path) if not storage.file_exists(): basic_logger.send("Error: Wallet file not found.") sys.exit(0) if storage.is_encrypted(): storage.decrypt(password) if args.testnet: NetworkConstants.set_testnet() config = SimpleConfig({'server': "bch0.kister.net:51002:s"}) network = Network(config) network.start() wallet = Wallet(storage) wallet.start_threads(network) coin = Coin(network) # # setup server port = args.port host = args.server stat_port = args.stat_port ssl = args.ssl fee = args.fee secured = ("s" if ssl else "") stat_endpoint = "http{}://{}:{}/stats".format(secured, host, stat_port) schedule.every(args.period).minutes.do(job) while True: schedule.run_pending() sleep(10) ## Delete later
class TestCoin(unittest.TestCase): def __init__(self, *args, **kwargs): super(TestCoin, self).__init__(*args, **kwargs) self.network = testNetwork() self.ec_keys = [random_sk() for _ in range(10)] self.public_keys = [make_fake_public_key(secret_key=sk) for sk in self.ec_keys] self.addresses = [address_from_public_key(public_key) for public_key in self.public_keys] for address in self.addresses: for value in [10000, 1000, 500, 100]: self.network.add_coin(address, value, tx_hash = fake_hash(address, value)) self.coin = Coin(self.network) def test_001_sufficient_funds(self): pubkey_1, pubkey_2, pubkey_3 = self.public_keys[0:3] address_1, address_2, address_3 = self.addresses[0:3] address_x = "111111111111111111111111111" inputs = { pubkey_1:[ fake_hash(address_1, 1000) + ":0", fake_hash(address_1, 100) + ":0" ], pubkey_2:[ fake_hash(address_2, 1000) + ":0"] } self.assertTrue(self.coin.check_inputs_for_sufficient_funds(inputs, 2022)) self.assertFalse(self.coin.check_inputs_for_sufficient_funds(inputs, 20022)) bad_hash_input = {Hash("pubkey_1").hex():["a1h4"]} self.assertIsNone(self.coin.check_inputs_for_sufficient_funds(bad_hash_input, 2222)) bad_address_input = {Hash("pubkey_111").hex():["a111h1"]} self.assertIsNone(self.coin.check_inputs_for_sufficient_funds(bad_address_input, 2222)) def test_002_get_coins(self): pubkey_1, pubkey_2, pubkey_3 = self.public_keys[0:3] address_1, address_2, address_3 = self.addresses[0:3] inputs = { pubkey_1:[ fake_hash(address_1, 1000)+":0", fake_hash(address_1, 100)+":0" ], pubkey_2:[fake_hash(address_2, 1000)+":0"] } coins = self.coin.get_coins(inputs) self.assertEquals(coins[pubkey_1][0]["value"], 1000) self.assertEquals(coins[pubkey_1][0]["tx_hash"], fake_hash(address_1, 1000)) self.assertEquals(coins[pubkey_1][1]["value"], 100) self.assertEquals(coins[pubkey_1][1]["tx_hash"], fake_hash(address_1, 100)) self.assertEquals(coins[pubkey_2][0]["value"], 1000) self.assertEquals(coins[pubkey_2][0]["tx_hash"], fake_hash(address_2, 1000)) bad_input = { pubkey_1:[fake_hash(address_2, 2222)] } coins = self.coin.get_coins(bad_input) self.assertIsNone(coins) def test_003_make_unsigned_transaction(self): fee = 50 amount = 1000 pubkey_1, pubkey_2, pubkey_3, pubkey_4 = self.public_keys[0:4] address_1, address_2, address_3, address_4 = self.addresses[0:4] inputs = { "player_1_vk": { pubkey_1:[ fake_hash(address_1, 500) + ":0", fake_hash(address_1, 100) + ":0", ], pubkey_2:[ fake_hash(address_2, 500) + ":0", ] }, "player_2_vk": { pubkey_3:[ fake_hash(address_3, 1000) + ":0" , fake_hash(address_3, 100) + ":0", ] }, "player_3_vk": { pubkey_4:[ fake_hash(address_4, 10000)+ ":0", ] } } outputs = [make_fake_address() for _ in range(3)] changes = { player:make_fake_address() for player in ["player_1_vk", "player_2_vk", "player_3_vk"]} transaction = self.coin.make_unsigned_transaction(amount, fee, inputs, outputs, changes) flat_inputs = [ {"public_key": pubkey_1, "address": address_1, "tx_hash": inputs["player_1_vk"][pubkey_1][0].split(":")[0], "value": 500}, {"public_key": pubkey_1, "address": address_1, "tx_hash": inputs["player_1_vk"][pubkey_1][1].split(":")[0], "value": 100}, {"public_key": pubkey_2, "address": address_2, "tx_hash": inputs["player_1_vk"][pubkey_2][0].split(":")[0], "value": 500}, {"public_key": pubkey_3, "address": address_3, "tx_hash": inputs["player_2_vk"][pubkey_3][0].split(":")[0], "value": 1000}, {"public_key": pubkey_3, "address": address_3, "tx_hash": inputs["player_2_vk"][pubkey_3][1].split(":")[0], "value": 100}, {"public_key": pubkey_4, "address": address_4, "tx_hash": inputs["player_3_vk"][pubkey_4][0].split(":")[0], "value": 10000}, ] flat_inputs.sort(key=lambda x:x["tx_hash"]) for i, input in enumerate(transaction.inputs()): self.assertEquals(input['value'], flat_inputs[i]['value']) self.assertEquals(input['tx_hash'], flat_inputs[i]['tx_hash']) self.assertEquals(input['pubkeys'][0], flat_inputs[i]['public_key']) self.assertEquals(input['address'].to_string(Address.FMT_LEGACY), flat_inputs[i]['address']) amounts = {"player_1_vk":1100, "player_2_vk":1100, "player_3_vk":10000 } flat_changes = [(changes[player], amounts[player]) for player in sorted(changes)] flat_outputs = [ (0, Address.from_string(outputs[0]), amount), (0, Address.from_string(outputs[1]), amount), (0, Address.from_string(outputs[2]), amount), (0, Address.from_string(flat_changes[0][0]), flat_changes[0][1] - amount -fee), (0, Address.from_string(flat_changes[1][0]), flat_changes[1][1] - amount -fee), (0, Address.from_string(flat_changes[2][0]), flat_changes[2][1] - amount - fee) ] self.assertEquals(transaction.outputs(), flat_outputs) def test_004_all_about_signatures(self): fee = 50 amount = 1000 sk_1, sk_2, sk_3, sk_4 = self.ec_keys[0:4] pubkey_1, pubkey_2, pubkey_3, pubkey_4 = self.public_keys[0:4] address_1, address_2, address_3, address_4 = self.addresses[0:4] inputs_vk_1 = { pubkey_1:[ fake_hash(address_1, 500)+":0", fake_hash(address_1, 100)+":0", ], pubkey_2:[ fake_hash(address_2, 500)+":0", ] } inputs_vk_2 = { pubkey_3:[ fake_hash(address_3, 1000)+":0", fake_hash(address_3, 100)+":0", ] } inputs_vk_3 = { pubkey_4:[ fake_hash(address_4, 10000)+":0", ] } inputs = { "player_1_vk": inputs_vk_1, "player_2_vk": inputs_vk_2, "player_3_vk": inputs_vk_3 } outputs = [make_fake_address() for _ in range(3)] changes = { player:make_fake_address() for player in ["player_1_vk", "player_2_vk", "player_3_vk"]} transaction = self.coin.make_unsigned_transaction(amount, fee, inputs, outputs, changes) secret_keys_vk_1 = {pubkey_1:sk_1, pubkey_2: sk_2} secret_keys_vk_2 = {pubkey_3:sk_3} secret_keys_vk_3 = {pubkey_4:sk_4} signatures = {} signatures.update(self.coin.get_transaction_signature(transaction, inputs_vk_1, secret_keys_vk_1)) signatures.update(self.coin.get_transaction_signature(transaction, inputs_vk_2, secret_keys_vk_2)) signatures.update(self.coin.get_transaction_signature(transaction, inputs_vk_3, secret_keys_vk_3)) for player in inputs: for pubkey in inputs[player]: for tx_hash in inputs[player][pubkey]: signature = signatures[tx_hash] self.assertTrue(self.coin.verify_tx_signature(signature , transaction, pubkey, tx_hash)) self.coin.add_transaction_signatures(transaction, signatures) def test_005_verigy_signatures(self): message = b"some_message_for_test" sk_1 = random_sk() pubkey_1 = sk_1.get_public_key(True) signature_1 = sk_1.sign_message(message, True) self.assertTrue(self.coin.verify_signature(signature_1, message, pubkey_1)) sk_2 = random_sk() pubkey_2 = sk_2.get_public_key(False) signature_2 = sk_2.sign_message(message, False) self.assertTrue(self.coin.verify_signature(signature_2, message, pubkey_2)) self.assertFalse(self.coin.verify_signature(signature_2, message, pubkey_1))
class TestRound(unittest.TestCase): def __init__(self, *args, **kwargs): super(TestRound, self).__init__(*args, **kwargs) self.network = testNetwork() self.ec_keys = [random_sk() for _ in range(10)] self.public_keys = [ make_fake_public_key(secret_key=sk) for sk in self.ec_keys ] self.addresses = [ address_from_public_key(public_key) for public_key in self.public_keys ] for address in self.addresses: for value in [10000, 1000, 500, 100]: self.network.add_coin(address, value, tx_hash=fake_hash(address, value)) self.coin = Coin(self.network) def setUp(self): self.number_of_players = 5 self.crypto = Crypto() self.messages = Messages() self.outchan = Channel() self.inchan = Channel() self.logchan = Channel() self.session = b"session" self.phase = Phase('Announcement') self.amount = 1000 self.fee = 50 self.secret_keys = [random_sk() for _ in range(self.number_of_players)] self.verification_keys = [ make_fake_public_key(secret_key=sk) for sk in self.secret_keys ] self.players = { index + 1: vk for index, vk in enumerate(self.verification_keys) } self.inputs = { self.verification_keys[0]: { self.public_keys[0]: [ fake_hash(self.addresses[0], 500) + ":0", fake_hash(self.addresses[0], 100) + ":0" ], self.public_keys[1]: [fake_hash(self.addresses[1], 500) + ":0"] }, self.verification_keys[1]: { self.public_keys[2]: [ fake_hash(self.addresses[2], 1000) + ":0", fake_hash(self.addresses[2], 100) + ":0" ], }, self.verification_keys[2]: { self.public_keys[3]: [fake_hash(self.addresses[3], 1000) + ":0"], self.public_keys[4]: [fake_hash(self.addresses[4], 100) + ":0"], }, self.verification_keys[3]: { self.public_keys[5]: [fake_hash(self.addresses[5], 10000) + ":0"], }, self.verification_keys[4]: { self.public_keys[6]: [fake_hash(self.addresses[6], 1000) + ":0"], self.public_keys[7]: [fake_hash(self.addresses[7], 500) + ":0"] } } self.sks = { self.public_keys[0]: self.ec_keys[0], self.public_keys[1]: self.ec_keys[1], } self.all_sks = { self.verification_keys[0]: { self.public_keys[0]: self.ec_keys[0], self.public_keys[1]: self.ec_keys[1] }, self.verification_keys[1]: { self.public_keys[2]: self.ec_keys[2], }, self.verification_keys[2]: { self.public_keys[3]: self.ec_keys[3], self.public_keys[4]: self.ec_keys[4], }, self.verification_keys[3]: { self.public_keys[5]: self.ec_keys[5], }, self.verification_keys[4]: { self.public_keys[6]: self.ec_keys[6], self.public_keys[7]: self.ec_keys[7] } } self.sk = self.secret_keys[0] self.verification_key = self.verification_keys[0] self.new_addresses = [ make_fake_address() for _ in range(self.number_of_players) ] self.changes = { vk: make_fake_address() for vk in self.verification_keys } self.addr_new = self.new_addresses[0] self.change = make_fake_address() self.round = Round(self.coin, self.crypto, self.messages, self.inchan, self.outchan, self.logchan, self.session, self.phase, self.amount, self.fee, self.sk, self.sks, self.inputs, self.verification_key, self.players, self.addr_new, self.change) def test_001_test_init(self): self.assertEquals(self.round.number_of_players, self.number_of_players) self.assertEquals(self.round.me, 1) def test_002_blame_insufficient_funds(self): self.assertTrue(self.round.blame_insufficient_funds()) self.assertEquals(self.logchan.get(), "Player 1 finds sufficient funds") self.round.inputs[self.round.players[1]][ self.public_keys[1]][0] = fake_hash(self.addresses[1], 100) + ":0" self.assertFalse(self.round.blame_insufficient_funds()) self.assertEquals(self.logchan.get(), "Blame: insufficient funds of player 1") self.assertIsNotNone(self.outchan.get(timeout=0)) def test_0021_blame_insufficient_funds_network_fail(self): self.round.coin.network = None self.assertIsNone(self.round.blame_insufficient_funds()) self.assertEquals(self.logchan.get(), "Error: blockchain network fault!") def test_003_process_equivocation_check(self): # SetUp self.round.new_addresses = self.new_addresses self.round.changes = self.changes self.round.encryption_keys = { player: "encryption_key" for player in self.round.players.values() } computed_hash = self.crypto.hash( str(self.round.new_addresses) + str([ self.round.encryption_keys[self.round.players[i]] for i in sorted(self.round.players) ])) # Wrong phase ignored self.round.phase = 'Announcement' self.round.process_equivocation_check() self.assertTrue(self.outchan.empty()) self.assertTrue(self.logchan.empty()) # Set Proper phase # Check if incomplete inbox ignored self.round.phase = 'EquivocationCheck' self.round.inbox[self.messages.phases[self.round.phase]] = { self.round.players[1]: "something" } self.round.process_equivocation_check() self.assertTrue(self.outchan.empty()) self.assertTrue(self.logchan.empty()) # check processing with inbox completed # making the fake messages with equal hashes and fulfill inbox with it self.messages.clear_packets() self.messages.add_hash(computed_hash) message = self.messages.packets.SerializeToString() self.round.inbox[self.messages.phases[self.round.phase]] = { player: message for player in self.round.players.values() } self.round.process_equivocation_check() self.assertEquals(self.round.phase, "VerificationAndSubmission") self.assertTrue(self.logchan.get(timeout=0), "Player 1 reaches phase 5") self.assertTrue(self.logchan.get(timeout=0), "Player 1 send transction signatures") self.assertTrue(self.logchan.empty()) self.assertIsNotNone(self.round.transaction) self.messages.packets.ParseFromString(self.outchan.get(timeout=0)) self.assertTrue(self.outchan.empty()) signatures = self.messages.get_signatures() for pubkey in self.round.inputs[self.round.vk]: for hash in self.round.inputs[self.round.vk][pubkey]: self.assertIn(hash, signatures) # Checking the blame behaviour self.round.phase = 'EquivocationCheck' self.messages.clear_packets() self.messages.add_hash(computed_hash + b"fail") message = self.messages.packets.SerializeToString() self.round.inbox[self.messages.phases[self.round.phase]][ self.round.vk] = message self.round.process_equivocation_check() self.assertEquals(self.round.phase, "Blame") self.assertEquals(self.logchan.get(timeout=0), "Player 1 found bad hash from 1") self.assertEquals(self.logchan.get(timeout=0), "Blame: wrong hash computed by player 1") self.assertTrue(self.logchan.empty()) self.messages.packets.ParseFromString(self.outchan.get(timeout=0)) self.assertEquals( self.messages.get_blame_reason(), self.messages.blame_reason("EQUIVOCATIONFAILURE") ) # This should be replaced with allias for the reason instread of 2. def test_004_process_verification_and_submission(self): self.round.phase = 'VerificationAndSubmission' # Check if nothing is happend with incomplete inbox self.round.inbox[self.messages.phases[self.round.phase]] = { self.round.players[1]: "something" } self.round.process_verification_and_submission() self.assertTrue(self.outchan.empty()) self.assertTrue(self.logchan.empty()) # Check normal case transaction = self.coin.make_unsigned_transaction( self.amount, self.fee, self.inputs, self.new_addresses, self.changes) self.round.transaction = transaction signatures = { player: self.coin.get_transaction_signature(transaction, self.inputs[player], self.all_sks[player]) for player in self.round.players.values() } transaction = self.coin.make_unsigned_transaction( self.amount, self.fee, self.inputs, self.new_addresses, self.changes) for player in signatures: self.messages.clear_packets() self.messages.add_signatures(signatures[player]) self.round.inbox[self.messages.phases[self.round.phase]][ player] = self.messages.packets.SerializeToString() self.round.process_verification_and_submission() self.assertIsNotNone(self.round.tx) self.assertTrue(self.round.done) self.assertEquals(self.logchan.get(timeout=0), "Player 1 got transction signatures") self.assertEquals(self.logchan.get(timeout=0), "Player 1 done") self.assertEquals(self.logchan.get(timeout=0), "Player 1 complete protocol") self.assertTrue(self.logchan.empty()) self.assertTrue(self.outchan.empty()) # Abnormal case self.round.done = False self.round.tx = None transaction = self.coin.make_unsigned_transaction( self.amount, self.fee, self.inputs, self.new_addresses, self.changes) signatures = { player: self.coin.get_transaction_signature(transaction, self.inputs[player], self.all_sks[player]) for player in self.round.players.values() } signatures[self.round.vk][self.inputs[self.round.vk][ self.public_keys[0]][0]] = signatures[self.round.vk][self.inputs[ self.round.vk][self.public_keys[0]][1]] for player in signatures: self.messages.clear_packets() self.messages.add_signatures(signatures[player]) self.round.inbox[self.messages.phases[self.round.phase]][ player] = self.messages.packets.SerializeToString() self.round.transaction = self.coin.make_unsigned_transaction( self.amount, self.fee, self.inputs, self.new_addresses, self.changes) self.round.process_verification_and_submission() self.assertEquals(self.logchan.get(timeout=0), "Player 1 got transction signatures") self.assertEquals(self.logchan.get(timeout=0), "Blame: wrong transaction signature from player 1") self.assertTrue(self.logchan.empty()) self.messages.packets.ParseFromString(self.outchan.get(timeout=0)) self.assertEquals(self.messages.get_blame_reason(), self.messages.blame_reason("Invalid Signature"))