def begin_announcement_phase(self): """Begins the announcement phase.""" sprint(self.name, 'Beginning announcement phase...') self.phase = Constants.ANNOUNCEMENT_PHASE # shuffle list of servers random.shuffle(self.servers) # update servers and neighbors self.servers_ready = 0 self.broadcast_neighbors() # pause before beginning announcement phase while self.servers_ready != self.num_servers: time.sleep(0.01) server_addr = self.servers[0] # get ciphertexts (secret, encrypted reputation) secret, reputation = sendrecv(server_addr, [Constants.GET_CIPHERTEXTS]) clients = [] for server_addr in self.servers: clients.extend(sendrecv(server_addr, [Constants.GET_CLIENTS])) for server_addr in self.servers: sendrecv(server_addr, [Constants.UPDATE_CLIENTS, secret, reputation, clients]) send(self.servers[0], [Constants.NEW_ANNOUNCEMENT, Constants.G, [], [], 0, 0, Constants.INIT_ID])
def lrs_sign(self, msg): """Sign for LRS.""" generator = sendrecv(self.server_addr, [Constants.GET_GENERATOR]) stp_array = sendrecv(self.server_addr, [Constants.GET_STP_ARRAY]) stp = powm(generator, self.pri_key) stp_idx = stp_array.index(stp) # modify stp_array to prevent duplicate voting stp_array.append(msg_hash(msg, sha1)) return lrs.sign(msg, self.pri_key, stp_idx, stp_array, g=generator)
def __init__(self, server_host, server_port, private_key=None): self.name = 'CLIENT' # core variables self.pri_key = randkey() if private_key is None else private_key self.pub_key = powm(Constants.G, self.pri_key) # socket variables self.server_addr = (server_host, server_port) # new client sendrecv(self.server_addr, [Constants.NEW_CLIENT, self.pub_key])
def post(self, msg): """Post a message.""" generator = sendrecv(self.server_addr, [Constants.GET_GENERATOR]) stp = powm(generator, self.pri_key) sig = self.sign(msg, generator) send(self.server_addr, [Constants.NEW_MESSAGE, msg, stp, sig])
def lrs_sign(self, msg): """Sign for LRS.""" ltp_array = sendrecv(self.server_addr, [Constants.GET_LTP_ARRAY]) ltp_idx = ltp_array.index(self.pub_key) # modify stp_array to prevent duplicate voting ltp_array.append(msg_hash(msg, sha1)) return lrs.sign(msg, self.pri_key, ltp_idx, ltp_array)
def vote(self, amount, msg_id): """Vote on a message.""" messages = sendrecv(config.COORDINATOR_ADDR, [Constants.DISP_BOARD]) # verify message id if msg_id < 0 or msg_id >= len(messages): eprint(self.name, 'Invalid message id.') return False msg = messages[msg_id][1][Constants.MSG] sig = self.lrs_sign(msg) response = sendrecv(self.server_addr, [Constants.NEW_FEEDBACK, msg_id, msg, amount, sig]) if response[0] == Constants.FAIL: eprint(self.name, response[1]) return False else: return True
def __init__(self, server_host, server_port): self.contract_address = sendrecv(config.COORDINATOR_ADDR, [Constants.GET_CONTRACT_ADDRESS]) self.blockchain = bc.LocalBlockchain() self.blockchain.connect_to_contract('reputation.sol', self.contract_address) self.wallets = [] self.listening = False self.respond = { Constants.PARTICIPATION_STATUS: self.give_keys, Constants.KEYS: self.get_keys, } self.msg_types = { Constants.PARTICIPATION_STATUS: [int], Constants.KEYS: [list, list], } assert set(self.respond.keys()) == set(self.msg_types.keys()) super().__init__(server_host, server_port)
def get_message_board(self): return sendrecv(config.COORDINATOR_ADDR, [Constants.DISP_BOARD])
if len(sys.argv) != 3: print('USAGE: python client_blockchain.py server_host server_port') sys.exit(1) client_host = sys.argv[1] client_port = int(sys.argv[2]) c = BlockchainClient(client_host, client_port) c.show_help() while True: try: s = input('> ').strip().upper() if s == 'HELP': c.show_help() elif s == 'SHOW': messages = sendrecv(config.COORDINATOR_ADDR, [Constants.DISP_BOARD]) pprint.PrettyPrinter(indent=4).pprint(messages) elif s == 'GET REP': print('Your reputation is: {}'.format( sum( c.blockchain.get_reputation(x.address) for x in c.wallets))) elif re.match("^WRITE \d+$", s) is not None: msg = input('Write message here: ') c.post(msg, int(s.split()[-1])) pass elif re.match("^VOTE UP \d+$", s) is not None: c.vote(1, int(s.split()[-1])) pass elif re.match("^VOTE DOWN \d+$", s) is not None: c.vote(-1, int(s.split()[-1]))
def start_coinshuffle(self): """Begins Coinshuffle phase.""" sprint(self.name, 'Beginning CoinShuffle phase...') # Commits all the changes in reputation to the blockchain. promises = [] for i in range(self.message_marker, len(self.board)): addresses = self.board[i][1][Constants.REP] net_fb = (self.board[i][1][Constants.FB][0] + self.board[i][1][Constants.FB][1]) if net_fb > 0: promises.append( self.blockchain.add_reputation(addresses[0], net_fb)) elif net_fb < 0: to_remove = -net_fb for address in addresses: can_remove = min(to_remove, self.blockchain.get_reputation(address)) promises.append( self.blockchain.remove_reputation(address, can_remove)) to_remove -= can_remove if to_remove <= 0: break for promise in promises: promise.resolve() # reset used_wallets self.used_wallets = set() self.coordinator.phase = Constants.COINSHUFFLE_PHASE # contains a list of (wallet, balance_of_wallet) that need to be transfered # to another wallet self.spending_wallets = [] self.spending_wallets_total = 0 # determine which clients should participate in the coinshuffle final_balances = defaultdict(int) for i in range(self.message_marker, len(self.board)): addr = self.msg_id_to_addr[i] # check if this user has > 0 reputation for wallet in self.board[i][1][Constants.REP]: balance = self.blockchain.get_reputation(wallet) final_balances[addr] += balance if balance > 0: self.spending_wallets.append((wallet, balance)) self.spending_wallets_total += balance # let all clients know whether they are participating in the shuffle or not. participants = [] for addr, balance in final_balances.items(): if balance > 0: encryption_key = sendrecv( addr, [Constants.PARTICIPATION_STATUS, balance]) participants.append((addr, encryption_key)) else: send(addr, [Constants.PARTICIPATION_STATUS, balance]) # iterate over participants and send them the encyption keys that # they need, get ack. e_keys = [] for i, (addr, e_key) in enumerate(reversed(participants)): if i == 0: next_addr = self.coordinator.addr else: next_addr = participants[len(participants) - i][0] # send participants encryption keys next hop in the ring sendrecv(addr, [Constants.KEYS, next_addr, e_keys]) e_keys.append(e_key) # start the shuffling if len(participants) == 0: self.coordinator.phase = Constants.COINSHUFFLE_FINISHED_PHASE return sendbytes(participants[0][0], b'')