def valid_metamask_message(address, message, signature): #address = attrs['address'] #message = attrs['msg'] #signature = attrs['signed_msg'] r = int(signature[0:66], 16) s = int(add_0x_prefix(signature[66:130]), 16) v = int(add_0x_prefix(signature[130:132]), 16) if v not in (27, 28): v += 27 message_hash = defunct_hash_message(text=message) pubkey = ecrecover_to_pub(decode_hex(message_hash.hex()), v, r, s) signer_address = encode_hex(sha3(pubkey)[-20:]) if signer_address != address.lower(): raise ValidationError({'result': 'Incorrect signature'}, code=400) return True
def test_add_0x_prefix_rejects_non_text_types(value): with pytest.raises(TypeError): add_0x_prefix(value)
def test_add_0x_prefix(value, expected): actual = add_0x_prefix(value) assert actual == expected
def post(self): """ Handle POST request """ if not self.request.body: log.warning('Missing body') self.set_status(400) self.write_json({ 'success': False, 'clicks': None, 'token': '', }) return req = json.loads(self.request.body) token = req.get('token') recipient = req.get('recipient') contract = req.get('contract') invalids = [] if not is_valid_token(token): invalids.append('token') if not recipient or not is_address(recipient): invalids.append('recipient') if not contract or not is_address(contract): invalids.append('contract') recipient = Web3.toChecksumAddress(recipient) contract = Web3.toChecksumAddress(contract) if len(invalids) > 0: log.warning('Invalid input: {}'.format(', '.join(invalids))) self.set_status(400) self.write_json({ 'success': False, 'clicks': None, 'token': '', 'message': 'Invalid input' }) return # Verify it exists clicks = rgetint(self.redis, token, 0) if not clicks: log.warning('Token has no clicks') self.write_json({ 'success': False, 'clicks': None, 'token': token, 'message': 'Try clicking first' }) return log.info('create_claim({}, {}, {}, {})'.format(recipient, add_0x_prefix(token), clicks * int(1e18), contract)) # Assemble claim claim = create_claim(recipient, add_0x_prefix(token), clicks * int(1e18), contract) prefixed_claim_hash = defunct_hash_message(claim) # Docstring for this function sugests this does not prefix messages, so # we're prefixing above signed = self.accounts.eth_account.signHash( prefixed_claim_hash, self.signer_account_privkey) self.write_json({ 'success': True, 'clicks': clicks, 'token': token, 'claim': claim.hex(), 'signature': signed.signature.hex(), 'contract': contract, })