Skip to content

Commit

Permalink
Benchmark send_transaction and get_block
Browse files Browse the repository at this point in the history
  • Loading branch information
kclowes committed Jun 4, 2021
1 parent 17264b4 commit b596263
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 78 deletions.
2 changes: 1 addition & 1 deletion web3/_utils/module_testing/eth_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ async def test_eth_getBlockByNumber_not_found(
self, async_w3: "Web3", empty_block: BlockData
) -> None:
with pytest.raises(BlockNotFound):
await async_w3.async_eth.get_block(BlockNumber(12345))
await async_w3.async_eth.get_block(BlockNumber(12345))

@pytest.mark.asyncio
async def test_eth_getBlockByNumber_pending(
Expand Down
12 changes: 8 additions & 4 deletions web3/_utils/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

if TYPE_CHECKING:
from web3 import Web3 # noqa: F401
from web3.eth import AsyncEth, Eth # noqa: F401


@curry
Expand Down Expand Up @@ -112,15 +113,15 @@ def wait_for_transaction_receipt(
return txn_receipt


def get_block_gas_limit(web3_eth: "Web3", block_identifier: Optional[BlockIdentifier] = None) -> Wei:
def get_block_gas_limit(web3_eth: "Eth", block_identifier: Optional[BlockIdentifier] = None) -> Wei:
if block_identifier is None:
block_identifier = web3_eth.block_number
block = web3_eth.get_block(block_identifier)
return block['gasLimit']


def get_buffered_gas_estimate(
web3_eth: "Web3", transaction: TxParams, gas_buffer: Wei = Wei(100000)
web3_eth: "Eth", transaction: TxParams, gas_buffer: Wei = Wei(100000)
) -> Wei:
gas_estimate_transaction = cast(TxParams, dict(**transaction))

Expand All @@ -138,14 +139,17 @@ def get_buffered_gas_estimate(
return Wei(min(gas_limit, gas_estimate + gas_buffer))


async def async_get_block_gas_limit(web3_eth: "Web3", block_identifier: Optional[BlockIdentifier] = None) -> Wei:
async def async_get_block_gas_limit(
web3_eth: "AsyncEth", block_identifier: Optional[BlockIdentifier] = None
) -> Wei:
if block_identifier is None:
block_identifier = await web3_eth.block_number
block = await web3_eth.get_block(block_identifier)
return block['gasLimit']


async def async_get_buffered_gas_estimate(
web3_eth: "Web3", transaction: TxParams, gas_buffer: Wei = Wei(100000)
web3_eth: "AsyncEth", transaction: TxParams, gas_buffer: Wei = Wei(100000)
) -> Wei:
gas_estimate_transaction = cast(TxParams, dict(**transaction))

Expand Down
53 changes: 22 additions & 31 deletions web3/eth.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
from web3._utils.transactions import (
assert_valid_transaction_params,
extract_valid_transaction_params,
get_buffered_gas_estimate,
get_required_transaction,
replace_transaction,
wait_for_transaction_receipt,
Expand Down Expand Up @@ -121,13 +120,6 @@ def send_transaction_munger(self, transaction: TxParams) -> Tuple[TxParams]:
if 'from' not in transaction and is_checksum_address(self.default_account):
transaction = assoc(transaction, 'from', self.default_account)

# TODO: move gas estimation in middleware
# if 'gas' not in transaction:
# transaction = assoc(
# transaction,
# 'gas',
# get_buffered_gas_estimate(self.web3, transaction),
# )
return (transaction,)

_send_transaction: Method[Callable[[TxParams], HexBytes]] = Method(
Expand Down Expand Up @@ -186,11 +178,16 @@ def get_block_munger(
mungers=[get_block_munger],
)

_get_block_number: Method[Callable[[], BlockNumber]] = Method(
get_block_number: Method[Callable[[], BlockNumber]] = Method(
RPC.eth_blockNumber,
mungers=None,
)

get_coinbase: Method[Callable[[], ChecksumAddress]] = Method(
RPC.eth_coinbase,
mungers=None,
)


class AsyncEth(BaseEth):
is_async = True
Expand All @@ -201,9 +198,11 @@ async def gas_price(self) -> Wei:
return await self._gas_price() # type: ignore

async def send_transaction(self, transaction: TxParams) -> HexBytes:
# types ignored b/c mypy conflict with BlockingEth properties
return await self._send_transaction(transaction) # type: ignore

async def get_transaction(self, transaction_hash: _Hash32) -> TxData:
# types ignored b/c mypy conflict with BlockingEth properties
return await self._get_transaction(transaction_hash) # type: ignore

async def generate_gas_price(
Expand All @@ -216,16 +215,24 @@ async def estimate_gas(
transaction: TxParams,
block_identifier: Optional[BlockIdentifier] = None
) -> Wei:
return await self._estimate_gas(transaction, block_identifier)
# types ignored b/c mypy conflict with BlockingEth properties
return await self._estimate_gas(transaction, block_identifier) # type: ignore

async def get_block(
self, block_identifier: BlockIdentifier, full_transactions: bool = False
) -> BlockData:
return await self._get_block(block_identifier, full_transactions)
# types ignored b/c mypy conflict with BlockingEth properties
return await self._get_block(block_identifier, full_transactions) # type: ignore

@property
async def block_number(self) -> BlockNumber:
return await self._get_block_number()
# types ignored b/c mypy conflict with BlockingEth properties
return await self.get_block_number() # type: ignore

@property
async def coinbase(self) -> ChecksumAddress:
# types ignored b/c mypy conflict with BlockingEth properties
return await self.get_coinbase() # type: ignore


class Eth(BaseEth, Module):
Expand Down Expand Up @@ -270,11 +277,6 @@ def protocolVersion(self) -> str:
def syncing(self) -> Union[SyncStatus, bool]:
return self.is_syncing()

get_coinbase: Method[Callable[[], ChecksumAddress]] = Method(
RPC.eth_coinbase,
mungers=None,
)

@property
def coinbase(self) -> ChecksumAddress:
return self.get_coinbase()
Expand Down Expand Up @@ -318,14 +320,9 @@ def gasPrice(self) -> Wei:
def accounts(self) -> Tuple[ChecksumAddress]:
return self.get_accounts()

# get_block_number: Method[Callable[[], BlockNumber]] = Method(
# RPC.eth_blockNumber,
# mungers=None,
# )

@property
def block_number(self) -> BlockNumber:
return self._get_block_number()
return self.get_block_number()

@property
def blockNumber(self) -> BlockNumber:
Expand Down Expand Up @@ -633,12 +630,6 @@ def call_munger(
mungers=[call_munger]
)


# estimate_gas: Method[Callable[..., Wei]] = Method(
# RPC.eth_estimateGas,
# mungers=[estimate_gas_munger]
# )

def estimate_gas(
self,
transaction: TxParams,
Expand Down Expand Up @@ -763,7 +754,7 @@ def setGasPriceStrategy(self, gas_price_strategy: GasPriceStrategy) -> None:
# Deprecated Methods
getBalance = DeprecatedMethod(get_balance, 'getBalance', 'get_balance')
getStorageAt = DeprecatedMethod(get_storage_at, 'getStorageAt', 'get_storage_at')
getBlock = DeprecatedMethod(get_block, 'getBlock', 'get_block')
getBlock = DeprecatedMethod(get_block, 'getBlock', 'get_block') # type: ignore
getBlockTransactionCount = DeprecatedMethod(get_block_transaction_count,
'getBlockTransactionCount',
'get_block_transaction_count')
Expand All @@ -788,7 +779,7 @@ def setGasPriceStrategy(self, gas_price_strategy: GasPriceStrategy) -> None:
submitHashrate = DeprecatedMethod(submit_hashrate, 'submitHashrate', 'submit_hashrate')
submitWork = DeprecatedMethod(submit_work, 'submitWork', 'submit_work')
getLogs = DeprecatedMethod(get_logs, 'getLogs', 'get_logs')
estimateGas = DeprecatedMethod(estimate_gas, 'estimateGas', 'estimate_gas')
estimateGas = DeprecatedMethod(estimate_gas, 'estimateGas', 'estimate_gas') # type: ignore
sendRawTransaction = DeprecatedMethod(send_raw_transaction,
'sendRawTransaction',
'send_raw_transaction')
Expand Down
6 changes: 4 additions & 2 deletions web3/middleware/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
from .attrdict import ( # noqa: F401
attrdict_middleware,
)
from .buffered_gas_estimate import ( # noqa: F401
async_buffered_gas_estimate_middleware,
buffered_gas_estimate_middleware,
)
from .cache import ( # noqa: F401
_latest_block_based_cache_middleware as latest_block_based_cache_middleware,
_simple_cache_middleware as simple_cache_middleware,
Expand Down Expand Up @@ -44,8 +48,6 @@
)
from .gas_price_strategy import ( # noqa: F401
async_gas_price_strategy_middleware,
async_buffered_gas_estimate_middleware,
buffered_gas_estimate_middleware,
gas_price_strategy_middleware,
)
from .geth_poa import ( # noqa: F401
Expand Down
57 changes: 57 additions & 0 deletions web3/middleware/buffered_gas_estimate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from typing import (
TYPE_CHECKING,
Any,
Callable,
Coroutine,
)

from eth_utils.toolz import (
assoc,
)

from web3._utils.transactions import (
async_get_buffered_gas_estimate,
get_buffered_gas_estimate,
)
from web3.types import (
RPCEndpoint,
RPCResponse,
)

if TYPE_CHECKING:
from web3 import Web3 # noqa: F401


def buffered_gas_estimate_middleware(
make_request: Callable[[RPCEndpoint, Any], Any], web3: "Web3"
) -> Callable[[RPCEndpoint, Any], RPCResponse]:
def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
if method == 'eth_sendTransaction':
transaction = params[0]
if 'gas' not in transaction:
transaction = assoc(
transaction,
'gas',
hex(get_buffered_gas_estimate(web3.eth, transaction)),
)
return make_request(method, [transaction])
return make_request(method, params)
return middleware


async def async_buffered_gas_estimate_middleware(
make_request: Callable[[RPCEndpoint, Any], Any], web3: "Web3"
) -> Callable[[RPCEndpoint, Any], Coroutine[Any, Any, RPCResponse]]:
async def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
if method == 'eth_sendTransaction':
transaction = params[0]
if 'gas' not in transaction:
gas_estimate = await async_get_buffered_gas_estimate(web3.async_eth, transaction)
transaction = assoc(
transaction,
'gas',
hex(gas_estimate)
)
return await make_request(method, [transaction])
return await make_request(method, params)
return middleware
36 changes: 0 additions & 36 deletions web3/middleware/gas_price_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
assoc,
)

from web3._utils.transactions import (
get_buffered_gas_estimate,
async_get_buffered_gas_estimate,
)
from web3.types import (
RPCEndpoint,
RPCResponse,
Expand Down Expand Up @@ -56,35 +52,3 @@ async def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
return await make_request(method, [transaction])
return await make_request(method, params)
return middleware

def buffered_gas_estimate_middleware(
make_request: Callable[[RPCEndpoint, Any], Any], web3: "Web3"
):
def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
if method == 'eth_sendTransaction':
transaction = params[0]
if 'gas' not in transaction:
transaction = assoc(
transaction,
'gas',
get_buffered_gas_estimate(web3.eth, transaction),
)
return make_request(method, [transaction])
return make_request(method, params)
return middleware

async def async_buffered_gas_estimate_middleware(
make_request: Callable[[RPCEndpoint, Any], Any], web3: "Web3"
):
def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
if method == 'eth_sendTransaction':
transaction = params[0]
if 'gas' not in transaction:
transaction = assoc(
transaction,
'gas',
async_get_buffered_gas_estimate(web3.async_eth, transaction),
)
return make_request(method, [transaction])
return make_request(method, params)
return middleware
Loading

0 comments on commit b596263

Please sign in to comment.