Remove eth_keys, web3 dependencies
This commit is contained in:
parent
3fb5745f98
commit
b46ed3a9e6
@ -1,3 +1,3 @@
|
||||
[signer]
|
||||
secret = deadbeef
|
||||
socket_path = /tmp/crypto-dev-signer/jsonrpc.ipc
|
||||
socket_path = ipc:///tmp/crypto-dev-signer/jsonrpc.ipc
|
||||
|
@ -1,4 +0,0 @@
|
||||
import crypto_dev_signer.eth.signer
|
||||
import crypto_dev_signer.eth.web3ext
|
||||
import crypto_dev_signer.eth.transaction
|
||||
import crypto_dev_signer.common
|
@ -1,11 +1,15 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# external imports
|
||||
import sha3
|
||||
import coincurve
|
||||
#from eth_keys import KeyAPI
|
||||
#from eth_keys.backends import NativeECCBackend
|
||||
|
||||
from eth_keys import KeyAPI
|
||||
from eth_keys.backends import NativeECCBackend
|
||||
|
||||
keys = KeyAPI(NativeECCBackend)
|
||||
logg = logging.getLogger(__name__)
|
||||
#keys = KeyAPI(NativeECCBackend)
|
||||
#logg = logging.getLogger(__name__)
|
||||
logg = logging.getLogger()
|
||||
|
||||
|
||||
class Signer:
|
||||
@ -31,9 +35,9 @@ class ReferenceSigner(Signer):
|
||||
s = tx.rlp_serialize()
|
||||
h = sha3.keccak_256()
|
||||
h.update(s)
|
||||
g = h.digest()
|
||||
k = keys.PrivateKey(self.keyGetter.get(tx.sender, password))
|
||||
z = keys.ecdsa_sign(message_hash=g, private_key=k)
|
||||
message_to_sign = h.digest()
|
||||
z = self.sign(tx.sender, message_to_sign, password)
|
||||
|
||||
vnum = int.from_bytes(tx.v, 'big')
|
||||
v = (vnum * 2) + 35 + z[64]
|
||||
byts = ((v.bit_length()-1)/8)+1
|
||||
@ -55,17 +59,30 @@ class ReferenceSigner(Signer):
|
||||
|
||||
|
||||
def signEthereumMessage(self, address, message, password=None):
|
||||
#msg = b'\x19Ethereum Signed Message:\n{}{}'.format(len(message), message)
|
||||
k = keys.PrivateKey(self.keyGetter.get(address, password))
|
||||
|
||||
#k = keys.PrivateKey(self.keyGetter.get(address, password))
|
||||
#z = keys.ecdsa_sign(message_hash=g, private_key=k)
|
||||
z = None
|
||||
if type(message).__name__ == 'str':
|
||||
logg.debug('signing message in "str" format: {}'.format(message))
|
||||
z = k.sign_msg(bytes.fromhex(message))
|
||||
#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()))
|
||||
z = k.sign_msg(message)
|
||||
#z = k.sign_msg(message)
|
||||
else:
|
||||
logg.debug('unhandled format {}'.format(type(message).__name__))
|
||||
raise ValueError('message must be type str or bytes, received {}'.format(type(message).__name__))
|
||||
|
||||
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)
|
||||
return z
|
||||
|
||||
|
||||
def sign(self, address, message, password=None):
|
||||
pk = coincurve.PrivateKey(secret=self.keyGetter.get(address, password))
|
||||
z = pk.sign(hasher=None, message=message)
|
||||
return z
|
||||
|
@ -1,8 +1,8 @@
|
||||
# third-party imports
|
||||
from eth_keys import KeyAPI
|
||||
from eth_keys.backends import NativeECCBackend
|
||||
#from eth_keys import KeyAPI
|
||||
#from eth_keys.backends import NativeECCBackend
|
||||
|
||||
keyapi = KeyAPI(NativeECCBackend)
|
||||
#keyapi = KeyAPI(NativeECCBackend)
|
||||
|
||||
from .postgres import ReferenceKeystore
|
||||
from .dict import DictKeystore
|
||||
#from .postgres import ReferenceKeystore
|
||||
#from .dict import DictKeystore
|
||||
|
@ -1,11 +1,14 @@
|
||||
# standard imports
|
||||
import logging
|
||||
|
||||
# external imports
|
||||
from hexathon import strip_0x
|
||||
|
||||
# local imports
|
||||
from . import keyapi
|
||||
#from . import keyapi
|
||||
from .interface import Keystore
|
||||
from crypto_dev_signer.error import UnknownAccountError
|
||||
from crypto_dev_signer.common import strip_hex_prefix
|
||||
from crypto_dev_signer.encoding import private_key_to_address
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
@ -25,9 +28,13 @@ class DictKeystore(Keystore):
|
||||
raise UnknownAccountError(address)
|
||||
|
||||
|
||||
def list(self):
|
||||
return list(self.keys.keys())
|
||||
|
||||
|
||||
def import_key(self, pk, password=None):
|
||||
pubk = keyapi.private_key_to_public_key(pk)
|
||||
address_hex = pubk.to_checksum_address()
|
||||
address_hex_clean = strip_hex_prefix(address_hex)
|
||||
self.keys[address_hex_clean] = pk.to_bytes()
|
||||
address_hex = private_key_to_address(pk)
|
||||
address_hex_clean = strip_0x(address_hex)
|
||||
self.keys[address_hex_clean] = pk.secret
|
||||
logg.debug('added key {}'.format(address_hex))
|
||||
return address_hex
|
||||
|
@ -1,12 +1,13 @@
|
||||
# standard imports
|
||||
import os
|
||||
|
||||
# third-party imports
|
||||
import eth_keyfile
|
||||
import json
|
||||
import logging
|
||||
|
||||
# local imports
|
||||
from . import keyapi
|
||||
from crypto_dev_signer.keystore import keyfile
|
||||
import coincurve
|
||||
|
||||
logg = logging.getLogger(__name__)
|
||||
|
||||
class Keystore:
|
||||
|
||||
@ -14,13 +15,17 @@ class Keystore:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def list(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def new(self, password=None):
|
||||
b = os.urandom(32)
|
||||
return self.import_raw_key(b, password)
|
||||
|
||||
|
||||
def import_raw_key(self, b, password=None):
|
||||
pk = keyapi.PrivateKey(b)
|
||||
pk = coincurve.PrivateKey(secret=b)
|
||||
return self.import_key(pk, password)
|
||||
|
||||
|
||||
@ -30,9 +35,16 @@ class Keystore:
|
||||
|
||||
def import_keystore_data(self, keystore_content, password=''):
|
||||
#private_key = w3.eth.account.decrypt(keystore_content, password)
|
||||
private_key = eth_keyfile.decode_keyfile_json(keystore_content, password.encode('utf-8'))
|
||||
if type(keystore_content).__name__ == 'str':
|
||||
keystore_content = json.loads(keystore_content)
|
||||
elif type(keystore_content).__name__ == 'bytes':
|
||||
logg.debug('bytes {}'.format(keystore_content))
|
||||
keystore_content = json.loads(keystore_content.decode('utf-8'))
|
||||
private_key = keyfile.from_dict(keystore_content, password.encode('utf-8'))
|
||||
return self.import_raw_key(private_key, password)
|
||||
|
||||
def import_keystore_file(self, keystore_file, password=''):
|
||||
keystore_content = eth_keyfile.load_keyfile(keystore_file)
|
||||
return self.import_keystore_data(keystore_content, password)
|
||||
private_key = keyfile.from_file(keystore_file)
|
||||
#return self.import_keystore_data(keystore_content, password)
|
||||
return self.import_raw_key(private_key, password)
|
||||
#return kes
|
||||
|
@ -2,7 +2,7 @@
|
||||
import logging
|
||||
import base64
|
||||
|
||||
# third-party imports
|
||||
# external imports
|
||||
from cryptography.fernet import Fernet
|
||||
#import psycopg2
|
||||
#from psycopg2 import sql
|
||||
@ -10,12 +10,13 @@ from cryptography.fernet import Fernet
|
||||
from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
import sha3
|
||||
from hexathon import strip_0x
|
||||
|
||||
# local imports
|
||||
from .interface import Keystore
|
||||
from crypto_dev_signer.common import strip_hex_prefix
|
||||
from . import keyapi
|
||||
#from . import keyapi
|
||||
from crypto_dev_signer.error import UnknownAccountError
|
||||
from crypto_dev_signer.encoding import private_key_to_address
|
||||
|
||||
logg = logging.getLogger(__file__)
|
||||
|
||||
@ -53,7 +54,7 @@ class ReferenceKeystore(Keystore):
|
||||
|
||||
|
||||
def get(self, address, password=None):
|
||||
safe_address = strip_hex_prefix(address)
|
||||
safe_address = strip_0x(address)
|
||||
s = text('SELECT key_ciphertext FROM ethereum WHERE wallet_address_hex = :a')
|
||||
r = self.db_session.execute(s, {
|
||||
'a': safe_address,
|
||||
@ -69,10 +70,10 @@ class ReferenceKeystore(Keystore):
|
||||
|
||||
|
||||
def import_key(self, pk, password=None):
|
||||
pubk = keyapi.private_key_to_public_key(pk)
|
||||
address_hex = pubk.to_checksum_address()
|
||||
address_hex_clean = strip_hex_prefix(address_hex)
|
||||
c = self._encrypt(pk.to_bytes(), password)
|
||||
address_hex = private_key_to_address(pk)
|
||||
address_hex_clean = strip_0x(address_hex)
|
||||
|
||||
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,
|
||||
|
8
crypto_dev_signer/runnable/keyfile.py
Normal file
8
crypto_dev_signer/runnable/keyfile.py
Normal file
@ -0,0 +1,8 @@
|
||||
# standard imports
|
||||
import logging
|
||||
import sys
|
||||
|
||||
# local imports
|
||||
from crypto_dev_signer.keystore.keyfile import parse_file
|
||||
|
||||
print(from_file(sys.argv[1]).hex())
|
@ -1,4 +1,5 @@
|
||||
# standard imports
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import stat
|
||||
@ -6,6 +7,7 @@ import socket
|
||||
import json
|
||||
import logging
|
||||
import argparse
|
||||
from urllib.parse import urlparse
|
||||
|
||||
# third-party imports
|
||||
import confini
|
||||
@ -51,9 +53,9 @@ logg.debug('config loaded from {}:\n{}'.format(config_dir, config))
|
||||
if args.i:
|
||||
chainId = args.i
|
||||
if args.s:
|
||||
socket_path = args.s
|
||||
socket_url = urlparse(args.s)
|
||||
elif config.get('SIGNER_SOCKET_PATH'):
|
||||
socket_path = config.get('SIGNER_SOCKET_PATH')
|
||||
socket_url = urlparse(config.get('SIGNER_SOCKET_PATH'))
|
||||
|
||||
|
||||
# connect to database
|
||||
@ -68,6 +70,8 @@ dsn = 'postgresql://{}:{}@{}:{}/{}'.format(
|
||||
logg.info('using dsn {}'.format(dsn))
|
||||
logg.info('using socket {}'.format(socket_path))
|
||||
|
||||
re_http = r'^http'
|
||||
re_unix = r'^ipc'
|
||||
|
||||
class MissingSecretError(BaseException):
|
||||
|
||||
@ -114,7 +118,7 @@ def personal_sign_transaction(p):
|
||||
|
||||
# TODO: temporary workaround for platform, since personal_signTransaction is missing from web3.py
|
||||
def eth_signTransaction(tx):
|
||||
return personal_sign_transaction([tx, ''])
|
||||
return personal_sign_transaction([tx[0], ''])
|
||||
|
||||
|
||||
def eth_sign(p):
|
||||
@ -249,13 +253,16 @@ def main():
|
||||
arg = json.loads(sys.argv[1])
|
||||
except:
|
||||
logg.info('no json rpc command detected, starting socket server')
|
||||
socket_spec = socket_path.split(':')
|
||||
if len(socket_spec) == 2:
|
||||
scheme = 'ipc'
|
||||
if socket_url.scheme != '':
|
||||
scheme = socket_url.scheme
|
||||
if re.match(re_http, socket_url.scheme):
|
||||
socket_spec = socket_url.netloc.split(':')
|
||||
host = socket_spec[0]
|
||||
port = int(socket_spec[1])
|
||||
start_server_tcp((host, port))
|
||||
else:
|
||||
start_server_unix(socket_path)
|
||||
start_server_unix(socket_url.path)
|
||||
sys.exit(0)
|
||||
|
||||
(rpc_id, response) = process_input(arg)
|
||||
|
@ -1,9 +1,10 @@
|
||||
web3==5.12.2
|
||||
psycopg2==2.8.6
|
||||
cryptography==3.2.1
|
||||
eth-keys==0.3.3
|
||||
#cryptography==3.2.1
|
||||
pysha3==1.0.2
|
||||
rlp==2.0.1
|
||||
simple-rlp==0.1.2
|
||||
json-rpc==1.13.0
|
||||
confini~=0.3.6a1
|
||||
sqlalchemy==1.3.20
|
||||
coincurve==15.0.0
|
||||
pycrypto==2.6.1
|
||||
hexathon==0.0.1a3
|
||||
|
2
setup.py
2
setup.py
@ -24,7 +24,7 @@ f.close()
|
||||
|
||||
setup(
|
||||
name="crypto-dev-signer",
|
||||
version="0.4.13rc4",
|
||||
version="0.4.13rc6",
|
||||
description="A signer and keystore daemon and library for cryptocurrency software development",
|
||||
author="Louis Holbrook",
|
||||
author_email="dev@holbrook.no",
|
||||
|
@ -3,14 +3,12 @@ import unittest
|
||||
import logging
|
||||
import os
|
||||
|
||||
# third-party imports
|
||||
import web3
|
||||
|
||||
# local imports
|
||||
from crypto_dev_signer.keystore import DictKeystore
|
||||
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.eth.helper import EthTxExecutor
|
||||
from crypto_dev_signer.encoding import to_checksum_address
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logg = logging.getLogger()
|
||||
@ -42,7 +40,7 @@ class MockEthTxBackend:
|
||||
|
||||
def builder_two(self, tx):
|
||||
tx['value'] = 10243
|
||||
tx['to'] = web3.Web3.toChecksumAddress('0x' + os.urandom(20).hex())
|
||||
tx['to'] = to_checksum_address('0x' + os.urandom(20).hex())
|
||||
tx['data'] = ''
|
||||
if tx.get('feePrice') != None:
|
||||
tx['gasPrice'] = tx['feePrice']
|
||||
@ -78,15 +76,15 @@ class TestHelper(unittest.TestCase):
|
||||
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])
|
||||
# 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__':
|
||||
|
@ -7,7 +7,7 @@ import base64
|
||||
import os
|
||||
|
||||
# local imports
|
||||
from crypto_dev_signer.keystore import DictKeystore
|
||||
from crypto_dev_signer.keystore.dict import DictKeystore
|
||||
from crypto_dev_signer.error import UnknownAccountError
|
||||
from crypto_dev_signer.eth.signer import ReferenceSigner
|
||||
|
||||
|
@ -12,7 +12,7 @@ from psycopg2 import sql
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
|
||||
# local imports
|
||||
from crypto_dev_signer.keystore import ReferenceKeystore
|
||||
from crypto_dev_signer.keystore.postgres import ReferenceKeystore
|
||||
from crypto_dev_signer.error import UnknownAccountError
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
@ -68,14 +68,14 @@ class TestSign(unittest.TestCase):
|
||||
t = EIP155Transaction(tx_ints, 0)
|
||||
self.assertRegex(t.__class__.__name__, "Transaction")
|
||||
s = t.serialize()
|
||||
self.assertEqual('{}'.format(s), "{'nonce': '', 'gasPrice': '0x04a817c800', 'gas': '0x5208', 'to': '0x3535353535353535353535353535353535353535', 'value': '0x03e8', 'data': '0xdeadbeef', 'v': '0x01', 'r': '', 's': ''}")
|
||||
self.assertEqual('{}'.format(s), "{'nonce': '0x00', 'gasPrice': '0x04a817c800', 'gas': '0x5208', 'to': '0x3535353535353535353535353535353535353535', 'value': '0x03e8', 'data': '0xdeadbeef', 'v': '0x01', 'r': '', 's': ''}")
|
||||
r = t.rlp_serialize()
|
||||
self.assertEqual(r.hex(), 'ea808504a817c8008252089435353535353535353535353535353535353535358203e884deadbeef018080')
|
||||
|
||||
t = EIP155Transaction(tx_hexs, 0)
|
||||
self.assertRegex(t.__class__.__name__, "Transaction")
|
||||
s = t.serialize()
|
||||
self.assertEqual('{}'.format(s), "{'nonce': '', 'gasPrice': '0x04a817c800', 'gas': '0x5208', 'to': '0x3535353535353535353535353535353535353535', 'value': '0x03e8', 'data': '0xdeadbeef', 'v': '0x01', 'r': '', 's': ''}")
|
||||
self.assertEqual('{}'.format(s), "{'nonce': '0x00', 'gasPrice': '0x04a817c800', 'gas': '0x5208', 'to': '0x3535353535353535353535353535353535353535', 'value': '0x03e8', 'data': '0xdeadbeef', 'v': '0x01', 'r': '', 's': ''}")
|
||||
r = t.rlp_serialize()
|
||||
self.assertEqual(r.hex(), 'ea808504a817c8008252089435353535353535353535353535353535353535358203e884deadbeef018080')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user