commit 51f076ba2aa51643df6efd4f19692dcc75f398c0
parent 472e2f04fc106523b24b65f99aa572cc6df453fa
Author: nolash <dev@holbrook.no>
Date: Sat, 8 Aug 2020 10:45:37 +0200
Add setup.py, rename server script
Diffstat:
7 files changed, 182 insertions(+), 162 deletions(-)
diff --git a/scripts/crypto-dev-daemon b/scripts/crypto-dev-daemon
@@ -0,0 +1 @@
+scripts/crypto-dev-daemon.py
+\ No newline at end of file
diff --git a/scripts/crypto-dev-daemon.py b/scripts/crypto-dev-daemon.py
@@ -0,0 +1,158 @@
+#!/usr/bin/python3
+
+import socket
+import json
+import logging
+import sys
+import os
+
+from jsonrpc.exceptions import *
+
+from signer import ReferenceSigner
+from keystore import ReferenceKeystore
+from transaction import EIP155Transaction
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+db = None
+signer = None
+chainId = 8995
+
+
+def personal_new_account(p):
+ password = p
+ if p.__class__.__name__ != 'str':
+ if p.__class__.__name__ != 'list':
+ e = JSONRPCInvalidParams()
+ e.data = 'parameter must be list containing one string'
+ raise ValueError(e)
+ logg.error('foo {}'.format(p))
+ if len(p) != 1:
+ e = JSONRPCInvalidParams()
+ e.data = 'parameter must be list containing one string'
+ raise ValueError(e)
+ if p[0].__class__.__name__ != 'str':
+ e = JSONRPCInvalidParams()
+ e.data = 'parameter must be list containing one string'
+ raise ValueError(e)
+ password = p[0]
+
+ r = db.new(password)
+
+ return r
+
+
+def personal_sign_transaction(p):
+ t = EIP155Transaction(p[0], 0, 8995)
+ z = signer.signTransaction(t, p[1])
+ raw_signed_tx = t.rlp_serialize()
+ o = {
+ 'raw': '0x' + raw_signed_tx.hex(),
+ 'tx': t.serialize(),
+ }
+ return o
+
+
+# TODO: temporary workaround for platform, since personal_signTransaction is missing from web3.py
+def eth_signTransaction(tx):
+ return personal_sign_transaction([tx, ''])
+
+
+methods = {
+ 'personal_newAccount': personal_new_account,
+ 'personal_signTransaction': personal_sign_transaction,
+ 'eth_signTransaction': eth_signTransaction,
+ }
+
+
+def jsonrpc_error(rpc_id, err):
+ return {
+ 'json-rpc': '2.0',
+ 'id': rpc_id,
+ 'error': {
+ 'code': err.CODE,
+ 'message': err.MESSAGE,
+ },
+ }
+
+
+def jsonrpc_ok(rpc_id, response):
+ return {
+ 'json-rpc': '2.0',
+ 'id': rpc_id,
+ 'result': response,
+ }
+
+
+def is_valid_json(j):
+ if j.get('id') == 'None':
+ raise ValueError('id missing')
+ return True
+
+
+def process_input(j):
+ rpc_id = j['id']
+ m = j['method']
+ p = j['params']
+ return (rpc_id, methods[m](p))
+
+
+def start_server():
+ try:
+ os.unlink('/tmp/foo.ipc')
+ except FileNotFoundError:
+ pass
+ s = socket.socket(family = socket.AF_UNIX, type = socket.SOCK_STREAM)
+ s.bind('/tmp/foo.ipc')
+ s.listen(10)
+ while True:
+ (csock, caddr) = s.accept()
+ d = csock.recv(4096)
+ j = None
+ try:
+ j = json.loads(d)
+ is_valid_json(j)
+ logg.debug('{}'.format(d.decode('utf-8')))
+ except:
+ csock.send(json.dumps(jsonrpc_error(None, JSONRPCParseError)).encode('utf-8'))
+ csock.close()
+ continue
+
+ try:
+ (rpc_id, r) = process_input(j)
+ csock.send(json.dumps(jsonrpc_ok(rpc_id, r)).encode('utf-8'))
+ except:
+ # TODO: handle cases to give better error context to caller
+ csock.send(json.dumps(jsonrpc_error(j['id'], JSONRPCServerError)).encode('utf-8'))
+
+ csock.close()
+ s.close()
+
+ os.unlink('/tmp/foo.ipc')
+
+
+def init():
+ global db, signer
+ secret_hex = os.environ.get('SIGNER_SECRET')
+ secret = bytes.fromhex(secret_hex)
+ kw = {
+ 'symmetric_key': secret,
+ }
+ db = ReferenceKeystore('cic_signer', **kw)
+ signer = ReferenceSigner(db)
+
+
+if __name__ == '__main__':
+ init()
+ arg = None
+ try:
+ arg = json.loads(sys.argv[1])
+ except:
+ logg.info('no json rpc command detected, starting socket server')
+ start_server()
+ sys.exit(0)
+
+ (rpc_id, response) = process_input(arg)
+ r = jsonrpc_ok(rpc_id, response)
+ sys.stdout.write(json.dumps(r))
diff --git a/scripts/server.py b/scripts/server.py
@@ -1,157 +0,0 @@
-import socket
-import json
-import logging
-import sys
-import os
-
-from jsonrpc.exceptions import *
-
-from signer import ReferenceSigner
-from keystore import ReferenceKeystore
-from transaction import EIP155Transaction
-
-logging.basicConfig(level=logging.DEBUG)
-logg = logging.getLogger()
-
-db = None
-signer = None
-chainId = 8995
-
-
-def personal_new_account(p):
- if p.__class__.__name__ != 'list':
- e = JSONRPCInvalidParams()
- e.data = 'parameter must be list containing one string'
- raise ValueError(e)
- if len(p) != 1:
- e = JSONRPCInvalidParams()
- e.data = 'parameter must be list containing one string'
- raise ValueError(e)
- if p[0].__class__.__name__ != 'str':
- e = JSONRPCInvalidParams()
- e.data = 'parameter must be list containing one string'
- raise ValueError(e)
-
- r = db.new(p[0])
-
- return r
-
-
-def personal_sign_transaction(p):
- t = EIP155Transaction(p[0], 0, 8995)
- z = signer.signTransaction(t, p[1])
- raw_signed_tx = t.rlp_serialize()
- o = {
- 'raw': '0x' + raw_signed_tx.hex(),
- 'tx': t.serialize(),
- }
- return o
-
-
-# TODO: temporary workaround for platform, since personal_signTransaction is missing from web3.py
-def eth_signTransaction(tx):
- password = tx['password']
- del tx['password']
- tx_signed = personal_sign_transaction([tx, password])
- return tx_signed
-
-
-methods = {
- 'personal_newAccount': personal_new_account,
- 'personal_signTransaction': personal_sign_transaction,
- 'eth_signTransaction': eth_signTransaction,
- }
-
-
-def jsonrpc_error(rpc_id, err):
- return {
- 'json-rpc': '2.0',
- 'id': rpc_id,
- 'error': {
- 'code': err.CODE,
- 'message': err.MESSAGE,
- },
- }
-
-
-def jsonrpc_ok(rpc_id, response):
- return {
- 'json-rpc': '2.0',
- 'id': rpc_id,
- 'result': response,
- }
-
-
-def is_valid_json(j):
- if j.get('id') == 'None':
- raise ValueError('id missing')
- return True
-
-
-def process_input(j):
-
- rpc_id = j['id']
-
- m = j['method']
- p = j['params']
- return (rpc_id, methods[m](p))
-
-
-def start_server():
- try:
- os.unlink('/tmp/foo.ipc')
- except FileNotFoundError:
- pass
- s = socket.socket(family = socket.AF_UNIX, type = socket.SOCK_STREAM)
- s.bind('/tmp/foo.ipc')
- s.listen(10)
- while True:
- (csock, caddr) = s.accept()
- d = csock.recv(4096)
- j = None
- try:
- j = json.loads(d)
- is_valid_json(j)
- logg.debug('{}'.format(d.decode('utf-8')))
- except:
- csock.send(json.dumps(jsonrpc_error(None, JSONRPCParseError)).encode('utf-8'))
- csock.close()
- continue
-
- try:
- (rpc_id, r) = process_input(j)
- csock.send(json.dumps(jsonrpc_ok(rpc_id, r)).encode('utf-8'))
- except:
- # TODO: handle cases to give better error context to caller
- csock.send(json.dumps(jsonrpc_error(j['id'], JSONRPCServerError)).encode('utf-8'))
-
- csock.close()
- s.close()
-
- os.unlink('/tmp/foo.ipc')
-
-
-def init():
- global db, signer
- secret_hex = os.environ.get('SIGNER_SECRET')
- secret = bytes.fromhex(secret_hex)
- kw = {
- 'symmetric_key': secret,
- }
- db = ReferenceKeystore('cic_signer', **kw)
- signer = ReferenceSigner(db)
-
-
-if __name__ == '__main__':
- init()
- arg = None
- try:
- arg = json.loads(sys.argv[1])
- except:
- logg.info('no json rpc command detected, starting socket server')
- start_server()
- sys.exit(0)
-
- (rpc_id, response) = process_input(arg)
- r = jsonrpc_ok(rpc_id, response)
- sys.stdout.write(json.dumps(r))
diff --git a/setup.py b/setup.py
@@ -0,0 +1,14 @@
+from setuptools import setup
+
+setup(
+ name="crypto-dev-signer",
+ version="0.1.0",
+ 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'],
+ scripts = [
+ 'scripts/crypto-dev-daemon.py',
+ ],
+ )
diff --git a/src/keystore/postgres.py b/src/keystore/postgres.py
@@ -1,7 +1,9 @@
+# standard imports
import logging
import base64
import os
+# third-party imports
from cryptography.fernet import Fernet
import psycopg2
from psycopg2 import sql
@@ -9,6 +11,7 @@ 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
@@ -18,15 +21,10 @@ logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger(__file__)
-
def to_bytes(x):
return x.encode('utf-8')
-
-
-
-
class ReferenceKeystore(Keystore):
schema = [
diff --git a/src/transaction.py b/src/transaction.py
@@ -1,12 +1,16 @@
+# 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):
diff --git a/src/web3ext/middleware.py b/src/web3ext/middleware.py
@@ -1,3 +1,4 @@
+# standard imports
import logging
import re
import socket