commit fafef39943f896c5895327df1814d76f8f38a6a0
Author: nolash <dev@holbrook.no>
Date: Tue, 4 Aug 2020 23:41:31 +0200
Initial commit
Diffstat:
5 files changed, 151 insertions(+), 0 deletions(-)
diff --git a/src/common.py b/src/common.py
@@ -0,0 +1,5 @@
+def strip_hex_prefix(hx):
+ if hx[:2] == '0x':
+ return hx[2:]
+ return hx
+
diff --git a/src/signer/__init__.py b/src/signer/__init__.py
@@ -0,0 +1 @@
+from signer.defaultsigner import ReferenceSigner, Signer
diff --git a/src/signer/defaultsigner.py b/src/signer/defaultsigner.py
@@ -0,0 +1,39 @@
+import logging
+import sha3
+
+from eth_keys import KeyAPI
+from eth_keys.backends import NativeECCBackend
+
+keys = KeyAPI(NativeECCBackend)
+logg = logging.getLogger(__name__)
+
+
+class Signer:
+
+ def __init__(self, keyGetter):
+ self.keyGetter = keyGetter
+
+ def signTransaction(self, tx):
+ raise NotImplementedError
+
+
+class ReferenceSigner(Signer):
+
+ def __init__(self, keyGetter):
+ super(ReferenceSigner, self).__init__(keyGetter)
+
+
+ def signTransaction(self, tx):
+ s = tx.serialize()
+ h = sha3.keccak_256()
+ h.update(s)
+ g = h.digest()
+ k = keys.PrivateKey(self.keyGetter(tx.sender))
+ z = keys.ecdsa_sign(message_hash=g, private_key=k)
+ tx.v = (tx.v * 2) + 35 + z[64]
+ tx.r = z[:32]
+ tx.s = z[32:64]
+ return z
+
+
+
diff --git a/src/transaction.py b/src/transaction.py
@@ -0,0 +1,42 @@
+import logging
+import binascii
+
+from rlp import encode as rlp_encode
+
+from common import strip_hex_prefix
+
+logg = logging.getLogger(__name__)
+
+class Transaction:
+
+ def __init__(self, tx, nonce, chainId=1):
+
+ to = binascii.unhexlify(strip_hex_prefix(tx['to']))
+ data = binascii.unhexlify(strip_hex_prefix(tx['data']))
+
+ self.nonce = nonce
+ self.gas_price = int(tx['gasPrice'])
+ self.start_gas = int(tx['gas'])
+ self.to = to
+ self.value = int(tx['value'])
+ self.data = data
+ self.v = chainId
+ self.r = 0
+ self.s = 0
+ self.sender = tx['from']
+
+
+ def serialize(self):
+ b = self.nonce.to_bytes(8, byteorder='little')
+ s = [
+ self.nonce,
+ self.gas_price,
+ self.start_gas,
+ self.to,
+ self.value,
+ self.data,
+ self.v,
+ self.r,
+ self.s,
+ ]
+ return rlp_encode(s)
diff --git a/test/sign.py b/test/sign.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+
+import unittest
+import logging
+
+from rlp import encode as rlp_encode
+
+from signer import ReferenceSigner
+from transaction import Transaction
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+
+tx = {
+ 'from': "0xEB014f8c8B418Db6b45774c326A0E64C78914dC0",
+ 'gasPrice': "20000000000",
+ 'gas': "22000",
+ 'to': '0x3535353535353535353535353535353535353535',
+ 'value': "1000",
+ 'data': "deadbeef",
+}
+
+class TestSign(unittest.TestCase):
+
+ pk = None
+ nonce = -1
+
+
+ def getPk(self, address):
+ return self.pk
+
+
+ def getNonce(self):
+ self.nonce += 1
+ return self.nonce
+
+
+ def setUp(self):
+ #self.pk = b'abcdefghijklmnopqrstuvwxyz012345' #random.sample(range(256), k=32)
+ self.pk = bytes.fromhex('5087503f0a9cc35b38665955eb830c63f778453dd11b8fa5bd04bc41fd2cc6d6')
+
+
+ def tearDown(self):
+ logg.info('teardown empty')
+
+
+
+ def test_serialize_transaction(self):
+ t = Transaction(tx, 0)
+ self.assertRegex(t.__class__.__name__, "Transaction")
+ logg.debug('{}'.format(rlp_encode(t.serialize())))
+
+
+ def test_sign_transaction(self):
+ t = Transaction(tx, 461, 8995)
+ s = ReferenceSigner(self.getPk)
+ z = s.signTransaction(t)
+ logg.debug('{}'.format(z.to_bytes()))
+ logg.debug('{}'.format(t.serialize().hex()))
+
+
+if __name__ == '__main__':
+ unittest.main()