mirror of https://github.com/hyperledger/besu
NC-2147 Implement ConstantinopleFix hardfork (#601)
* create a new fork definition * make it constantinople without EIP-1283 * update tests where appropriate * Add PetersbergGasCalculator * Add fork ordering test * Add rinkeby Constantinople block * fix json config bug * add Ropsten constantinopleFix block * run reference tests * clique test genesis file violates block ordering rules Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>pull/2/head
parent
948e8fe443
commit
0e3f199ef5
@ -0,0 +1,56 @@ |
||||
/* |
||||
* Copyright 2018 ConsenSys AG. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
*/ |
||||
package tech.pegasys.pantheon.ethereum.mainnet; |
||||
|
||||
import tech.pegasys.pantheon.ethereum.core.Account; |
||||
import tech.pegasys.pantheon.ethereum.core.Gas; |
||||
import tech.pegasys.pantheon.util.uint.UInt256; |
||||
|
||||
/** |
||||
* Gas Calculator for Petersberg Hard Fork. Rollback EIP-1283. |
||||
* |
||||
* <p>Neither {@link TangerineWhistleGasCalculator} nor {@link SpuriousDragonGasCalculator} overrode |
||||
* these two methods so {@link FrontierGasCalculator} is the source. |
||||
*/ |
||||
public class ConstantinopleFixGasCalculator extends ConstantinopleGasCalculator { |
||||
|
||||
/** Same as {#link {@link FrontierGasCalculator#STORAGE_SET_GAS_COST} */ |
||||
private static final Gas STORAGE_SET_GAS_COST = Gas.of(20_000L); |
||||
/** Same as {#link {@link FrontierGasCalculator#STORAGE_RESET_GAS_COST} */ |
||||
private static final Gas STORAGE_RESET_GAS_COST = Gas.of(5_000L); |
||||
/** Same as {#link {@link FrontierGasCalculator#STORAGE_RESET_REFUND_AMOUNT} */ |
||||
private static final Gas STORAGE_RESET_REFUND_AMOUNT = Gas.of(15_000L); |
||||
|
||||
/** |
||||
* Same as {#link {@link FrontierGasCalculator#calculateStorageCost(Account, UInt256, UInt256)} |
||||
*/ |
||||
@Override |
||||
public Gas calculateStorageCost( |
||||
final Account account, final UInt256 key, final UInt256 newValue) { |
||||
return !newValue.isZero() && account.getStorageValue(key).isZero() |
||||
? STORAGE_SET_GAS_COST |
||||
: STORAGE_RESET_GAS_COST; |
||||
} |
||||
|
||||
/** |
||||
* Same as {#link {@link FrontierGasCalculator#calculateStorageRefundAmount(Account, UInt256, |
||||
* UInt256)} |
||||
*/ |
||||
@Override |
||||
public Gas calculateStorageRefundAmount( |
||||
final Account account, final UInt256 key, final UInt256 newValue) { |
||||
return newValue.isZero() && !account.getStorageValue(key).isZero() |
||||
? STORAGE_RESET_REFUND_AMOUNT |
||||
: Gas.ZERO; |
||||
} |
||||
} |
@ -0,0 +1,110 @@ |
||||
/* |
||||
* Copyright 2018 ConsenSys AG. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
*/ |
||||
package tech.pegasys.pantheon.ethereum.mainnet; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.when; |
||||
import static tech.pegasys.pantheon.util.uint.UInt256.ONE; |
||||
import static tech.pegasys.pantheon.util.uint.UInt256.ZERO; |
||||
|
||||
import tech.pegasys.pantheon.ethereum.core.Account; |
||||
import tech.pegasys.pantheon.ethereum.core.Gas; |
||||
import tech.pegasys.pantheon.util.uint.UInt256; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.junit.runners.Parameterized; |
||||
import org.junit.runners.Parameterized.Parameter; |
||||
import org.junit.runners.Parameterized.Parameters; |
||||
|
||||
@RunWith(Parameterized.class) |
||||
public class ConstantinopleFixSstoreGasTest { |
||||
|
||||
private static final UInt256 TWO = UInt256.of(2); |
||||
|
||||
private final ConstantinopleFixGasCalculator gasCalculator = new ConstantinopleFixGasCalculator(); |
||||
|
||||
@Parameters(name = "original: {0}, current: {1}, new: {2}") |
||||
public static Object[][] scenarios() { |
||||
return new Object[][] { |
||||
// Zero no-op
|
||||
{ZERO, ZERO, ZERO, Gas.of(5_000), Gas.ZERO}, |
||||
|
||||
// Zero fresh change
|
||||
{ZERO, ZERO, ONE, Gas.of(20_000), Gas.ZERO}, |
||||
|
||||
// Dirty, reset to zero
|
||||
{ZERO, ONE, ZERO, Gas.of(5_000), Gas.of(15_000)}, |
||||
|
||||
// Dirty, changed but not reset
|
||||
{ZERO, ONE, TWO, Gas.of(5_000), Gas.ZERO}, |
||||
|
||||
// Dirty no-op
|
||||
{ZERO, ONE, ONE, Gas.of(5_000), Gas.ZERO}, |
||||
|
||||
// Dirty, zero no-op
|
||||
{ONE, ZERO, ZERO, Gas.of(5_000), Gas.ZERO}, |
||||
|
||||
// Dirty, reset to non-zero
|
||||
{ONE, ZERO, ONE, Gas.of(20_000), Gas.ZERO}, |
||||
|
||||
// Fresh change to zero
|
||||
{ONE, ONE, ZERO, Gas.of(5_000), Gas.of(15_000)}, |
||||
|
||||
// Fresh change with all non-zero
|
||||
{ONE, ONE, TWO, Gas.of(5_000), Gas.ZERO}, |
||||
|
||||
// Dirty, clear originally set value
|
||||
{ONE, TWO, ZERO, Gas.of(5_000), Gas.of(15_000)}, |
||||
|
||||
// Non-zero no-op
|
||||
{ONE, ONE, ONE, Gas.of(5_000), Gas.ZERO}, |
||||
}; |
||||
} |
||||
|
||||
@Parameter public UInt256 originalValue; |
||||
|
||||
@Parameter(value = 1) |
||||
public UInt256 currentValue; |
||||
|
||||
@Parameter(value = 2) |
||||
public UInt256 newValue; |
||||
|
||||
@Parameter(value = 3) |
||||
public Gas expectedGasCost; |
||||
|
||||
@Parameter(value = 4) |
||||
public Gas expectedGasRefund; |
||||
|
||||
private final Account account = mock(Account.class); |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
when(account.getOriginalStorageValue(UInt256.ZERO)).thenReturn(originalValue); |
||||
when(account.getStorageValue(UInt256.ZERO)).thenReturn(currentValue); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldChargeCorrectGas() { |
||||
assertThat(gasCalculator.calculateStorageCost(account, UInt256.ZERO, newValue)) |
||||
.isEqualTo(expectedGasCost); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldRefundCorrectGas() { |
||||
assertThat(gasCalculator.calculateStorageRefundAmount(account, UInt256.ZERO, newValue)) |
||||
.isEqualTo(expectedGasRefund); |
||||
} |
||||
} |
Loading…
Reference in new issue