Skip to content

Commit

Permalink
Merge pull request #838 from eth-brownie/feat-chain
Browse files Browse the repository at this point in the history
Add `timestamp` kwarg to `chain.mine`
  • Loading branch information
iamdefinitelyahuman authored Nov 4, 2020
2 parents 85442b3 + d5421cd commit 1c7d2da
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
24 changes: 22 additions & 2 deletions brownie/network/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ def __getitem__(self, block_number: int) -> BlockData:
self._block_gas_time = block["timestamp"]
return block

def __iter__(self) -> Iterator:
return iter(web3.eth.getBlock(i) for i in range(web3.eth.blockNumber + 1))

def new_blocks(self, height_buffer: int = 0, poll_interval: int = 5) -> Iterator:
"""
Generator for iterating over new blocks.
Expand Down Expand Up @@ -315,14 +318,18 @@ def sleep(self, seconds: int) -> None:
self._redo_buffer.clear()
self._current_id = self._snap()

def mine(self, blocks: int = 1) -> int:
def mine(self, blocks: int = 1, timestamp: Optional[int] = None) -> int:
"""
Increase the block height within the test RPC.
Arguments
---------
blocks : int
Number of new blocks to be mined
timestamp : int
Timestamp of the final block being mined. If multiple blocks
are mined, they will be placed at equal intervals starting
at `chain.time()` and ending at `timestamp`.
Returns
-------
Expand All @@ -331,8 +338,21 @@ def mine(self, blocks: int = 1) -> int:
"""
if not isinstance(blocks, int):
raise TypeError("blocks must be an integer value")

if timestamp is None:
params: List = [[] for i in range(blocks)]
elif blocks == 1:
params = [[timestamp]]
else:
now = self.time()
duration = (timestamp - now) / (blocks - 1)
params = [[round(now + duration * i)] for i in range(blocks)]

for i in range(blocks):
self._request("evm_mine", [])
self._request("evm_mine", params[i])

if timestamp is not None:
self.sleep(0)

self._redo_buffer.clear()
self._current_id = self._snap()
Expand Down
3 changes: 2 additions & 1 deletion docs/api-network.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1685,11 +1685,12 @@ Chain Methods
>>> chain.time()
1550189143
.. py:method:: Chain.mine(blocks=1)
.. py:method:: Chain.mine(blocks=1, timestamp=None)
Mine one or more empty blocks.

* ``blocks``: Number of blocks to mine
* ``timestamp``: Timestamp of the final block being mined. If multiple blocks are mined, they will be mined at equal intervals starting from :ref:`chain.time <Chain.time>` and ending at ``timestamp``.

Returns the block height after all new blocks have been mined.

Expand Down
19 changes: 19 additions & 0 deletions tests/network/state/test_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,22 @@ def test_getitem_positive_index(devnetwork, accounts, chain, web3):

assert chain[0] == block
assert chain[0] != web3.eth.getBlock("latest")


def test_mine_timestamp(devnetwork, chain):
chain.mine(timestamp=12345)

assert chain[-1].timestamp == 12345
assert chain.time() - 12345 < 3


def test_mine_multiple_timestamp(devnetwork, chain):
chain.mine(5, timestamp=chain.time() + 123)
timestamps = [i.timestamp for i in list(chain)[-5:]]

assert chain.time() - timestamps[-1] < 3

for i in range(1, 5):
assert timestamps[i] > timestamps[i - 1]

assert timestamps[0] + 123 == timestamps[-1]

0 comments on commit 1c7d2da

Please sign in to comment.