WIP refactor eth to separate module, rename to funga
This commit is contained in:
parent
7f8a3628ce
commit
cb974126cd
@ -1,11 +0,0 @@
|
|||||||
def strip_hex_prefix(hx):
|
|
||||||
if hx[:2] == '0x':
|
|
||||||
return hx[2:]
|
|
||||||
return hx
|
|
||||||
|
|
||||||
def add_hex_prefix(hx):
|
|
||||||
if len(hx) < 2:
|
|
||||||
return hx
|
|
||||||
if hx[:2] != '0x':
|
|
||||||
return '0x' + hx
|
|
||||||
return hx
|
|
@ -1,8 +0,0 @@
|
|||||||
ethereum_recid_modifier = 35
|
|
||||||
|
|
||||||
def chain_id_to_v(chain_id, signature):
|
|
||||||
v = signature[64]
|
|
||||||
return (chain_id * 2) + ethereum_recid_modifier + v
|
|
||||||
|
|
||||||
def chainv_to_v(chain_id, v):
|
|
||||||
return v - ethereum_recid_modifier - (chain_id * 2)
|
|
@ -1 +0,0 @@
|
|||||||
from crypto_dev_signer.eth.signer.defaultsigner import ReferenceSigner, Signer
|
|
@ -53,7 +53,7 @@ def is_checksum_address(address_hex):
|
|||||||
hx = to_checksum(address_hex)
|
hx = to_checksum(address_hex)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
return hx == address_hex
|
return hx == strip_0x(address_hex)
|
||||||
|
|
||||||
|
|
||||||
def to_checksum_address(address_hex):
|
def to_checksum_address(address_hex):
|
||||||
@ -65,7 +65,8 @@ def to_checksum_address(address_hex):
|
|||||||
h.update(address_hex.encode('utf-8'))
|
h.update(address_hex.encode('utf-8'))
|
||||||
z = h.digest()
|
z = h.digest()
|
||||||
|
|
||||||
checksum_address_hex = '0x'
|
#checksum_address_hex = '0x'
|
||||||
|
checksum_address_hex = ''
|
||||||
|
|
||||||
for (i, c) in enumerate(address_hex):
|
for (i, c) in enumerate(address_hex):
|
||||||
if c in '1234567890':
|
if c in '1234567890':
|
||||||
@ -79,3 +80,12 @@ def to_checksum_address(address_hex):
|
|||||||
return checksum_address_hex
|
return checksum_address_hex
|
||||||
|
|
||||||
to_checksum = to_checksum_address
|
to_checksum = to_checksum_address
|
||||||
|
|
||||||
|
ethereum_recid_modifier = 35
|
||||||
|
|
||||||
|
def chain_id_to_v(chain_id, signature):
|
||||||
|
v = signature[64]
|
||||||
|
return (chain_id * 2) + ethereum_recid_modifier + v
|
||||||
|
|
||||||
|
def chainv_to_v(chain_id, v):
|
||||||
|
return v - ethereum_recid_modifier - (chain_id * 2)
|
1
funga/eth/helper/__init__.py
Normal file
1
funga/eth/helper/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .tx import EthTxExecutor
|
58
funga/eth/helper/tx.py
Normal file
58
funga/eth/helper/tx.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# standard imports
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# local imports
|
||||||
|
from crypto_dev_signer.helper import TxExecutor
|
||||||
|
from crypto_dev_signer.error import NetworkError
|
||||||
|
|
||||||
|
logg = logging.getLogger()
|
||||||
|
logging.getLogger('web3').setLevel(logging.CRITICAL)
|
||||||
|
logging.getLogger('urllib3').setLevel(logging.CRITICAL)
|
||||||
|
|
||||||
|
|
||||||
|
class EthTxExecutor(TxExecutor):
|
||||||
|
|
||||||
|
def __init__(self, w3, sender, signer, chain_id, verifier=None, block=False):
|
||||||
|
self.w3 = w3
|
||||||
|
nonce = self.w3.eth.getTransactionCount(sender, 'pending')
|
||||||
|
super(EthTxExecutor, self).__init__(sender, signer, self.translator, self.dispatcher, self.reporter, nonce, chain_id, self.fee_helper, self.fee_price_helper, verifier, block)
|
||||||
|
|
||||||
|
|
||||||
|
def fee_helper(self, tx):
|
||||||
|
estimate = self.w3.eth.estimateGas(tx)
|
||||||
|
if estimate < 21000:
|
||||||
|
estimate = 21000
|
||||||
|
logg.debug('estimate {} {}'.format(tx, estimate))
|
||||||
|
return estimate
|
||||||
|
|
||||||
|
|
||||||
|
def fee_price_helper(self):
|
||||||
|
return self.w3.eth.gasPrice
|
||||||
|
|
||||||
|
|
||||||
|
def dispatcher(self, tx):
|
||||||
|
error_object = None
|
||||||
|
try:
|
||||||
|
tx_hash = self.w3.eth.sendRawTransaction(tx)
|
||||||
|
except ValueError as e:
|
||||||
|
error_object = e.args[0]
|
||||||
|
logg.error('node could not intepret rlp {}'.format(tx))
|
||||||
|
if error_object != None:
|
||||||
|
raise NetworkError(error_object)
|
||||||
|
return tx_hash
|
||||||
|
|
||||||
|
|
||||||
|
def reporter(self, tx):
|
||||||
|
return self.w3.eth.getTransactionReceipt(tx)
|
||||||
|
|
||||||
|
|
||||||
|
def translator(self, tx):
|
||||||
|
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
|
@ -9,14 +9,14 @@ from hexathon import (
|
|||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
#from . import keyapi
|
#from . import keyapi
|
||||||
from .interface import Keystore
|
from funga.error import UnknownAccountError
|
||||||
from crypto_dev_signer.error import UnknownAccountError
|
from .interface import EthKeystore
|
||||||
from crypto_dev_signer.encoding import private_key_to_address
|
from funga.eth.encoding import private_key_to_address
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DictKeystore(Keystore):
|
class DictKeystore(EthKeystore):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.keys = {}
|
self.keys = {}
|
@ -4,23 +4,28 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from crypto_dev_signer.keystore import keyfile
|
from funga.keystore import Keystore
|
||||||
from crypto_dev_signer.encoding import private_key_from_bytes
|
from funga.eth.keystore import keyfile
|
||||||
|
from funga.eth.encoding import private_key_from_bytes
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
class Keystore:
|
|
||||||
|
|
||||||
def get(self, address, password=None):
|
def native_keygen(self):
|
||||||
raise NotImplementedError
|
return os.urandom(32)
|
||||||
|
|
||||||
|
|
||||||
def list(self):
|
class EthKeystore(Keystore):
|
||||||
raise NotImplementedError
|
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def new(self, password=None):
|
def new(self, password=None):
|
||||||
b = os.urandom(32)
|
|
||||||
return self.import_raw_key(b, password)
|
return self.import_raw_key(b, password)
|
||||||
|
|
||||||
|
|
||||||
@ -42,6 +47,7 @@ class Keystore:
|
|||||||
private_key = keyfile.from_dict(keystore_content, password.encode('utf-8'))
|
private_key = keyfile.from_dict(keystore_content, password.encode('utf-8'))
|
||||||
return self.import_raw_key(private_key, password)
|
return self.import_raw_key(private_key, password)
|
||||||
|
|
||||||
|
|
||||||
def import_keystore_file(self, keystore_file, password=''):
|
def import_keystore_file(self, keystore_file, password=''):
|
||||||
private_key = keyfile.from_file(keystore_file, password)
|
private_key = keyfile.from_file(keystore_file, password)
|
||||||
return self.import_raw_key(private_key)
|
return self.import_raw_key(private_key)
|
@ -12,7 +12,7 @@ from Crypto.Util import Counter
|
|||||||
import sha3
|
import sha3
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from crypto_dev_signer.encoding import private_key_to_address
|
from funga.eth.encoding import private_key_to_address
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -141,3 +141,18 @@ def from_file(filepath, passphrase=''):
|
|||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
return from_dict(o, passphrase)
|
return from_dict(o, passphrase)
|
||||||
|
|
||||||
|
|
||||||
|
def from_some(v, passphrase=''):
|
||||||
|
if isinstance(v, bytes):
|
||||||
|
v = v.decode('utf-8')
|
||||||
|
|
||||||
|
if isinstance(v, str):
|
||||||
|
try:
|
||||||
|
return from_file(v, passphrase)
|
||||||
|
except Exception:
|
||||||
|
logg.debug('keyfile parse as file fail')
|
||||||
|
pass
|
||||||
|
v = json.loads(v)
|
||||||
|
|
||||||
|
return from_dict(v, passphrase)
|
1
funga/eth/signer/__init__.py
Normal file
1
funga/eth/signer/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from funga.eth.signer.defaultsigner import EIP155Signer
|
@ -7,27 +7,16 @@ import coincurve
|
|||||||
from hexathon import int_to_minbytes
|
from hexathon import int_to_minbytes
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from crypto_dev_signer.eth.encoding import chain_id_to_v
|
from funga.signer import Signer
|
||||||
|
from funga.eth.encoding import chain_id_to_v
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Signer:
|
class EIP155Signer(Signer):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, keyGetter):
|
def __init__(self, keyGetter):
|
||||||
self.keyGetter = keyGetter
|
super(EIP155Signer, self).__init__(keyGetter)
|
||||||
|
|
||||||
|
|
||||||
def sign_transaction(self, tx, password=None):
|
|
||||||
return NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
class ReferenceSigner(Signer):
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, keyGetter):
|
|
||||||
super(ReferenceSigner, self).__init__(keyGetter)
|
|
||||||
|
|
||||||
|
|
||||||
def sign_transaction(self, tx, password=None):
|
def sign_transaction(self, tx, password=None):
|
29
funga/eth/web3ext/__init__.py
Normal file
29
funga/eth/web3ext/__init__.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import logging
|
||||||
|
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?://')
|
||||||
|
|
||||||
|
logg = logging.getLogger(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
def create_middleware(ipcpath):
|
||||||
|
PlatformMiddleware.ipcaddr = ipcpath
|
||||||
|
return PlatformMiddleware
|
||||||
|
|
||||||
|
|
||||||
|
# overrides the original Web3 constructor
|
||||||
|
#def Web3(blockchain_provider='ws://localhost:8546', ipcpath=None):
|
||||||
|
def Web3(provider, ipcpath=None):
|
||||||
|
w3 = Web3super(provider)
|
||||||
|
|
||||||
|
if ipcpath != None:
|
||||||
|
logg.info('using signer middleware with ipc {}'.format(ipcpath))
|
||||||
|
w3.middleware_onion.add(create_middleware(ipcpath))
|
||||||
|
|
||||||
|
w3.eth.personal = w3.geth.personal
|
||||||
|
return w3
|
116
funga/eth/web3ext/middleware.py
Normal file
116
funga/eth/web3ext/middleware.py
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
# standard imports
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import uuid
|
||||||
|
import json
|
||||||
|
|
||||||
|
logg = logging.getLogger(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
def jsonrpc_request(method, params):
|
||||||
|
uu = uuid.uuid4()
|
||||||
|
return {
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": str(uu),
|
||||||
|
"method": method,
|
||||||
|
"params": params,
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlatformMiddleware:
|
||||||
|
|
||||||
|
# id for the request is not available, meaning we cannot easily short-circuit
|
||||||
|
# hack workaround
|
||||||
|
id_seq = -1
|
||||||
|
re_personal = re.compile('^personal_.*')
|
||||||
|
ipcaddr = None
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, make_request, w3):
|
||||||
|
self.w3 = w3
|
||||||
|
self.make_request = make_request
|
||||||
|
if self.ipcaddr == None:
|
||||||
|
raise AttributeError('ipcaddr not set')
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: understand what format input params come in
|
||||||
|
# single entry input gives a tuple on params, wtf...
|
||||||
|
# dict input comes as [{}] and fails if not passed on as an array
|
||||||
|
@staticmethod
|
||||||
|
def _translate_params(params):
|
||||||
|
#if params.__class__.__name__ == 'tuple':
|
||||||
|
# r = []
|
||||||
|
# for p in params:
|
||||||
|
# r.append(p)
|
||||||
|
# return r
|
||||||
|
|
||||||
|
if params.__class__.__name__ == 'list' and len(params) > 0:
|
||||||
|
return params[0]
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: DRY
|
||||||
|
def __call__(self, method, suspect_params):
|
||||||
|
|
||||||
|
self.id_seq += 1
|
||||||
|
logg.debug('in middleware method {} params {} ipcpath {}'.format(method, suspect_params, self.ipcaddr))
|
||||||
|
|
||||||
|
if self.re_personal.match(method) != None:
|
||||||
|
params = PlatformMiddleware._translate_params(suspect_params)
|
||||||
|
# multiple providers is removed in web3.py 5.12.0
|
||||||
|
# https://github.com/ethereum/web3.py/issues/1701
|
||||||
|
# thus we need a workaround to use the same web3 instance
|
||||||
|
s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0)
|
||||||
|
ipc_provider_workaround = s.connect(self.ipcaddr)
|
||||||
|
|
||||||
|
logg.info('redirecting method {} params {} original params {}'.format(method, params, suspect_params))
|
||||||
|
o = jsonrpc_request(method, params[0])
|
||||||
|
j = json.dumps(o)
|
||||||
|
logg.debug('send {}'.format(j))
|
||||||
|
s.send(j.encode('utf-8'))
|
||||||
|
r = s.recv(4096)
|
||||||
|
s.close()
|
||||||
|
logg.debug('got recv {}'.format(str(r)))
|
||||||
|
jr = json.loads(r)
|
||||||
|
jr['id'] = self.id_seq
|
||||||
|
#return str(json.dumps(jr))
|
||||||
|
return jr
|
||||||
|
|
||||||
|
elif method == 'eth_signTransaction':
|
||||||
|
params = PlatformMiddleware._translate_params(suspect_params)
|
||||||
|
s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0)
|
||||||
|
ipc_provider_workaround = s.connect(self.ipcaddr)
|
||||||
|
logg.info('redirecting method {} params {} original params {}'.format(method, params, suspect_params))
|
||||||
|
o = jsonrpc_request(method, params[0])
|
||||||
|
j = json.dumps(o)
|
||||||
|
logg.debug('send {}'.format(j))
|
||||||
|
s.send(j.encode('utf-8'))
|
||||||
|
r = s.recv(4096)
|
||||||
|
s.close()
|
||||||
|
logg.debug('got recv {}'.format(str(r)))
|
||||||
|
jr = json.loads(r)
|
||||||
|
jr['id'] = self.id_seq
|
||||||
|
#return str(json.dumps(jr))
|
||||||
|
return jr
|
||||||
|
|
||||||
|
elif method == 'eth_sign':
|
||||||
|
params = PlatformMiddleware._translate_params(suspect_params)
|
||||||
|
s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0)
|
||||||
|
ipc_provider_workaround = s.connect(self.ipcaddr)
|
||||||
|
logg.info('redirecting method {} params {} original params {}'.format(method, params, suspect_params))
|
||||||
|
o = jsonrpc_request(method, params)
|
||||||
|
j = json.dumps(o)
|
||||||
|
logg.debug('send {}'.format(j))
|
||||||
|
s.send(j.encode('utf-8'))
|
||||||
|
r = s.recv(4096)
|
||||||
|
s.close()
|
||||||
|
logg.debug('got recv {}'.format(str(r)))
|
||||||
|
jr = json.loads(r)
|
||||||
|
jr['id'] = self.id_seq
|
||||||
|
return jr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r = self.make_request(method, suspect_params)
|
||||||
|
return r
|
46
funga/keystore.py
Normal file
46
funga/keystore.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# standard imports
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Keystore:
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, private_key_generator, private_key_parser, keystore_parser):
|
||||||
|
self.private_key_generator = private_key_generator
|
||||||
|
self.private_key_parser = private_key_parser
|
||||||
|
self.keystore_parser = keystore_parser
|
||||||
|
|
||||||
|
|
||||||
|
def get(self, address, password=None):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
def new(self, password=None):
|
||||||
|
self.private_key_generator(password=password)
|
||||||
|
|
||||||
|
|
||||||
|
def import_raw_key(self, b, password=None):
|
||||||
|
pk = self.private_key_parser(b)
|
||||||
|
return self.import_key(pk, password)
|
||||||
|
|
||||||
|
|
||||||
|
def import_key(self, pk, password=None):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
def import_keystore_data(self, keystore_content, password=''):
|
||||||
|
private_key = self.keystore_parser(keystore_content, password.encode('utf-8'))
|
||||||
|
return self.import_raw_key(private_key, password=password)
|
||||||
|
|
||||||
|
|
||||||
|
def import_keystore_file(self, keystore_file, password=''):
|
||||||
|
private_key = self.keystore_parser(keystore_file, password)
|
||||||
|
return self.import_raw_key(private_key, password=password)
|
8
funga/signer.py
Normal file
8
funga/signer.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
class Signer:
|
||||||
|
|
||||||
|
def __init__(self, keyGetter):
|
||||||
|
self.keyGetter = keyGetter
|
||||||
|
|
||||||
|
|
||||||
|
def sign_transaction(self, tx, password=None):
|
||||||
|
return NotImplementedError
|
22
setup.py
22
setup.py
@ -32,18 +32,18 @@ while True:
|
|||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="crypto-dev-signer",
|
name="funga",
|
||||||
version="0.4.15a7",
|
version="0.5.1a1",
|
||||||
description="A signer and keystore daemon and library for cryptocurrency software development",
|
description="A signer and keystore daemon and library for cryptocurrency software development",
|
||||||
author="Louis Holbrook",
|
author="Louis Holbrook",
|
||||||
author_email="dev@holbrook.no",
|
author_email="dev@holbrook.no",
|
||||||
packages=[
|
packages=[
|
||||||
'crypto_dev_signer.eth.signer',
|
'funga.eth.signer',
|
||||||
'crypto_dev_signer.eth',
|
'funga.eth',
|
||||||
'crypto_dev_signer.cli',
|
'funga.cli',
|
||||||
'crypto_dev_signer.keystore',
|
'funga.keystore',
|
||||||
'crypto_dev_signer.runnable',
|
'funga.runnable',
|
||||||
'crypto_dev_signer',
|
'funga',
|
||||||
],
|
],
|
||||||
install_requires=requirements,
|
install_requires=requirements,
|
||||||
extras_require={
|
extras_require={
|
||||||
@ -54,9 +54,9 @@ setup(
|
|||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
entry_points = {
|
entry_points = {
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'crypto-dev-daemon=crypto_dev_signer.runnable.signer:main',
|
'crypto-dev-daemon=funga.runnable.signer:main',
|
||||||
'eth-keyfile=crypto_dev_signer.runnable.keyfile:main',
|
'eth-keyfile=funga.runnable.keyfile:main',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
url='https://gitlab.com/chaintool/crypto-dev-signer',
|
url='https://gitlab.com/chaintool/funga',
|
||||||
)
|
)
|
||||||
|
@ -13,9 +13,9 @@ from hexathon import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from crypto_dev_signer.keystore.dict import DictKeystore
|
from funga.error import UnknownAccountError
|
||||||
from crypto_dev_signer.error import UnknownAccountError
|
from funga.eth.keystore.dict import DictKeystore
|
||||||
from crypto_dev_signer.eth.signer import ReferenceSigner
|
from funga.eth.signer import EIP155Signer
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
logg = logging.getLogger()
|
logg = logging.getLogger()
|
||||||
@ -53,7 +53,7 @@ class TestDict(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
def test_sign_message(self):
|
def test_sign_message(self):
|
||||||
s = ReferenceSigner(self.db)
|
s = EIP155Signer(self.db)
|
||||||
z = s.sign_ethereum_message(strip_0x(self.address_hex), b'foo')
|
z = s.sign_ethereum_message(strip_0x(self.address_hex), b'foo')
|
||||||
logg.debug('zzz {}'.format(str(z)))
|
logg.debug('zzz {}'.format(str(z)))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user