From b96369834c758de08f27bfdbe0c696b18aba0cce Mon Sep 17 00:00:00 2001 From: Piper Merriam Date: Mon, 1 May 2017 08:41:18 -0600 Subject: [PATCH] 3.8.1 Release --- CHANGELOG | 7 + setup.py | 2 +- .../test_private_key_signing_manager.py | 79 ------ web3/main.py | 4 - web3/providers/manager.py | 234 ------------------ 5 files changed, 8 insertions(+), 318 deletions(-) delete mode 100644 tests/managers/test_private_key_signing_manager.py diff --git a/CHANGELOG b/CHANGELOG index ed3a480..88ba58b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +3.8.1 +----- + +* Bugfix for `eth_sign` double hashing input. +* Removed deprecated `DelegatedSigningManager` +* Removed deprecate `PrivateKeySigningManager` + 3.8.0 ----- diff --git a/setup.py b/setup.py index 93e4817..fe34cf9 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ if sys.platform == 'win32': setup( name='web3', - version='3.8.0', + version='3.8.1', description="""Web3.py""", long_description=readme, author='Piper Merriam', diff --git a/tests/managers/test_private_key_signing_manager.py b/tests/managers/test_private_key_signing_manager.py deleted file mode 100644 index a097b43..0000000 --- a/tests/managers/test_private_key_signing_manager.py +++ /dev/null @@ -1,79 +0,0 @@ -import pytest - -from eth_utils import ( - denoms, - to_normalized_address, - decode_hex, -) - -from web3.providers.manager import ( - PrivateKeySigningManager, -) - -from testrpc.client.utils import ( - mk_random_privkey, - encode_address, -) - - -@pytest.fixture() -def account_private_key(): - return mk_random_privkey() - - -@pytest.fixture() -def account_public_key(account_private_key): - from ethereum.utils import privtoaddr - return to_normalized_address(encode_address(privtoaddr(account_private_key))) - - -@pytest.fixture() -def web3_pk_signer(web3, - account_public_key, - account_private_key, - wait_for_block, - wait_for_transaction): - pk_signing_manager = PrivateKeySigningManager(web3._requestManager) - pk_signing_manager.register_private_key(account_private_key) - assert account_public_key in pk_signing_manager.keys - - wait_for_block(web3) - - fund_txn_hash = web3.eth.sendTransaction({ - 'from': web3.eth.coinbase, - 'to': account_public_key, - 'value': 10 * denoms.ether, - }) - wait_for_transaction(web3, fund_txn_hash) - - web3._requestManager = pk_signing_manager - return web3 - - -def test_private_key_signing_manager(web3_pk_signer, - account_private_key, - account_public_key, - wait_for_transaction): - web3 = web3_pk_signer - assert account_public_key not in web3_pk_signer.eth.accounts - - with pytest.raises(ValueError): - web3.eth.sendTransaction({ - 'from': account_public_key, - 'to': web3.eth.coinbase, - 'value': 1, - }) - - from ethereum import tester - tester.keys.append(account_private_key) - tester.accounts.append(decode_hex(account_public_key)) - - txn_hash = web3.eth.sendTransaction({ - 'from': account_public_key, - 'to': web3.eth.coinbase, - 'value': 1, - }) - txn_receipt = wait_for_transaction(web3, txn_hash) - txn = web3.eth.getTransaction(txn_hash) - - assert txn['from'] == account_public_key diff --git a/web3/main.py b/web3/main.py index c4bab25..c066850 100644 --- a/web3/main.py +++ b/web3/main.py @@ -40,8 +40,6 @@ from web3.providers.ipc import ( ) from web3.providers.manager import ( RequestManager, - DelegatedSigningManager, - PrivateKeySigningManager, ) from web3.utils.encoding import ( @@ -62,8 +60,6 @@ class Web3(object): # Managers RequestManager = RequestManager - DelegatedSigningManager = DelegatedSigningManager - PrivateKeySigningManager = PrivateKeySigningManager # Iban Iban = Iban diff --git a/web3/providers/manager.py b/web3/providers/manager.py index 84b7f89..dcda92e 100644 --- a/web3/providers/manager.py +++ b/web3/providers/manager.py @@ -1,29 +1,12 @@ -import collections import json import uuid -import warnings - -import rlp from eth_utils import ( - decode_hex, - encode_hex, force_text, is_dict, is_string, - keccak, - to_normalized_address, ) -from web3.utils.encoding import ( - to_decimal, -) -from web3.utils.transactions import ( - is_bitcoin_available, - Transaction, - serialize_transaction, - add_signature_to_transaction, -) from web3.utils.compat import ( spawn, ) @@ -79,220 +62,3 @@ class RequestManager(object): def receive_async(self, request_id, *args, **kwargs): raise NotImplementedError("Callback pattern not implemented") - - -class ManagerWrapper(object): - def __init__(self, wrapped_manager): - warnings.warn(DeprecationWarning( - "ManagerWrapper has been deprecated and will be removed from" - "web3.py in subsequen releases." - )) - self.wrapped_manager = wrapped_manager - - @property - def provider(self): - return self.wrapped_manager.provider - - @property - def pending_requests(self): - return self.wrapped_manager.pending_requests - - def setProvider(self, provider): - self.wrapped_manager.provider = provider - - def request_blocking(self, *args, **kwargs): - return self.wrapped_manager.request_blocking(*args, **kwargs) - - def request_async(self, *args, **kwargs): - return self.wrapped_manager.request_async(*args, **kwargs) - - def receive_blocking(self, *args, **kwargs): - return self.wrapped_manager.receive_blocking(*args, **kwargs) - - def receive_async(self, *args, **kwargs): - return self.wrapped_manager.receive_async(*args, **kwargs) - - -class BaseSendRawTransactionMixin(ManagerWrapper): - _known_transactions = None - _known_nonces = None - - def __init__(self, *args, **kwargs): - self._known_transactions = collections.defaultdict(set) - self._known_nonces = collections.defaultdict(set) - super(BaseSendRawTransactionMixin, self).__init__(*args, **kwargs) - - def _get_nonces_and_cleanup(self, addr, chain_nonce): - all_txns = { - txn_hash: self.request_blocking( - 'eth_getTransactionByHash', - [txn_hash], - ) for txn_hash in self._known_transactions[addr] - } - for txn_hash, txn in all_txns.items(): - if txn is None: - continue - txn_nonce = to_decimal(txn['nonce']) - if txn_nonce < chain_nonce: - self._known_transactions[addr].discard(txn_hash) - else: - yield txn_nonce - - all_known_nonces = tuple(self._known_nonces[addr]) - for nonce in all_known_nonces: - if nonce < chain_nonce: - self._known_nonces[addr].discard(nonce) - else: - yield nonce - - def get_chain_nonce(self, addr): - chain_nonce = to_decimal(self.request_blocking( - 'eth_getTransactionCount', - [addr, 'pending'] - )) - return chain_nonce - - def get_nonce(self, addr): - chain_nonce = self.get_chain_nonce(addr) - tracked_txn_nonces = tuple(self._get_nonces_and_cleanup(addr, chain_nonce)) - nonce = max(0, chain_nonce, *tracked_txn_nonces) - if nonce == 0 and not tracked_txn_nonces: - return -1 - else: - return nonce - - def get_transaction_signature(self, serialized_txn): - raise NotImplementedError("Must be implemented by subclasses") - - def sign_and_serialize_transaction(self, transaction): - serialized_txn = serialize_transaction(transaction) - signature = self.get_transaction_signature(transaction) - signed_transaction = add_signature_to_transaction( - serialized_txn, - signature, - ) - signed_and_serialized_txn = rlp.encode(signed_transaction, Transaction) - return signed_and_serialized_txn - - def construct_full_transaction(self, base_transaction): - txn_from = base_transaction['from'] - full_txn = dict(**base_transaction) - full_txn.setdefault('nonce', self.get_nonce(txn_from) + 1) - full_txn.setdefault('gasPrice', self.request_blocking( - 'eth_gasPrice', [] - )) - full_txn.setdefault('gas', hex(90000)) - full_txn.setdefault('value', '0x0') - full_txn.setdefault('to', '') - full_txn.setdefault('data', '') - return full_txn - - TXN_SENDING_METHODS = { - 'eth_sendTransaction', - 'eth_sendRawTransaction', - 'personal_signAndSendTransaction', - 'personal_sendTransaction', - } - - def request_blocking(self, method, params): - if method == 'eth_sendTransaction': - base_transaction = params[0] - # create a fully signed transaction and send through the - # `eth_sendRawTransaction` endpoint instead. - full_transaction = self.construct_full_transaction(base_transaction) - raw_transaction_bytes = self.sign_and_serialize_transaction( - full_transaction, - ) - raw_transaction_bytes_as_hex = encode_hex(raw_transaction_bytes) - return self.request_blocking( - 'eth_sendRawTransaction', [raw_transaction_bytes_as_hex], - ) - - result = super(BaseSendRawTransactionMixin, self).request_blocking( - method, params, - ) - if method in self.TXN_SENDING_METHODS: - if method == 'eth_sendRawTransaction': - txn = rlp.decode(decode_hex(params[0]), Transaction) - self._known_transactions[to_normalized_address(txn.sender)].add(result) - self._known_nonces[to_normalized_address(txn.sender)].add(txn.nonce) - else: - txn = params[0] - self._known_transactions[to_normalized_address(txn['from'])].add(result) - if 'nonce' in txn: - self._known_nonces[to_normalized_address(txn['from'])].add( - to_decimal(txn['nonce']) - ) - return result - - -class DelegatedSigningManager(BaseSendRawTransactionMixin): - def __init__(self, *args, **kwargs): - warnings.warn(DeprecationWarning( - "DelegatedSigningManager has been deprecated and will be removed from" - "web3.py in subsequen releases." - )) - self.signing_manager = kwargs.pop('signing_manager') - super(DelegatedSigningManager, self).__init__(*args, **kwargs) - - def get_chain_nonce(self, addr): - signer_nonce = to_decimal(self.signing_manager.request_blocking( - 'eth_getTransactionCount', - [addr, 'pending'] - )) - wrapped_nonce = to_decimal(self.wrapped_manager.request_blocking( - 'eth_getTransactionCount', - [addr, 'pending'] - )) - return max(signer_nonce, wrapped_nonce) - - def get_transaction_signature(self, transaction): - serialized_txn = serialize_transaction(transaction) - hash_to_sign = self.signing_manager.request_blocking( - 'web3_sha3', [encode_hex(serialized_txn)], - ) - signature_hex = self.signing_manager.request_blocking( - 'eth_sign', - [ - transaction['from'], - hash_to_sign, - ], - ) - signature = decode_hex(signature_hex) - return signature - - -class PrivateKeySigningManager(BaseSendRawTransactionMixin): - def __init__(self, *args, **kwargs): - warnings.warn(DeprecationWarning( - "PrivateKeySigningManager has been deprecated and will be removed from" - "web3.py in subsequen releases." - )) - if not is_bitcoin_available(): - raise ImportError( - "In order to use the `PrivateKeySigningManager` the " - "`bitcoin` and `secp256k1` packages must be installed." - ) - self.keys = kwargs.pop('keys', {}) - super(PrivateKeySigningManager, self).__init__(*args, **kwargs) - - def register_private_key(self, key): - from bitcoin import privtopub - address = to_normalized_address(keccak(privtopub(key)[1:])[-20:]) - self.keys[address] = key - - def sign_and_serialize_transaction(self, transaction): - txn_from = to_normalized_address(transaction['from']) - if txn_from not in self.keys: - raise KeyError("No signing key registered for from address: {0}".format(txn_from)) - transaction = Transaction( - nonce=to_decimal(transaction['nonce']), - gasprice=to_decimal(transaction['gasPrice']), - startgas=to_decimal(transaction['gas']), - to=transaction['to'], - value=to_decimal(transaction['value']), - data=decode_hex(transaction['data']), - ) - transaction.sign(self.keys[txn_from]) - assert to_normalized_address(transaction.sender) == txn_from - return rlp.encode(transaction, Transaction)