funga/crypto_dev_signer/eth/signer/defaultsigner.py

85 lines
2.5 KiB
Python
Raw Normal View History

2021-03-17 15:34:51 +01:00
# standard imports
2020-08-04 23:41:31 +02:00
import logging
2021-03-17 15:34:51 +01:00
# external imports
import sha3
import coincurve
2020-08-04 23:41:31 +02:00
logg = logging.getLogger().getChild(__name__)
2020-08-04 23:41:31 +02:00
class Signer:
2020-08-05 18:14:25 +02:00
2020-08-04 23:41:31 +02:00
def __init__(self, keyGetter):
self.keyGetter = keyGetter
2020-08-05 18:14:25 +02:00
def sign_transaction(self, tx, password=None):
return NotImplementedError
2020-08-04 23:41:31 +02:00
2020-08-05 18:14:25 +02:00
2020-08-04 23:41:31 +02:00
class ReferenceSigner(Signer):
2020-08-05 18:14:25 +02:00
2020-08-04 23:41:31 +02:00
def __init__(self, keyGetter):
super(ReferenceSigner, self).__init__(keyGetter)
def sign_transaction(self, tx, password=None):
s = tx.rlp_serialize()
2020-08-04 23:41:31 +02:00
h = sha3.keccak_256()
h.update(s)
2021-03-17 15:34:51 +01:00
message_to_sign = h.digest()
z = self.sign(tx.sender, message_to_sign, password)
2021-01-12 14:50:52 +01:00
vnum = int.from_bytes(tx.v, 'big')
v = (vnum * 2) + 35 + z[64]
byts = ((v.bit_length()-1)/8)+1
tx.v = v.to_bytes(int(byts), 'big')
2020-08-04 23:41:31 +02:00
tx.r = z[:32]
tx.s = z[32:64]
for i in range(len(tx.r)):
if tx.r[i] > 0:
tx.r = tx.r[i:]
break
for i in range(len(tx.s)):
if tx.s[i] > 0:
tx.s = tx.s[i:]
break
2020-08-04 23:41:31 +02:00
return z
2020-12-19 08:47:21 +01:00
def sign_ethereum_message(self, address, message, password=None):
2021-03-17 15:34:51 +01:00
#k = keys.PrivateKey(self.keyGetter.get(address, password))
2020-12-19 08:47:21 +01:00
#z = keys.ecdsa_sign(message_hash=g, private_key=k)
if type(message).__name__ == 'str':
logg.debug('signing message in "str" format: {}'.format(message))
2021-03-17 15:34:51 +01:00
#z = k.sign_msg(bytes.fromhex(message))
message = bytes.fromhex(message)
elif type(message).__name__ == 'bytes':
logg.debug('signing message in "bytes" format: {}'.format(message.hex()))
2021-03-17 15:34:51 +01:00
#z = k.sign_msg(message)
else:
2021-03-17 15:34:51 +01:00
logg.debug('unhandled format {}'.format(type(message).__name__))
raise ValueError('message must be type str or bytes, received {}'.format(type(message).__name__))
2021-03-17 15:34:51 +01:00
ethereumed_message_header = b'\x19' + 'Ethereum Signed Message:\n{}'.format(len(message)).encode('utf-8')
h = sha3.keccak_256()
h.update(ethereumed_message_header + message)
message_to_sign = h.digest()
z = self.sign(address, message_to_sign, password)
2020-12-19 08:47:21 +01:00
return z
2021-03-17 15:34:51 +01:00
# TODO: generic sign should be moved to non-eth context
2021-03-17 15:34:51 +01:00
def sign(self, address, message, password=None):
pk = coincurve.PrivateKey(secret=self.keyGetter.get(address, password))
2021-03-17 17:09:42 +01:00
z = pk.sign_recoverable(hasher=None, message=message)
2021-03-17 15:34:51 +01:00
return z