funga

Signer and keystore daemon and library for cryptocurrency software development
Log | Files | Refs | README | LICENSE

commit 646dbf5f79ab75e1318ae312d032732988c3ad57
parent 4df619f072d87096cca866e70edcfdc50d2056bb
Author: nolash <dev@holbrook.no>
Date:   Sat,  8 Aug 2020 11:33:15 +0200

Fix setup.py to include all modules

Diffstat:
Acrypto_dev_signer/__init__.py | 4++++
Rsrc/common.py -> crypto_dev_signer/common.py | 0
Acrypto_dev_signer/eth/__init__.py | 0
Acrypto_dev_signer/eth/signer/__init__.py | 1+
Rsrc/signer/defaultsigner.py -> crypto_dev_signer/eth/signer/defaultsigner.py | 0
Acrypto_dev_signer/eth/transaction.py | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acrypto_dev_signer/eth/web3ext/__init__.py | 29+++++++++++++++++++++++++++++
Rsrc/web3ext/middleware.py -> crypto_dev_signer/eth/web3ext/middleware.py | 0
Acrypto_dev_signer/keystore/__init__.py | 1+
Rsrc/keystore/interface.py -> crypto_dev_signer/keystore/interface.py | 0
Acrypto_dev_signer/keystore/postgres.py | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Tscripts/crypto-dev-daemon | 0
Tscripts/crypto-dev-daemon.py | 0
Msetup.py | 12+++++++++---
Dsrc/keystore/__init__.py | 1-
Dsrc/keystore/postgres.py | 95-------------------------------------------------------------------------------
Dsrc/signer/__init__.py | 1-
Dsrc/transaction.py | 68--------------------------------------------------------------------
Dsrc/web3ext/__init__.py | 29-----------------------------
Mtest/test_keystore.py | 2+-
Mtest/test_sign.py | 4++--
21 files changed, 210 insertions(+), 200 deletions(-)

