Initial commit
This commit is contained in:
commit
fafef39943
5
src/common.py
Normal file
5
src/common.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
def strip_hex_prefix(hx):
|
||||||
|
if hx[:2] == '0x':
|
||||||
|
return hx[2:]
|
||||||
|
return hx
|
||||||
|
|
1
src/signer/__init__.py
Normal file
1
src/signer/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from signer.defaultsigner import ReferenceSigner, Signer
|
39
src/signer/defaultsigner.py
Normal file
39
src/signer/defaultsigner.py
Normal file
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
42
src/transaction.py
Normal file
42
src/transaction.py
Normal file
@ -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)
|
64
test/sign.py
Normal file
64
test/sign.py
Normal file
@ -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()
|
Loading…
Reference in New Issue
Block a user