Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix'selfdestruct): immutable map #1337

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import net.consensys.linea.zktracer.module.hub.defer.PostTransactionDefer;
import net.consensys.linea.zktracer.module.hub.fragment.DomSubStampsSubFragment;
import net.consensys.linea.zktracer.module.hub.fragment.TraceFragment;
import net.consensys.linea.zktracer.module.hub.section.halt.EphemeralAccount;
import net.consensys.linea.zktracer.module.romlex.ContractMetadata;
import net.consensys.linea.zktracer.types.EWord;
import net.consensys.linea.zktracer.types.TransactionProcessingMetadata;
Expand Down Expand Up @@ -171,11 +172,10 @@ public Trace trace(Trace trace) {
@Override
public void resolvePostTransaction(
Hub hub, WorldView state, Transaction tx, boolean isSuccessful) {
final Map<TransactionProcessingMetadata.EphemeralAccount, Integer> effectiveSelfDestructMap =
final Map<EphemeralAccount, Integer> effectiveSelfDestructMap =
transactionProcessingMetadata.getEffectiveSelfDestructMap();
final TransactionProcessingMetadata.EphemeralAccount ephemeralAccount =
new TransactionProcessingMetadata.EphemeralAccount(
oldState.address(), oldState.deploymentNumber());
final EphemeralAccount ephemeralAccount =
new EphemeralAccount(oldState.address(), oldState.deploymentNumber());
if (effectiveSelfDestructMap.containsKey(ephemeralAccount)) {
final int selfDestructTime = effectiveSelfDestructMap.get(ephemeralAccount);
markedForSelfDestruct = hubStamp > selfDestructTime;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright ConsenSys Inc.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package net.consensys.linea.zktracer.module.hub.section.halt;

import net.consensys.linea.zktracer.runtime.callstack.CallFrame;

public record AttemptedSelfDestruct(int hubStamp, CallFrame callFrame) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright ConsenSys Inc.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/

package net.consensys.linea.zktracer.module.hub.section.halt;

import org.hyperledger.besu.datatypes.Address;

/**
* Ephemeral accounts are both accounts that have been deployed on-chain and accounts that live for
* a limited time
*/
public record EphemeralAccount(Address address, int deploymentNumber) {}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import static com.google.common.base.Preconditions.*;
import static net.consensys.linea.zktracer.module.hub.signals.Exceptions.OUT_OF_GAS_EXCEPTION;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

Expand All @@ -34,8 +35,6 @@
import net.consensys.linea.zktracer.module.hub.transients.DeploymentInfo;
import net.consensys.linea.zktracer.runtime.callstack.CallFrame;
import net.consensys.linea.zktracer.types.TransactionProcessingMetadata;
import net.consensys.linea.zktracer.types.TransactionProcessingMetadata.AttemptedSelfDestruct;
import net.consensys.linea.zktracer.types.TransactionProcessingMetadata.EphemeralAccount;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.hyperledger.besu.datatypes.Address;
Expand Down Expand Up @@ -138,23 +137,22 @@ public SelfdestructSection(Hub hub) {
}

// Unexceptional case
Map<EphemeralAccount, List<AttemptedSelfDestruct>> unexceptionalSelfDestructMap =
final Map<EphemeralAccount, ArrayList<AttemptedSelfDestruct>> unexceptionalSelfDestructMap =
hub.txStack().current().getUnexceptionalSelfDestructMap();

EphemeralAccount ephemeralAccount =
final EphemeralAccount ephemeralAccount =
new EphemeralAccount(
addressWhichMaySelfDestruct, selfdestructorAccountBefore.deploymentNumber());

if (unexceptionalSelfDestructMap.containsKey(ephemeralAccount)) {
List<AttemptedSelfDestruct> attemptedSelfDestructs =
unexceptionalSelfDestructMap.get(ephemeralAccount);
attemptedSelfDestructs.add(new AttemptedSelfDestruct(hubStamp, hub.currentFrame()));
// We do not need to put again the list in the map, as it is a reference
unexceptionalSelfDestructMap
.get(ephemeralAccount)
.add(new AttemptedSelfDestruct(hubStamp, hub.currentFrame()));
} else {
unexceptionalSelfDestructMap.put(
new EphemeralAccount(
addressWhichMaySelfDestruct, selfdestructorAccountBefore.deploymentNumber()),
List.of(new AttemptedSelfDestruct(hubStamp, hub.currentFrame())));
new ArrayList<>(List.of(new AttemptedSelfDestruct(hubStamp, hub.currentFrame()))));
}

hub.defers().scheduleForPostRollback(this, hub.currentFrame());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static net.consensys.linea.zktracer.types.AddressUtils.effectiveToAddress;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand All @@ -32,9 +33,10 @@
import net.consensys.linea.zktracer.ZkTracer;
import net.consensys.linea.zktracer.module.hub.AccountSnapshot;
import net.consensys.linea.zktracer.module.hub.Hub;
import net.consensys.linea.zktracer.module.hub.section.halt.AttemptedSelfDestruct;
import net.consensys.linea.zktracer.module.hub.section.halt.EphemeralAccount;
import net.consensys.linea.zktracer.module.hub.transients.Block;
import net.consensys.linea.zktracer.module.hub.transients.StorageInitialValues;
import net.consensys.linea.zktracer.runtime.callstack.CallFrame;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Transaction;
import org.hyperledger.besu.datatypes.Wei;
Expand Down Expand Up @@ -114,50 +116,44 @@ public class TransactionProcessingMetadata {
@Setter Set<AccountSnapshot> destructedAccountsSnapshot = new HashSet<>();

@Getter
final Map<EphemeralAccount, List<AttemptedSelfDestruct>> unexceptionalSelfDestructMap =
final Map<EphemeralAccount, ArrayList<AttemptedSelfDestruct>> unexceptionalSelfDestructMap =
new HashMap<>();

@Getter final Map<EphemeralAccount, Integer> effectiveSelfDestructMap = new HashMap<>();

// Ephermeral accounts are both accounts that have been deployed on-chain
// and accounts that live for a limited time
public record EphemeralAccount(Address address, int deploymentNumber) {}

public record AttemptedSelfDestruct(int hubStamp, CallFrame callFrame) {}

public TransactionProcessingMetadata(
final WorldView world,
final Transaction transaction,
final Block block,
final int relativeTransactionNumber,
final int absoluteTransactionNumber) {
this.absoluteTransactionNumber = absoluteTransactionNumber;
this.relativeBlockNumber = block.blockNumber();
this.coinbase = block.coinbaseAddress();
this.baseFee = block.baseFee().toLong();
relativeBlockNumber = block.blockNumber();
coinbase = block.coinbaseAddress();
baseFee = block.baseFee().toLong();

this.besuTransaction = transaction;
besuTransaction = transaction;
this.relativeTransactionNumber = relativeTransactionNumber;

this.isDeployment = transaction.getTo().isEmpty();
this.requiresEvmExecution = computeRequiresEvmExecution(world);
this.copyTransactionCallData = computeCopyCallData();
isDeployment = transaction.getTo().isEmpty();
requiresEvmExecution = computeRequiresEvmExecution(world);
copyTransactionCallData = computeCopyCallData();

this.initialBalance = getInitialBalance(world);
initialBalance = getInitialBalance(world);

// Note: Besu's dataCost computation contains
// - the 21_000 transaction cost (we deduce it)
// - the contract creation cost in case of deployment (we set deployment to false to not add it)
this.dataCost =
dataCost =
ZkTracer.gasCalculator.transactionIntrinsicGasCost(besuTransaction.getPayload(), false)
- GAS_CONST_G_TRANSACTION;
this.accessListCost =
accessListCost =
besuTransaction.getAccessList().map(ZkTracer.gasCalculator::accessListGasCost).orElse(0L);
this.initiallyAvailableGas = getInitiallyAvailableGas();
initiallyAvailableGas = getInitiallyAvailableGas();

this.effectiveRecipient = effectiveToAddress(besuTransaction);
effectiveRecipient = effectiveToAddress(besuTransaction);

this.effectiveGasPrice = computeEffectiveGasPrice();
effectiveGasPrice = computeEffectiveGasPrice();
}

public void setPreFinalisationValues(
Expand All @@ -166,14 +162,14 @@ public void setPreFinalisationValues(
final boolean coinbaseIsWarmAtFinalisation,
final int accumulatedGasUsedInBlockAtStartTx) {

this.isCoinbaseWarmAtTransactionEnd(coinbaseIsWarmAtFinalisation);
isCoinbaseWarmAtTransactionEnd(coinbaseIsWarmAtFinalisation);
this.refundCounterMax = refundCounterMax;
this.setLeftoverGas(leftOverGas);
this.gasUsed = computeGasUsed();
this.refundEffective = computeRefundEffective();
this.gasRefunded = computeRefunded();
this.totalGasUsed = computeTotalGasUsed();
this.accumulatedGasUsedInBlock = (int) (accumulatedGasUsedInBlockAtStartTx + totalGasUsed);
setLeftoverGas(leftOverGas);
gasUsed = computeGasUsed();
refundEffective = computeRefundEffective();
gasRefunded = computeRefunded();
totalGasUsed = computeTotalGasUsed();
accumulatedGasUsedInBlock = (int) (accumulatedGasUsedInBlockAtStartTx + totalGasUsed);
}

public void completeLineaTransaction(
Expand Down Expand Up @@ -206,7 +202,7 @@ private boolean computeRequiresEvmExecution(WorldView world) {
.orElse(false);
}

return !this.besuTransaction.getInit().get().isEmpty();
return !besuTransaction.getInit().get().isEmpty();
}

private BigInteger getInitialBalance(WorldView world) {
Expand All @@ -226,7 +222,7 @@ public long getInitiallyAvailableGas() {
}

private long computeRefundEffective() {
final long maxRefundableAmount = this.getGasUsed() / MAX_REFUND_QUOTIENT;
final long maxRefundableAmount = getGasUsed() / MAX_REFUND_QUOTIENT;
return Math.min(maxRefundableAmount, refundCounterMax);
}

Expand Down Expand Up @@ -266,7 +262,7 @@ public long computeGasUsed() {

/* g* in the EYP */
public long computeRefunded() {
return leftoverGas + this.refundEffective;
return leftoverGas + refundEffective;
}

/* Tg - g* in the EYP */
Expand All @@ -292,21 +288,21 @@ public Wei getGasRefundInWei() {
}

public int numberWarmedAddress() {
return this.besuTransaction.getAccessList().isPresent()
? this.besuTransaction.getAccessList().get().size()
return besuTransaction.getAccessList().isPresent()
? besuTransaction.getAccessList().get().size()
: 0;
}

public int numberWarmedKey() {
return this.besuTransaction.getAccessList().isPresent()
? this.besuTransaction.getAccessList().get().stream()
return besuTransaction.getAccessList().isPresent()
? besuTransaction.getAccessList().get().stream()
.mapToInt(accessListEntry -> accessListEntry.storageKeys().size())
.sum()
: 0;
}

private void determineSelfDestructTimeStamp() {
for (Map.Entry<EphemeralAccount, List<AttemptedSelfDestruct>> entry :
for (Map.Entry<EphemeralAccount, ArrayList<AttemptedSelfDestruct>> entry :
unexceptionalSelfDestructMap.entrySet()) {

final EphemeralAccount ephemeralAccount = entry.getKey();
Expand Down
Loading