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')