diff --git a/crypto_dev_signer/__init__.py b/crypto_dev_signer/__init__.py @@ -0,0 +1,4 @@ +import crypto_dev_signer.eth.signer +import crypto_dev_signer.eth.web3ext +import crypto_dev_signer.eth.transaction +import crypto_dev_signer.common diff --git a/src/common.py b/crypto_dev_signer/common.py diff --git a/crypto_dev_signer/eth/__init__.py b/crypto_dev_signer/eth/__init__.py diff --git a/crypto_dev_signer/eth/signer/__init__.py b/crypto_dev_signer/eth/signer/__init__.py @@ -0,0 +1 @@ +from crypto_dev_signer.eth.signer.defaultsigner import ReferenceSigner, Signer diff --git a/src/signer/defaultsigner.py b/crypto_dev_signer/eth/signer/defaultsigner.py diff --git a/crypto_dev_signer/eth/transaction.py b/crypto_dev_signer/eth/transaction.py @@ -0,0 +1,68 @@ +# standard imports +import logging +import binascii + +# third-party imports +from rlp import encode as rlp_encode + +# local imports +from crypto_dev_signer.common import strip_hex_prefix, add_hex_prefix + +logg = logging.getLogger(__name__) + + +class Transaction: + + def rlp_serialize(self): + raise NotImplementedError + + def serialize(self): + raise NotImplementedError + + +class EIP155Transaction: + + 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 = b'' + self.s = b'' + self.sender = strip_hex_prefix(tx['from']) + + + def rlp_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) + + def serialize(self): + return { + 'nonce': add_hex_prefix(hex(self.nonce)), + 'gasPrice': add_hex_prefix(hex(self.gas_price)), + 'gas': add_hex_prefix(hex(self.start_gas)), + 'to': add_hex_prefix(self.to.hex()), + 'value': add_hex_prefix(hex(self.value)), + 'data': add_hex_prefix(self.data.hex()), + 'v': add_hex_prefix(hex(self.v)), + 'r': add_hex_prefix(self.r.hex()), + 's': add_hex_prefix(self.s.hex()), + } diff --git a/crypto_dev_signer/eth/web3ext/__init__.py b/crypto_dev_signer/eth/web3ext/__init__.py @@ -0,0 +1,29 @@ +import re + +from web3 import Web3 as Web3super +from web3 import WebsocketProvider, HTTPProvider +from .middleware import PlatformMiddleware + +re_websocket = re.compile('^wss?://') +re_http = re.compile('^https?://') + + +#def create_middleware(ipcaddr='/var/run/cic-platform/cic.ipc'): +def create_middleware(ipcaddr='/tmp/foo.ipc'): + PlatformMiddleware.ipcaddr = ipcaddr + return PlatformMiddleware + + +# overrides the original Web3 constructor +def Web3(blockchain_provider='ws://localhost:8546', ipcaddr=None): + provider = None + if re.match(re_websocket, blockchain_provider) != None: + provider = WebsocketProvider(blockchain_provider) + elif re.match(re_http, blockchain_provider) != None: + provider = HTTPProvider(blockchain_provider) + + w3 = Web3super(provider) + + w3.middleware_onion.add(create_middleware()) + w3.eth.personal = w3.geth.personal + return w3 diff --git a/src/web3ext/middleware.py b/crypto_dev_signer/eth/web3ext/middleware.py diff --git a/crypto_dev_signer/keystore/__init__.py b/crypto_dev_signer/keystore/__init__.py @@ -0,0 +1 @@ +from .postgres import ReferenceKeystore diff --git a/src/keystore/interface.py b/crypto_dev_signer/keystore/interface.py diff --git a/crypto_dev_signer/keystore/postgres.py b/crypto_dev_signer/keystore/postgres.py @@ -0,0 +1,95 @@ +# standard imports +import logging +import base64 +import os + +# third-party imports +from cryptography.fernet import Fernet +import psycopg2 +from psycopg2 import sql +from eth_keys import KeyAPI +from eth_keys.backends import NativeECCBackend +import sha3 + +# local imports +from crypto_dev_signer.common import strip_hex_prefix +from .interface import Keystore + +keyapi = KeyAPI(NativeECCBackend) + +logging.basicConfig(level=logging.DEBUG) +logg = logging.getLogger(__file__) + + +def to_bytes(x): + return x.encode('utf-8') + + +class ReferenceKeystore(Keystore): + + schema = [ + """CREATE TABLE ethereum ( + id SERIAL NOT NULL PRIMARY KEY, + key_ciphertext VARCHAR(256) NOT NULL, + wallet_address_hex CHAR(40) NOT NULL + ); +""", + """CREATE UNIQUE INDEX ethereum_address_idx ON ethereum ( wallet_address_hex ); +""", + ] + + def __init__(self, dbname, **kwargs): + self.conn = psycopg2.connect('dbname=' + dbname) + self.cur = self.conn.cursor() + self.symmetric_key = kwargs.get('symmetric_key') + + + def get(self, address, password=None): + safe_address = strip_hex_prefix(address) + s = sql.SQL('SELECT key_ciphertext FROM ethereum WHERE wallet_address_hex = %s') + self.cur.execute(s, [ safe_address ] ) + k = self.cur.fetchone()[0] + return self._decrypt(k, password) + + + def new(self, password=None): + b = os.urandom(32) + pk = keyapi.PrivateKey(b) + + pubk = keyapi.private_key_to_public_key(pk) + address_hex = pubk.to_checksum_address() + address_hex_clean = strip_hex_prefix(address_hex) + + logg.debug('address {}'.format(address_hex_clean)) + c = self._encrypt(pk.to_bytes(), password) + s = sql.SQL('INSERT INTO ethereum (wallet_address_hex, key_ciphertext) VALUES (%s, %s)') + self.cur.execute(s, [ address_hex_clean, c.decode('utf-8') ]) + self.conn.commit() + return 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')) + + + def __del__(self): + logg.debug('closing database') + self.conn.commit() + self.cur.close() + self.conn.close() diff --git a/scripts/crypto-dev-daemon b/scripts/crypto-dev-daemon diff --git a/scripts/crypto-dev-daemon.py b/scripts/crypto-dev-daemon.py diff --git a/setup.py b/setup.py @@ -6,9 +6,15 @@ setup( description="A signer and keystore daemon and library for cryptocurrency software development", author="Louis Holbrook", author_email="dev@holbrook.no", - packages=['crypto-dev-signer'], - install_requires=['web3', 'psycopg2', 'cryptography', 'eth-keys', 'pysha3', 'rlp'], + packages=[ + 'crypto_dev_signer.eth.signer', + 'crypto_dev_signer.eth.web3ext', + 'crypto_dev_signer.eth', + 'crypto_dev_signer.keystore', + 'crypto_dev_signer', + ], + install_requires=['web3', 'psycopg2', 'cryptography', 'eth-keys', 'pysha3', 'rlp', 'json-rpc'], scripts = [ - 'scripts/crypto-dev-daemon.py', + 'scripts/crypto-dev-daemon', ], ) diff --git a/src/keystore/__init__.py b/src/keystore/__init__.py @@ -1 +0,0 @@ -from keystore.postgres import ReferenceKeystore diff --git a/src/keystore/postgres.py b/src/keystore/postgres.py @@ -1,95 +0,0 @@ -# standard imports -import logging -import base64 -import os - -# third-party imports -from cryptography.fernet import Fernet -import psycopg2 -from psycopg2 import sql -from eth_keys import KeyAPI -from eth_keys.backends import NativeECCBackend -import sha3 - -# local imports -from common import strip_hex_prefix -from keystore.interface import Keystore - -keyapi = KeyAPI(NativeECCBackend) - -logging.basicConfig(level=logging.DEBUG) -logg = logging.getLogger(__file__) - - -def to_bytes(x): - return x.encode('utf-8') - - -class ReferenceKeystore(Keystore): - - schema = [ - """CREATE TABLE ethereum ( - id SERIAL NOT NULL PRIMARY KEY, - key_ciphertext VARCHAR(256) NOT NULL, - wallet_address_hex CHAR(40) NOT NULL - ); -""", - """CREATE UNIQUE INDEX ethereum_address_idx ON ethereum ( wallet_address_hex ); -""", - ] - - def __init__(self, dbname, **kwargs): - self.conn = psycopg2.connect('dbname=' + dbname) - self.cur = self.conn.cursor() - self.symmetric_key = kwargs.get('symmetric_key') - - - def get(self, address, password=None): - safe_address = strip_hex_prefix(address) - s = sql.SQL('SELECT key_ciphertext FROM ethereum WHERE wallet_address_hex = %s') - self.cur.execute(s, [ safe_address ] ) - k = self.cur.fetchone()[0] - return self._decrypt(k, password) - - - def new(self, password=None): - b = os.urandom(32) - pk = keyapi.PrivateKey(b) - - pubk = keyapi.private_key_to_public_key(pk) - address_hex = pubk.to_checksum_address() - address_hex_clean = strip_hex_prefix(address_hex) - - logg.debug('address {}'.format(address_hex_clean)) - c = self._encrypt(pk.to_bytes(), password) - s = sql.SQL('INSERT INTO ethereum (wallet_address_hex, key_ciphertext) VALUES (%s, %s)') - self.cur.execute(s, [ address_hex_clean, c.decode('utf-8') ]) - self.conn.commit() - return 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')) - - - def __del__(self): - logg.debug('closing database') - self.conn.commit() - self.cur.close() - self.conn.close() diff --git a/src/signer/__init__.py b/src/signer/__init__.py @@ -1 +0,0 @@ -from signer.defaultsigner import ReferenceSigner, Signer diff --git a/src/transaction.py b/src/transaction.py @@ -1,68 +0,0 @@ -# standard imports -import logging -import binascii - -# third-party imports -from rlp import encode as rlp_encode - -# local imports -from common import strip_hex_prefix, add_hex_prefix - -logg = logging.getLogger(__name__) - - -class Transaction: - - def rlp_serialize(self): - raise NotImplementedError - - def serialize(self): - raise NotImplementedError - - -class EIP155Transaction: - - 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 = b'' - self.s = b'' - self.sender = strip_hex_prefix(tx['from']) - - - def rlp_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) - - def serialize(self): - return { - 'nonce': add_hex_prefix(hex(self.nonce)), - 'gasPrice': add_hex_prefix(hex(self.gas_price)), - 'gas': add_hex_prefix(hex(self.start_gas)), - 'to': add_hex_prefix(self.to.hex()), - 'value': add_hex_prefix(hex(self.value)), - 'data': add_hex_prefix(self.data.hex()), - 'v': add_hex_prefix(hex(self.v)), - 'r': add_hex_prefix(self.r.hex()), - 's': add_hex_prefix(self.s.hex()), - } diff --git a/src/web3ext/__init__.py b/src/web3ext/__init__.py @@ -1,29 +0,0 @@ -import re - -from web3 import Web3 as Web3super -from web3 import WebsocketProvider, HTTPProvider -from web3ext.middleware import PlatformMiddleware - -re_websocket = re.compile('^wss?://') -re_http = re.compile('^https?://') - - -#def create_middleware(ipcaddr='/var/run/cic-platform/cic.ipc'): -def create_middleware(ipcaddr='/tmp/foo.ipc'): - PlatformMiddleware.ipcaddr = ipcaddr - return PlatformMiddleware - - -# overrides the original Web3 constructor -def Web3(blockchain_provider='ws://localhost:8546', ipcaddr=None): - provider = None - if re.match(re_websocket, blockchain_provider) != None: - provider = WebsocketProvider(blockchain_provider) - elif re.match(re_http, blockchain_provider) != None: - provider = HTTPProvider(blockchain_provider) - - w3 = Web3super(provider) - - w3.middleware_onion.add(create_middleware()) - w3.eth.personal = w3.geth.personal - return w3 diff --git a/test/test_keystore.py b/test/test_keystore.py @@ -8,7 +8,7 @@ import psycopg2 from psycopg2 import sql from cryptography.fernet import Fernet, InvalidToken -from keystore import ReferenceKeystore +from crypto_dev_signer.keystore import ReferenceKeystore logging.basicConfig(level=logging.DEBUG) logg = logging.getLogger() diff --git a/test/test_sign.py b/test/test_sign.py @@ -5,8 +5,8 @@ import logging from rlp import encode as rlp_encode -from signer import ReferenceSigner -from transaction import EIP155Transaction +from crypto_dev_signer.eth.signer import ReferenceSigner +from crypto_dev_signer.eth.transaction import EIP155Transaction logging.basicConfig(level=logging.DEBUG) logg = logging.getLogger()