def validate (db, source, move, random, rps_match_id): problems = [] rps_match = None if not isinstance(move, int): problems.append('move must be a integer') return None, None, problems if not all(c in string.hexdigits for c in random): problems.append('random must be an hexadecimal string') return None, None, problems random_bytes = binascii.unhexlify(random) if len(random_bytes) != 16: problems.append('random must be 16 bytes in hexadecimal format') return None, None, problems cursor = db.cursor() rps_matches = list(cursor.execute('''SELECT * FROM rps_matches WHERE id = ?''', (rps_match_id,))) cursor.close() if len(rps_matches) == 0: problems.append('no such rps match') return None, rps_match, problems elif len(rps_matches) > 1: assert False rps_match = rps_matches[0] if move<1: problems.append('move must be greater than 0') elif move > rps_match['possible_moves']: problems.append('move must be lower than {}'.format(rps_match['possible_moves'])) if source not in [rps_match['tx0_address'], rps_match['tx1_address']]: problems.append('invalid source address') return None, rps_match, problems if rps_match['tx0_address'] == source: txn = 0 rps_match_status = ['pending', 'pending and resolved'] else: txn = 1 rps_match_status = ['pending', 'resolved and pending'] move_random_hash = util.dhash(random_bytes + int(move).to_bytes(2, byteorder='big')) move_random_hash = binascii.hexlify(move_random_hash).decode('utf-8') if rps_match['tx{}_move_random_hash'.format(txn)] != move_random_hash: problems.append('invalid move or random value') return txn, rps_match, problems if rps_match['status'] == 'expired': problems.append('rps match expired') elif rps_match['status'].startswith('concluded'): problems.append('rps match concluded') elif rps_match['status'].startswith('invalid'): problems.append('rps match invalid') elif rps_match['status'] not in rps_match_status: problems.append('rps already resolved') return txn, rps_match, problems
def base58_check_decode(s, version): """Decode from base58.""" # Convert the string to an integer n = 0 for c in s: n *= 58 if c not in b58_digits: raise Base58Error('Not a valid Base58 character: ‘{}’'.format(c)) digit = b58_digits.index(c) n += digit # Convert the integer to bytes h = '%x' % n if len(h) % 2: h = '0' + h res = binascii.unhexlify(h.encode('utf8')) # Add padding back. pad = 0 for c in s[:-1]: if c == b58_digits[0]: pad += 1 else: break k = version * pad + res addrbyte, data, chk0 = k[0:1], k[1:-4], k[-4:] if addrbyte != version: raise VersionByteError('incorrect version byte') chk1 = util.dhash(addrbyte + data)[:4] if chk0 != chk1: raise Base58ChecksumError('Checksum mismatch: 0x{} ≠ 0x{}'.format(util.hexlify(chk0), util.hexlify(chk1))) return data
def base58_check_encode(original, version): """Check if base58 encoding is valid.""" b = binascii.unhexlify(bytes(original, 'utf-8')) d = version + b binary = d + util.dhash(d)[:4] res = base58_encode(binary) # Encode leading zeros as base58 zeros czero = 0 pad = 0 for c in d: if c == czero: pad += 1 else: break address = b58_digits[0] * pad + res if original != util.hexlify(base58_check_decode(address, version)): raise AddressError('encoded address does not decode properly') return address
def generate_move_random_hash(move): move = int(move).to_bytes(2, byteorder='big') random_bin = os.urandom(16) move_random_hash_bin = dhash(random_bin + move) return binascii.hexlify(random_bin).decode('utf8'), binascii.hexlify(move_random_hash_bin).decode('utf8')