Skip to content

Set gas limit according to TxPermission.blockGasLimit.#140

Merged
varasev merged 4 commits into
aura-posfrom
afck-gas-limit
Jul 15, 2019
Merged

Set gas limit according to TxPermission.blockGasLimit.#140
varasev merged 4 commits into
aura-posfrom
afck-gas-limit

Conversation

@afck
Copy link
Copy Markdown
Collaborator

@afck afck commented Jun 4, 2019

WIP: This passes the posdao-test-setup, but both the low and the regular gas limits are still hard-coded, and the call in verify_header_params uses the wrong header at the moment. (See TODOs.)

It also extends the Engine trait in a way that's not exactly sane. And it doesn't allow for a variable gas limit.

And crucially, I don't know yet whether the state of the block hash that we use for the limitBlockGas call is always available in the client's database, especially if there's a fork; or whether and how this will work together with snapshots and warp sync.

Closes #119.

@varasev
Copy link
Copy Markdown
Member

varasev commented Jun 4, 2019

Can we first try to do the same without calling the TxPermission.limitBlockGas()? Just imagine that for, e.g., 200-blocks staking epoch the gas limit should be decreased starting from the block 161 and should be restored after the block 239 (then for the second staking epoch the band is 361...439, and so on).

@afck
Copy link
Copy Markdown
Collaborator Author

afck commented Jun 4, 2019

Right, that would make things easier; basically we could just implement a configurable gas limit schedule, so one could write something like this into the chain spec:

"gasLimitSchedule": {
  "period": "200",
  "defaultLimit": "8000000",
  "schedule": [
    { "from": "161", "to": "200", "limit": "2000000" },
    { "from": "0", "to": "239", "limit": "2000000" }
  ]
}

@varasev
Copy link
Copy Markdown
Member

varasev commented Jun 4, 2019

The formula for those bands is: limit the block gas when the current block number

is greater than

stakingEpochEndBlock() - MAX_VALIDATORS * DELEGATORS_ALIQUOT - 1

or is less than

stakingEpochStartBlock() + MAX_VALIDATORS * DELEGATORS_ALIQUOT + 1

It would be equivalent of calling the TxPermission.limitBlockGas().

So, these values can be read once per staking epoch and used statically in Parity code.

What do you think about it?

@afck
Copy link
Copy Markdown
Collaborator Author

afck commented Jun 4, 2019

Or that, yes.
But it would be even easier to implement if we didn't have to ask the contract at all.

@varasev
Copy link
Copy Markdown
Member

varasev commented Jun 5, 2019

We could make in Parity a function like that:

fn limit_block_gas(block_number: U256) -> bool {
    if staking_epoch_duration <= 0 || max_validators <= 0 || delegators_aliquot <= 0 {
        return false;
    }

    let staking_epoch = block_number / staking_epoch_duration;

    let from = staking_epoch_duration * staking_epoch + max_validators * delegators_aliquot + 1;
    let to = staking_epoch_duration * (staking_epoch + 1) - max_validators * delegators_aliquot - 1;

    if block_number <= from || block_number >= to {
        true
    } else {
        false
    }
}

where

staking_epoch_duration is a constant taken from the stakingEpochDuration getter;
max_validators is a constant taken from the MAX_VALIDATORS getter;
delegators_aliquot is a constant taken from the DELEGATORS_ALIQUOT getter.

I think we should read these constant values from the contracts anyway because in case of writing their values to spec.json their values will be duplicated with those which are defined in the contracts.

This approach assumes that those constants and the formula will never be changed during the network's life.

@afck
Copy link
Copy Markdown
Collaborator Author

afck commented Jun 6, 2019

But then we might as well just call limitBlockGas directly, at just the correct block number (possibly a sibling), and assume that it only depends on the block number. That's a weaker requirement for the contract and moves less of the contract's implementation details into Parity than using those constants.

Still, I think the cleanest approach would be if we'd manage to call the function really at the right block. I'll try to dig through the code some more and see if we can do that.

@afck
Copy link
Copy Markdown
Collaborator Author

afck commented Jun 6, 2019

We also need to make a decision regarding the gas limit values if the function returns true or false. I don't like hard-coding values, and we can't e.g. use the target gas limit when switching back from true to false, because that's a per-node configuration, not part of the chain spec.

We could change limitBlockGas to gasLimit: Have the function return the gas limit for the current block itself? (Or for the next block, depending on where exactly we manage to call it…)

@varasev
Copy link
Copy Markdown
Member

varasev commented Jun 6, 2019

Ok, let's change the function so that it would return gas limit instead of boolean value. Let's do this after you ensure that we can call the function at the right block (as you wrote above).

@afck
Copy link
Copy Markdown
Collaborator Author

afck commented Jun 6, 2019

In Client::check_and_lock_block, the function that checks the gas limit, verify_block_family, is called before the new state is computed. But the good news is that at this point it is already required that the parent block's state is in the database, because enact_verified would fail with InvalidStateRoot otherwise.

We could:

  • Change the order; but it's probably like this for a reason: if the gas limit can be checked without the state, it should be done first, to avoid the overhead of enacting an invalid block.
  • Make the call at the parent block's state. (What this PR currently does.) We'd need to modify limitBlockGas or gasLimit to return the gas limit for the next block.
  • Use the parent block's state and make the call with a modified env info: I think this corresponds to making the call at the beginning of the next block, and the contract function would then see the correct (i.e. the new block's) block number. Not sure how complicated that is.

We should also decide what to do in terms of backward compatibility:

  • We could just make the contract call, and if it fails (because the contract doesn't have that function), we go with the default behavior.
  • We could add another transition for this. (contractBasedGasLimitTransition?)

@varasev
Copy link
Copy Markdown
Member

varasev commented Jun 6, 2019

Let's postpone this task a while, I'll try to repeat stress tests again and recheck those 80 blocks when switching staking epoch to see more closely how it is critical to have reduced gas limit.

@afck afck force-pushed the afck-gas-limit branch from bb21c57 to 6f0abad Compare July 4, 2019 09:14
@afck
Copy link
Copy Markdown
Collaborator Author

afck commented Jul 4, 2019

I implemented the third option: blockGasLimit is now called before each new block, but with the new block's number.

@afck afck marked this pull request as ready for review July 4, 2019 09:14
@afck afck changed the title Lower gas limit if TxPermission.limitBlockGas. Set gas limit according to TxPermission.blockGasLimit. Jul 4, 2019
@afck
Copy link
Copy Markdown
Collaborator Author

afck commented Jul 4, 2019

As discussed, I will add a separate blockGasLimitContract option for this.
I will probably also move it out of the engine, since it is not Aura-specific. (That's not as easy as I had hoped…)

@afck afck force-pushed the afck-gas-limit branch from 6f0abad to 1cc59a7 Compare July 4, 2019 12:03
@afck afck force-pushed the afck-gas-limit branch from 1cc59a7 to 07cbf84 Compare July 4, 2019 13:00
@varasev varasev self-requested a review July 5, 2019 06:31
Copy link
Copy Markdown
Member

@varasev varasev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works fine 👍

@varasev varasev merged commit 31e72e2 into aura-pos Jul 15, 2019
@afck afck deleted the afck-gas-limit branch July 22, 2019 11:03
Comment thread ethcore/src/engines/authority_round/mod.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reduced block gas limit when TxPermission.limitBlockGas() returns true

3 participants