commit e606384ed27f25a11ffed1c1fd97fcb5dc1c34f9
parent 91b94f5ddf6ef2610354026602fb7be9eb1ffdcf
Author: nolash <dev@holbrook.no>
Date: Sun, 10 Oct 2021 09:55:15 +0200
Make signer test pass
Diffstat:
5 files changed, 116 insertions(+), 211 deletions(-)
diff --git a/funga/eth/keystore/interface.py b/funga/eth/keystore/interface.py
@@ -4,29 +4,26 @@ import json
import logging
# local imports
-from funga.keystore import Keystore
from funga.eth.keystore import keyfile
from funga.eth.encoding import private_key_from_bytes
+from funga.keystore import Keystore
logg = logging.getLogger(__name__)
-def native_keygen(self):
+def native_keygen(*args, **kwargs):
return os.urandom(32)
class EthKeystore(Keystore):
def __init__(self, private_key_generator=native_keygen):
- super(Keystore, self).__init__(
- private_key_generator=private_key_generator,
- private_key_parser=private_key_from_bytes,
- keystore_parser=keyfile.from_some,
- )
+ super(EthKeystore, self).__init__(private_key_generator, private_key_from_bytes, keyfile.from_some)
def new(self, password=None):
- return self.import_raw_key(b, password)
+ b = self.private_key_generator()
+ return self.import_raw_key(b, password=password)
def import_raw_key(self, b, password=None):
diff --git a/funga/eth/keystore/reference.py b/funga/eth/keystore/reference.py
@@ -1,109 +0,0 @@
-# standard imports
-import logging
-import base64
-
-# external imports
-from cryptography.fernet import Fernet
-#import psycopg2
-#from psycopg2 import sql
-#from psycopg2.extensions import make_dsn
-from sqlalchemy import create_engine, text
-from sqlalchemy.orm import sessionmaker
-import sha3
-from hexathon import (
- strip_0x,
- add_0x,
- )
-
-# local imports
-from .interface import Keystore
-#from . import keyapi
-from crypto_dev_signer.error import UnknownAccountError
-from crypto_dev_signer.encoding import private_key_to_address
-
-logg = logging.getLogger(__name__)
-
-
-def to_bytes(x):
- return x.encode('utf-8')
-
-
-class ReferenceKeystore(Keystore):
-
- schema = [
- """CREATE TABLE IF NOT EXISTS ethereum (
- id SERIAL NOT NULL PRIMARY KEY,
- key_ciphertext VARCHAR(256) NOT NULL,
- wallet_address_hex CHAR(40) NOT NULL
- );
-""",
- """CREATE UNIQUE INDEX IF NOT EXISTS ethereum_address_idx ON ethereum ( wallet_address_hex );
-""",
- ]
-
- def __init__(self, dsn, **kwargs):
- logg.debug('starting db session with dsn {}'.format(dsn))
- self.db_engine = create_engine(dsn)
- self.db_session = sessionmaker(bind=self.db_engine)()
- for s in self.schema:
- self.db_session.execute(s)
- self.db_session.commit()
- self.symmetric_key = kwargs.get('symmetric_key')
-
-
- def __del__(self):
- logg.debug('closing db session')
- self.db_session.close()
-
-
- def get(self, address, password=None):
- safe_address = strip_0x(address).lower()
- s = text('SELECT key_ciphertext FROM ethereum WHERE wallet_address_hex = :a')
- r = self.db_session.execute(s, {
- 'a': safe_address,
- },
- )
- try:
- k = r.first()[0]
- except TypeError:
- self.db_session.rollback()
- raise UnknownAccountError(safe_address)
- self.db_session.commit()
- a = self._decrypt(k, password)
- return a
-
-
- def import_key(self, pk, password=None):
- address_hex = private_key_to_address(pk)
- address_hex_clean = strip_0x(address_hex).lower()
-
- c = self._encrypt(pk.secret, password)
- s = text('INSERT INTO ethereum (wallet_address_hex, key_ciphertext) VALUES (:a, :c)') #%s, %s)')
- self.db_session.execute(s, {
- 'a': address_hex_clean,
- 'c': c.decode('utf-8'),
- },
- )
- self.db_session.commit()
- logg.info('added private key for address {}'.format(address_hex_clean))
- return add_0x(address_hex)
-
-
- def _encrypt(self, private_key, password):
- f = self._generate_encryption_engine(password)
- return f.encrypt(private_key)
-
-
- def _generate_encryption_engine(self, password):
- h = sha3.keccak_256()
- h.update(self.symmetric_key)
- if password != None:
- password_bytes = to_bytes(password)
- h.update(password_bytes)
- g = h.digest()
- return Fernet(base64.b64encode(g))
-
-
- def _decrypt(self, c, password):
- f = self._generate_encryption_engine(password)
- return f.decrypt(c.encode('utf-8'))
diff --git a/funga/eth/keystore/sql.py b/funga/eth/keystore/sql.py
@@ -0,0 +1,108 @@
+# standard imports
+import logging
+import base64
+
+# external imports
+from cryptography.fernet import Fernet
+#import psycopg2
+from sqlalchemy import create_engine, text
+from sqlalchemy.orm import sessionmaker
+import sha3
+from hexathon import (
+ strip_0x,
+ add_0x,
+ )
+
+# local imports
+from .interface import EthKeystore
+#from . import keyapi
+from funga.error import UnknownAccountError
+from funga.eth.encoding import private_key_to_address
+
+logg = logging.getLogger(__name__)
+
+
+def to_bytes(x):
+ return x.encode('utf-8')
+
+
+class SQLKeystore(EthKeystore):
+
+ schema = [
+ """CREATE TABLE IF NOT EXISTS ethereum (
+ id SERIAL NOT NULL PRIMARY KEY,
+ key_ciphertext VARCHAR(256) NOT NULL,
+ wallet_address_hex CHAR(40) NOT NULL
+ );
+""",
+ """CREATE UNIQUE INDEX IF NOT EXISTS ethereum_address_idx ON ethereum ( wallet_address_hex );
+""",
+ ]
+
+ def __init__(self, dsn, **kwargs):
+ super(SQLKeystore, self).__init__()
+ logg.debug('starting db session with dsn {}'.format(dsn))
+ self.db_engine = create_engine(dsn)
+ self.db_session = sessionmaker(bind=self.db_engine)()
+ for s in self.schema:
+ self.db_session.execute(s)
+ self.db_session.commit()
+ self.symmetric_key = kwargs.get('symmetric_key')
+
+
+ def __del__(self):
+ logg.debug('closing db session')
+ self.db_session.close()
+
+
+ def get(self, address, password=None):
+ safe_address = strip_0x(address).lower()
+ s = text('SELECT key_ciphertext FROM ethereum WHERE wallet_address_hex = :a')
+ r = self.db_session.execute(s, {
+ 'a': safe_address,
+ },
+ )
+ try:
+ k = r.first()[0]
+ except TypeError:
+ self.db_session.rollback()
+ raise UnknownAccountError(safe_address)
+ self.db_session.commit()
+ a = self._decrypt(k, password)
+ return a
+
+
+ def import_key(self, pk, password=None):
+ address_hex = private_key_to_address(pk)
+ address_hex_clean = strip_0x(address_hex).lower()
+
+ c = self._encrypt(pk.secret, password)
+ s = text('INSERT INTO ethereum (wallet_address_hex, key_ciphertext) VALUES (:a, :c)') #%s, %s)')
+ self.db_session.execute(s, {
+ 'a': address_hex_clean,
+ 'c': c.decode('utf-8'),
+ },
+ )
+ self.db_session.commit()
+ logg.info('added private key for address {}'.format(address_hex_clean))
+ return add_0x(address_hex)
+
+
+ def _encrypt(self, private_key, password):
+ f = self._generate_encryption_engine(password)
+ return f.encrypt(private_key)
+
+
+ def _generate_encryption_engine(self, password):
+ h = sha3.keccak_256()
+ h.update(self.symmetric_key)
+ if password != None:
+ password_bytes = to_bytes(password)
+ h.update(password_bytes)
+ g = h.digest()
+ return Fernet(base64.b64encode(g))
+
+
+ def _decrypt(self, c, password):
+ f = self._generate_encryption_engine(password)
+ return f.decrypt(c.encode('utf-8'))
diff --git a/tests/test_helper.py b/tests/test_helper.py
@@ -1,91 +0,0 @@
-# standard imports
-import unittest
-import logging
-import os
-
-# local imports
-from crypto_dev_signer.keystore.dict import DictKeystore
-from crypto_dev_signer.eth.signer import ReferenceSigner
-from crypto_dev_signer.helper import TxExecutor
-#from crypto_dev_signer.eth.helper import EthTxExecutor
-from crypto_dev_signer.encoding import to_checksum_address
-
-logging.basicConfig(level=logging.DEBUG)
-logg = logging.getLogger()
-
-script_dir = os.path.realpath(os.path.dirname(__file__))
-
-
-class MockEthTxBackend:
-
- def dispatcher(self, tx):
- logg.debug('sender {}'.format(tx))
- return os.urandom(32)
-
- def reporter(self, tx):
- logg.debug('reporter {}'.format(tx))
-
- def verifier(self, rcpt):
- logg.debug('reporter {}'.format(rcpt))
-
- def fee_price_helper(self):
- return 21
-
- def fee_helper(self, tx):
- logg.debug('fee helper tx {}'.format(tx))
- return 2
-
- def builder(self, tx):
- return tx
-
- def builder_two(self, tx):
- tx['value'] = 10243
- tx['to'] = to_checksum_address('0x' + os.urandom(20).hex())
- tx['data'] = '0x'
- if tx.get('feePrice') != None:
- tx['gasPrice'] = tx['feePrice']
- del tx['feePrice']
- if tx.get('feeUnits') != None:
- tx['gas'] = tx['feeUnits']
- del tx['feeUnits']
- return tx
-
-
-class TestHelper(unittest.TestCase):
-
- def setUp(self):
- logg.debug('setup')
- self.db = DictKeystore()
-
- keystore_filename = 'UTC--2021-01-08T18-37-01.187235289Z--00a329c0648769a73afac7f9381e08fb43dbea72'
- keystore_filepath = os.path.join(script_dir, 'testdata', keystore_filename)
-
- self.address_hex = self.db.import_keystore_file(keystore_filepath, '')
- self.signer = ReferenceSigner(self.db)
-
-
- def tearDown(self):
- pass
-
-
- def test_helper(self):
- backend = MockEthTxBackend()
- executor = TxExecutor(self.address_hex, self.signer, backend.builder, backend.dispatcher, backend.reporter, 666, 13, backend.fee_helper, backend.fee_price_helper, backend.verifier)
-
- tx_ish = {'from': self.address_hex}
- executor.sign_and_send([backend.builder_two])
-
-
-# def test_eth_helper(self):
-# backend = MockEthTxBackend()
-# w3 = web3.Web3(web3.Web3.HTTPProvider('http://localhost:8545'))
-# executor = EthTxExecutor(w3, self.address_hex, self.signer, 1337)
-#
-# tx_ish = {'from': self.address_hex}
-# #executor.sign_and_send([backend.builder, backend.builder_two])
-# with self.assertRaises(ValueError):
-# executor.sign_and_send([backend.builder_two])
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/tests/test_keystore_reference.py b/tests/test_keystore_reference.py
@@ -12,8 +12,8 @@ from psycopg2 import sql
from cryptography.fernet import Fernet, InvalidToken
# local imports
-from crypto_dev_signer.keystore.reference import ReferenceKeystore
-from crypto_dev_signer.error import UnknownAccountError
+from funga.eth.keystore.sql import SQLKeystore
+from funga.error import UnknownAccountError
logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
@@ -37,7 +37,7 @@ class TestDatabase(unittest.TestCase):
kw = {
'symmetric_key': self.symkey,
}
- self.db = ReferenceKeystore('postgres+psycopg2://postgres@localhost:5432/signer_test', **kw)
+ self.db = SQLKeystore('postgres+psycopg2://postgres@localhost:5432/signer_test', **kw)
self.address_hex = self.db.new('foo')
#self.address_hex = add_0x(address_hex)