mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 15:37:54 -05:00
Devnet-5: bug fixes for 7702 (#8148)
* * fix code hash for delegated accounts in ExtCodeHashOperation * move common code to AbstractExtCodeOperation class Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net> * * rename DelegatedCode -> CodeDelegation, for consistency Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net> * * rename authorization -> CodeDelegation, for consistency Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net> * rename method to start with lower case Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net> --------- Signed-off-by: Daniel Lehrner <daniel.lehrner@consensys.net> Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
This commit is contained in:
@@ -87,7 +87,7 @@ public class CodeDelegationTransactionAcceptanceTest extends AcceptanceTestBase
|
||||
public void shouldTransferAllEthOfAuthorizerToSponsor() throws IOException {
|
||||
|
||||
// 7702 transaction
|
||||
final CodeDelegation authorization =
|
||||
final CodeDelegation codeDelegation =
|
||||
org.hyperledger.besu.ethereum.core.CodeDelegation.builder()
|
||||
.chainId(BigInteger.valueOf(20211))
|
||||
.address(SEND_ALL_ETH_CONTRACT_ADDRESS)
|
||||
@@ -108,7 +108,7 @@ public class CodeDelegationTransactionAcceptanceTest extends AcceptanceTestBase
|
||||
.value(Wei.ZERO)
|
||||
.payload(Bytes32.leftPad(Bytes.fromHexString(transactionSponsor.getAddress())))
|
||||
.accessList(List.of())
|
||||
.codeDelegations(List.of(authorization))
|
||||
.codeDelegations(List.of(codeDelegation))
|
||||
.signAndBuild(
|
||||
secp256k1.createKeyPair(
|
||||
secp256k1.createPrivateKey(
|
||||
@@ -143,7 +143,7 @@ public class CodeDelegationTransactionAcceptanceTest extends AcceptanceTestBase
|
||||
final long GAS_LIMIT = 1_000_000L;
|
||||
cluster.verify(authorizer.balanceEquals(Amount.ether(90_000)));
|
||||
|
||||
final CodeDelegation authorization =
|
||||
final CodeDelegation codeDelegation =
|
||||
org.hyperledger.besu.ethereum.core.CodeDelegation.builder()
|
||||
.chainId(BigInteger.valueOf(20211))
|
||||
.nonce(
|
||||
@@ -166,7 +166,7 @@ public class CodeDelegationTransactionAcceptanceTest extends AcceptanceTestBase
|
||||
.value(Wei.ZERO)
|
||||
.payload(Bytes32.leftPad(Bytes.fromHexString(otherAccount.getAddress())))
|
||||
.accessList(List.of())
|
||||
.codeDelegations(List.of(authorization))
|
||||
.codeDelegations(List.of(codeDelegation))
|
||||
.signAndBuild(
|
||||
secp256k1.createKeyPair(
|
||||
secp256k1.createPrivateKey(AUTHORIZER_PRIVATE_KEY.toUnsignedBigInteger())));
|
||||
|
||||
@@ -243,9 +243,9 @@ public interface Transaction {
|
||||
Optional<List<CodeDelegation>> getCodeDelegationList();
|
||||
|
||||
/**
|
||||
* Returns the size of the authorization list.
|
||||
* Returns the size of the code delegation list.
|
||||
*
|
||||
* @return the size of the authorization list
|
||||
* @return the size of the code delegation list
|
||||
*/
|
||||
int codeDelegationListSize();
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class CodeDelegationProcessor {
|
||||
.get()
|
||||
.forEach(
|
||||
codeDelegation ->
|
||||
processAuthorization(
|
||||
processCodeDelegation(
|
||||
evmWorldUpdater,
|
||||
(org.hyperledger.besu.ethereum.core.CodeDelegation) codeDelegation,
|
||||
result));
|
||||
@@ -78,7 +78,7 @@ public class CodeDelegationProcessor {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void processAuthorization(
|
||||
private void processCodeDelegation(
|
||||
final EVMWorldUpdater evmWorldUpdater,
|
||||
final CodeDelegation codeDelegation,
|
||||
final CodeDelegationResult result) {
|
||||
@@ -130,7 +130,7 @@ public class CodeDelegationProcessor {
|
||||
} else {
|
||||
authority = maybeAuthorityAccount.get();
|
||||
|
||||
if (!evmWorldUpdater.authorizedCodeService().canSetDelegatedCode(authority)) {
|
||||
if (!evmWorldUpdater.codeDelegationService().canSetCodeDelegation(authority)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -150,8 +150,8 @@ public class CodeDelegationProcessor {
|
||||
}
|
||||
|
||||
evmWorldUpdater
|
||||
.authorizedCodeService()
|
||||
.processDelegatedCodeAuthorization(authority, codeDelegation.address());
|
||||
.codeDelegationService()
|
||||
.processCodeDelegation(authority, codeDelegation.address());
|
||||
authority.incrementNonce();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,8 +427,8 @@ public class MainnetTransactionProcessor {
|
||||
final Address to = transaction.getTo().get();
|
||||
final Optional<Account> maybeContract = Optional.ofNullable(evmWorldUpdater.get(to));
|
||||
|
||||
if (maybeContract.isPresent() && maybeContract.get().hasDelegatedCode()) {
|
||||
warmAddressList.add(maybeContract.get().delegatedCodeAddress().get());
|
||||
if (maybeContract.isPresent() && maybeContract.get().hasCodeDelegation()) {
|
||||
warmAddressList.add(maybeContract.get().codeDelegationAddress().get());
|
||||
}
|
||||
|
||||
initialFrame =
|
||||
@@ -441,9 +441,10 @@ public class MainnetTransactionProcessor {
|
||||
maybeContract
|
||||
.map(
|
||||
c -> {
|
||||
if (c.hasDelegatedCode()) {
|
||||
if (c.hasCodeDelegation()) {
|
||||
return messageCallProcessor.getCodeFromEVM(
|
||||
c.getDelegatedCodeHash().get(), c.getDelegatedCode().get());
|
||||
c.getCodeDelegationTargetHash().get(),
|
||||
c.getCodeDelegationTargetCode().get());
|
||||
}
|
||||
|
||||
return messageCallProcessor.getCodeFromEVM(
|
||||
|
||||
@@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.mainnet;
|
||||
|
||||
import static org.hyperledger.besu.evm.account.Account.MAX_NONCE;
|
||||
import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
|
||||
import static org.hyperledger.besu.evm.worldstate.DelegateCodeHelper.hasDelegatedCode;
|
||||
import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.hasCodeDelegation;
|
||||
|
||||
import org.hyperledger.besu.crypto.SECPSignature;
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
|
||||
@@ -333,7 +333,7 @@ public class MainnetTransactionValidator implements TransactionValidator {
|
||||
}
|
||||
|
||||
private static boolean canSendTransaction(final Account sender, final Hash codeHash) {
|
||||
return codeHash.equals(Hash.EMPTY) || hasDelegatedCode(sender.getCode());
|
||||
return codeHash.equals(Hash.EMPTY) || hasCodeDelegation(sender.getCode());
|
||||
}
|
||||
|
||||
private ValidationResult<TransactionInvalidReason> validateTransactionSignature(
|
||||
|
||||
@@ -37,14 +37,15 @@ class CodeDelegationDecoderTest {
|
||||
Bytes.fromHexString(
|
||||
"0xf85a0194633688abc3ccf8b0c03088d2d1c6ae4958c2fa562a80a0840798fa67118e034c1eb7e42fe89e28d7cd5006dc813d5729e5f75b0d1a7ec5a03b1dbace38ceb862a65bf2eac0637693b5c3493bcb2a022dd614c0a74cce0b99"),
|
||||
true);
|
||||
final CodeDelegation authorization = CodeDelegationTransactionDecoder.decodeInnerPayload(input);
|
||||
final CodeDelegation codeDelegation =
|
||||
CodeDelegationTransactionDecoder.decodeInnerPayload(input);
|
||||
|
||||
assertThat(authorization.chainId()).isEqualTo(BigInteger.ONE);
|
||||
assertThat(authorization.address())
|
||||
assertThat(codeDelegation.chainId()).isEqualTo(BigInteger.ONE);
|
||||
assertThat(codeDelegation.address())
|
||||
.isEqualTo(Address.fromHexStringStrict("0x633688abc3cCf8B0C03088D2d1C6ae4958c2fA56"));
|
||||
assertThat(authorization.nonce()).isEqualTo(42);
|
||||
assertThat(codeDelegation.nonce()).isEqualTo(42);
|
||||
|
||||
final SECPSignature signature = authorization.signature();
|
||||
final SECPSignature signature = codeDelegation.signature();
|
||||
assertThat(signature.getRecId()).isEqualTo((byte) 0);
|
||||
assertThat(signature.getR().toString(16))
|
||||
.isEqualTo("840798fa67118e034c1eb7e42fe89e28d7cd5006dc813d5729e5f75b0d1a7ec5");
|
||||
@@ -61,14 +62,15 @@ class CodeDelegationDecoderTest {
|
||||
Bytes.fromHexString(
|
||||
"0xf85a0194633688abc3ccf8b0c03088d2d1c6ae4958c2fa568001a0dd6b24048be1b7d7fe5bbbb73ffc37eb2ce1997ecb4ae5b6096532ef19363148a025b58a1ff8ad00bddbbfa1d5c2411961cbb6d08dcdc8ae88303db3c6cf983031"),
|
||||
true);
|
||||
final CodeDelegation authorization = CodeDelegationTransactionDecoder.decodeInnerPayload(input);
|
||||
final CodeDelegation codeDelegation =
|
||||
CodeDelegationTransactionDecoder.decodeInnerPayload(input);
|
||||
|
||||
assertThat(authorization.chainId()).isEqualTo(BigInteger.ONE);
|
||||
assertThat(authorization.address())
|
||||
assertThat(codeDelegation.chainId()).isEqualTo(BigInteger.ONE);
|
||||
assertThat(codeDelegation.address())
|
||||
.isEqualTo(Address.fromHexStringStrict("0x633688abc3cCf8B0C03088D2d1C6ae4958c2fA56"));
|
||||
assertThat(authorization.nonce()).isEqualTo(0);
|
||||
assertThat(codeDelegation.nonce()).isEqualTo(0);
|
||||
|
||||
final SECPSignature signature = authorization.signature();
|
||||
final SECPSignature signature = codeDelegation.signature();
|
||||
assertThat(signature.getRecId()).isEqualTo((byte) 1);
|
||||
assertThat(signature.getR().toString(16))
|
||||
.isEqualTo("dd6b24048be1b7d7fe5bbbb73ffc37eb2ce1997ecb4ae5b6096532ef19363148");
|
||||
@@ -85,14 +87,15 @@ class CodeDelegationDecoderTest {
|
||||
Bytes.fromHexString(
|
||||
"0xf85a8094633688abc3ccf8b0c03088d2d1c6ae4958c2fa560501a0025c1240d7ffec0daeedb752d3357aff2e3cd58468f0c2d43ee0ee999e02ace2a03c8a25b2becd6e666f69803d1ae3322f2e137b7745c2c7f19da80f993ffde4df"),
|
||||
true);
|
||||
final CodeDelegation authorization = CodeDelegationTransactionDecoder.decodeInnerPayload(input);
|
||||
final CodeDelegation codeDelegation =
|
||||
CodeDelegationTransactionDecoder.decodeInnerPayload(input);
|
||||
|
||||
assertThat(authorization.chainId()).isEqualTo(BigInteger.ZERO);
|
||||
assertThat(authorization.address())
|
||||
assertThat(codeDelegation.chainId()).isEqualTo(BigInteger.ZERO);
|
||||
assertThat(codeDelegation.address())
|
||||
.isEqualTo(Address.fromHexStringStrict("0x633688abc3cCf8B0C03088D2d1C6ae4958c2fA56"));
|
||||
assertThat(authorization.nonce()).isEqualTo(5);
|
||||
assertThat(codeDelegation.nonce()).isEqualTo(5);
|
||||
|
||||
final SECPSignature signature = authorization.signature();
|
||||
final SECPSignature signature = codeDelegation.signature();
|
||||
assertThat(signature.getRecId()).isEqualTo((byte) 1);
|
||||
assertThat(signature.getR().toString(16))
|
||||
.isEqualTo("25c1240d7ffec0daeedb752d3357aff2e3cd58468f0c2d43ee0ee999e02ace2");
|
||||
@@ -107,8 +110,9 @@ class CodeDelegationDecoderTest {
|
||||
Bytes.fromHexString(
|
||||
"0xdf8501a1f0ff5a947a40026a3b9a41754a95eec8c92c6b99886f440c5b808080"),
|
||||
true);
|
||||
final CodeDelegation authorization = CodeDelegationTransactionDecoder.decodeInnerPayload(input);
|
||||
final CodeDelegation codeDelegation =
|
||||
CodeDelegationTransactionDecoder.decodeInnerPayload(input);
|
||||
|
||||
assertThat(authorization.chainId()).isEqualTo(new BigInteger("01a1f0ff5a", 16));
|
||||
assertThat(codeDelegation.chainId()).isEqualTo(new BigInteger("01a1f0ff5a", 16));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.hyperledger.besu.datatypes.CodeDelegation;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||
import org.hyperledger.besu.evm.worldstate.DelegatedCodeService;
|
||||
import org.hyperledger.besu.evm.worldstate.CodeDelegationService;
|
||||
import org.hyperledger.besu.evm.worldstate.EVMWorldUpdater;
|
||||
|
||||
import java.math.BigInteger;
|
||||
@@ -47,7 +47,7 @@ class CodeDelegationProcessorTest {
|
||||
|
||||
@Mock private Transaction transaction;
|
||||
|
||||
@Mock private DelegatedCodeService authorizedCodeService;
|
||||
@Mock private CodeDelegationService authorizedCodeService;
|
||||
|
||||
@Mock private MutableAccount authority;
|
||||
|
||||
@@ -95,7 +95,7 @@ class CodeDelegationProcessorTest {
|
||||
@Test
|
||||
void shouldProcessValidDelegationForNewAccount() {
|
||||
// Arrange
|
||||
when(worldUpdater.authorizedCodeService()).thenReturn(authorizedCodeService);
|
||||
when(worldUpdater.codeDelegationService()).thenReturn(authorizedCodeService);
|
||||
CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, 0L);
|
||||
when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation)));
|
||||
when(worldUpdater.getAccount(any())).thenReturn(null);
|
||||
@@ -109,18 +109,18 @@ class CodeDelegationProcessorTest {
|
||||
assertThat(result.alreadyExistingDelegators()).isZero();
|
||||
verify(worldUpdater).createAccount(any());
|
||||
verify(authority).incrementNonce();
|
||||
verify(authorizedCodeService).processDelegatedCodeAuthorization(authority, DELEGATE_ADDRESS);
|
||||
verify(authorizedCodeService).processCodeDelegation(authority, DELEGATE_ADDRESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldProcessValidDelegationForExistingAccount() {
|
||||
// Arrange
|
||||
when(worldUpdater.authorizedCodeService()).thenReturn(authorizedCodeService);
|
||||
when(worldUpdater.codeDelegationService()).thenReturn(authorizedCodeService);
|
||||
CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, 1L);
|
||||
when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation)));
|
||||
when(worldUpdater.getAccount(any())).thenReturn(authority);
|
||||
when(authority.getNonce()).thenReturn(1L);
|
||||
when(authorizedCodeService.canSetDelegatedCode(any())).thenReturn(true);
|
||||
when(authorizedCodeService.canSetCodeDelegation(any())).thenReturn(true);
|
||||
|
||||
// Act
|
||||
CodeDelegationResult result = processor.process(worldUpdater, transaction);
|
||||
@@ -129,17 +129,17 @@ class CodeDelegationProcessorTest {
|
||||
assertThat(result.alreadyExistingDelegators()).isEqualTo(1);
|
||||
verify(worldUpdater, never()).createAccount(any());
|
||||
verify(authority).incrementNonce();
|
||||
verify(authorizedCodeService).processDelegatedCodeAuthorization(authority, DELEGATE_ADDRESS);
|
||||
verify(authorizedCodeService).processCodeDelegation(authority, DELEGATE_ADDRESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectDelegationWithInvalidNonce() {
|
||||
// Arrange
|
||||
when(worldUpdater.authorizedCodeService()).thenReturn(authorizedCodeService);
|
||||
when(worldUpdater.codeDelegationService()).thenReturn(authorizedCodeService);
|
||||
CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, 2L);
|
||||
when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation)));
|
||||
when(worldUpdater.getAccount(any())).thenReturn(authority);
|
||||
when(authorizedCodeService.canSetDelegatedCode(any())).thenReturn(true);
|
||||
when(authorizedCodeService.canSetCodeDelegation(any())).thenReturn(true);
|
||||
|
||||
// Act
|
||||
CodeDelegationResult result = processor.process(worldUpdater, transaction);
|
||||
@@ -147,7 +147,7 @@ class CodeDelegationProcessorTest {
|
||||
// Assert
|
||||
assertThat(result.alreadyExistingDelegators()).isZero();
|
||||
verify(authority, never()).incrementNonce();
|
||||
verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any());
|
||||
verify(authorizedCodeService, never()).processCodeDelegation(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -163,7 +163,7 @@ class CodeDelegationProcessorTest {
|
||||
// Assert
|
||||
assertThat(result.alreadyExistingDelegators()).isZero();
|
||||
verify(authority, never()).incrementNonce();
|
||||
verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any());
|
||||
verify(authorizedCodeService, never()).processCodeDelegation(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,7 +181,7 @@ class CodeDelegationProcessorTest {
|
||||
// Assert
|
||||
assertThat(result.alreadyExistingDelegators()).isZero();
|
||||
verify(authority, never()).incrementNonce();
|
||||
verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any());
|
||||
verify(authorizedCodeService, never()).processCodeDelegation(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -201,17 +201,17 @@ class CodeDelegationProcessorTest {
|
||||
// Assert
|
||||
assertThat(result.alreadyExistingDelegators()).isZero();
|
||||
verify(authority, never()).incrementNonce();
|
||||
verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any());
|
||||
verify(authorizedCodeService, never()).processCodeDelegation(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectDelegationWhenCannotSetDelegatedCode() {
|
||||
void shouldRejectDelegationWhenCannotSetCodeDelegation() {
|
||||
// Arrange
|
||||
when(worldUpdater.authorizedCodeService()).thenReturn(authorizedCodeService);
|
||||
when(worldUpdater.codeDelegationService()).thenReturn(authorizedCodeService);
|
||||
CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, 1L);
|
||||
when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation)));
|
||||
when(worldUpdater.getAccount(any())).thenReturn(authority);
|
||||
when(authorizedCodeService.canSetDelegatedCode(any())).thenReturn(false);
|
||||
when(authorizedCodeService.canSetCodeDelegation(any())).thenReturn(false);
|
||||
|
||||
// Act
|
||||
CodeDelegationResult result = processor.process(worldUpdater, transaction);
|
||||
@@ -219,7 +219,7 @@ class CodeDelegationProcessorTest {
|
||||
// Assert
|
||||
assertThat(result.alreadyExistingDelegators()).isZero();
|
||||
verify(authority, never()).incrementNonce();
|
||||
verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any());
|
||||
verify(authorizedCodeService, never()).processCodeDelegation(any(), any());
|
||||
}
|
||||
|
||||
private CodeDelegation createCodeDelegation(final BigInteger chainId, final long nonce) {
|
||||
|
||||
@@ -221,43 +221,44 @@ public class T8nExecutor {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<CodeDelegation> authorizations = new ArrayList<>(authorizationList.size());
|
||||
List<CodeDelegation> codeDelegations = new ArrayList<>(authorizationList.size());
|
||||
for (JsonNode entryAsJson : authorizationList) {
|
||||
final BigInteger authorizationChainId =
|
||||
final BigInteger codeDelegationChainId =
|
||||
Bytes.fromHexStringLenient(entryAsJson.get("chainId").textValue())
|
||||
.toUnsignedBigInteger();
|
||||
final Address authorizationAddress =
|
||||
final Address codeDelegationAddress =
|
||||
Address.fromHexString(entryAsJson.get("address").textValue());
|
||||
|
||||
final long authorizationNonce =
|
||||
final long codeDelegationNonce =
|
||||
Bytes.fromHexStringLenient(entryAsJson.get("nonce").textValue()).toLong();
|
||||
|
||||
final BigInteger authorizationV =
|
||||
final BigInteger codeDelegationV =
|
||||
Bytes.fromHexStringLenient(entryAsJson.get("v").textValue())
|
||||
.toUnsignedBigInteger();
|
||||
if (authorizationV.compareTo(BigInteger.valueOf(256)) >= 0) {
|
||||
if (codeDelegationV.compareTo(BigInteger.valueOf(256)) >= 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid authorizationV value. Must be less than 256");
|
||||
"Invalid codeDelegationV value. Must be less than 256");
|
||||
}
|
||||
|
||||
final BigInteger authorizationR =
|
||||
final BigInteger codeDelegationR =
|
||||
Bytes.fromHexStringLenient(entryAsJson.get("r").textValue())
|
||||
.toUnsignedBigInteger();
|
||||
final BigInteger authorizationS =
|
||||
final BigInteger codeDelegationS =
|
||||
Bytes.fromHexStringLenient(entryAsJson.get("s").textValue())
|
||||
.toUnsignedBigInteger();
|
||||
|
||||
final SECPSignature authorizationSignature =
|
||||
new SECPSignature(authorizationR, authorizationS, authorizationV.byteValue());
|
||||
final SECPSignature codeDelegationSignature =
|
||||
new SECPSignature(
|
||||
codeDelegationR, codeDelegationS, codeDelegationV.byteValue());
|
||||
|
||||
authorizations.add(
|
||||
codeDelegations.add(
|
||||
new org.hyperledger.besu.ethereum.core.CodeDelegation(
|
||||
authorizationChainId,
|
||||
authorizationAddress,
|
||||
authorizationNonce,
|
||||
authorizationSignature));
|
||||
codeDelegationChainId,
|
||||
codeDelegationAddress,
|
||||
codeDelegationNonce,
|
||||
codeDelegationSignature));
|
||||
}
|
||||
builder.codeDelegations(authorizations);
|
||||
builder.codeDelegations(codeDelegations);
|
||||
}
|
||||
|
||||
if (txNode.has("blobVersionedHashes")) {
|
||||
|
||||
@@ -23,20 +23,20 @@ import java.util.Optional;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
abstract class AbstractDelegatedCodeAccount implements Account {
|
||||
abstract class AbstractCodeDelegationAccount implements Account {
|
||||
private final WorldUpdater worldUpdater;
|
||||
private final GasCalculator gasCalculator;
|
||||
|
||||
/** The address of the account that has delegated code to be loaded into it. */
|
||||
protected final Address delegatedCodeAddress;
|
||||
protected final Address codeDelegationAddress;
|
||||
|
||||
protected AbstractDelegatedCodeAccount(
|
||||
protected AbstractCodeDelegationAccount(
|
||||
final WorldUpdater worldUpdater,
|
||||
final Address delegatedCodeAddress,
|
||||
final Address codeDelegationAddress,
|
||||
final GasCalculator gasCalculator) {
|
||||
this.worldUpdater = worldUpdater;
|
||||
this.gasCalculator = gasCalculator;
|
||||
this.delegatedCodeAddress = delegatedCodeAddress;
|
||||
this.codeDelegationAddress = codeDelegationAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,8 +45,8 @@ abstract class AbstractDelegatedCodeAccount implements Account {
|
||||
* @return the delegated code.
|
||||
*/
|
||||
@Override
|
||||
public Optional<Bytes> getDelegatedCode() {
|
||||
return resolveDelegatedCode();
|
||||
public Optional<Bytes> getCodeDelegationTargetCode() {
|
||||
return resolveCodeDelegationTargetCode();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,8 +55,8 @@ abstract class AbstractDelegatedCodeAccount implements Account {
|
||||
* @return the hash of the delegated code.
|
||||
*/
|
||||
@Override
|
||||
public Optional<Hash> getDelegatedCodeHash() {
|
||||
return getDelegatedCode().map(Hash::hash);
|
||||
public Optional<Hash> getCodeDelegationTargetHash() {
|
||||
return getCodeDelegationTargetCode().map(Hash::hash);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,23 +65,23 @@ abstract class AbstractDelegatedCodeAccount implements Account {
|
||||
* @return the address of the delegated code.
|
||||
*/
|
||||
@Override
|
||||
public Optional<Address> delegatedCodeAddress() {
|
||||
return Optional.of(delegatedCodeAddress);
|
||||
public Optional<Address> codeDelegationAddress() {
|
||||
return Optional.of(codeDelegationAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDelegatedCode() {
|
||||
public boolean hasCodeDelegation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Optional<Account> getDelegatedAccount() {
|
||||
return Optional.ofNullable(worldUpdater.getAccount(delegatedCodeAddress));
|
||||
return Optional.ofNullable(worldUpdater.getAccount(codeDelegationAddress));
|
||||
}
|
||||
|
||||
private Optional<Bytes> resolveDelegatedCode() {
|
||||
private Optional<Bytes> resolveCodeDelegationTargetCode() {
|
||||
final Optional<Account> maybeDelegatedAccount = getDelegatedAccount();
|
||||
|
||||
if (gasCalculator.isPrecompile(delegatedCodeAddress) || maybeDelegatedAccount.isEmpty()) {
|
||||
if (gasCalculator.isPrecompile(codeDelegationAddress) || maybeDelegatedAccount.isEmpty()) {
|
||||
return Optional.of(Bytes.EMPTY);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public interface Account extends AccountState {
|
||||
*
|
||||
* @return the address of the delegated code account if it has one otherwise empty.
|
||||
*/
|
||||
default Optional<Address> delegatedCodeAddress() {
|
||||
default Optional<Address> codeDelegationAddress() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public interface Account extends AccountState {
|
||||
*
|
||||
* @return true if the account has delegated code otherwise false.
|
||||
*/
|
||||
default boolean hasDelegatedCode() {
|
||||
default boolean hasCodeDelegation() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,9 +78,9 @@ public interface AccountState {
|
||||
/**
|
||||
* The optional EVM bytecode if the account has set a 7702 code delegation.
|
||||
*
|
||||
* @return the delegated code (which may be empty).
|
||||
* @return the code of the target account (which may be empty).
|
||||
*/
|
||||
default Optional<Bytes> getDelegatedCode() {
|
||||
default Optional<Bytes> getCodeDelegationTargetCode() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -94,9 +94,9 @@ public interface AccountState {
|
||||
/**
|
||||
* The optional hash of the delegated EVM bytecode if the account has set a 7702 code delegation.
|
||||
*
|
||||
* @return the hash of the delegated code (which may be empty).
|
||||
* @return the hash of the code of the target account (which may be empty).
|
||||
*/
|
||||
default Optional<Hash> getDelegatedCodeHash() {
|
||||
default Optional<Hash> getCodeDelegationTargetHash() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,19 +28,19 @@ import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
|
||||
/** Wraps an EOA account and includes delegated code to be run on behalf of it. */
|
||||
public class DelegatedCodeAccount extends AbstractDelegatedCodeAccount implements Account {
|
||||
public class CodeDelegationAccount extends AbstractCodeDelegationAccount implements Account {
|
||||
|
||||
private final Account wrappedAccount;
|
||||
|
||||
/**
|
||||
* Creates a new AuthorizedCodeAccount.
|
||||
* Creates a new CodeDelegationAccount.
|
||||
*
|
||||
* @param worldUpdater the world updater.
|
||||
* @param wrappedAccount the account that has delegated code to be loaded into it.
|
||||
* @param codeDelegationAddress the address of the delegated code.
|
||||
* @param gasCalculator the gas calculator to check for precompiles.
|
||||
*/
|
||||
public DelegatedCodeAccount(
|
||||
public CodeDelegationAccount(
|
||||
final WorldUpdater worldUpdater,
|
||||
final Account wrappedAccount,
|
||||
final Address codeDelegationAddress,
|
||||
@@ -60,8 +60,8 @@ public class DelegatedCodeAccount extends AbstractDelegatedCodeAccount implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Address> delegatedCodeAddress() {
|
||||
return super.delegatedCodeAddress();
|
||||
public Optional<Address> codeDelegationAddress() {
|
||||
return super.codeDelegationAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -29,20 +29,20 @@ import org.apache.tuweni.bytes.Bytes32;
|
||||
import org.apache.tuweni.units.bigints.UInt256;
|
||||
|
||||
/** Wraps an EOA account and includes delegated code to be run on behalf of it. */
|
||||
public class MutableDelegatedCodeAccount extends AbstractDelegatedCodeAccount
|
||||
public class MutableCodeDelegationDelegationAccount extends AbstractCodeDelegationAccount
|
||||
implements MutableAccount {
|
||||
|
||||
private final MutableAccount wrappedAccount;
|
||||
|
||||
/**
|
||||
* Creates a new MutableAuthorizedCodeAccount.
|
||||
* Creates a new MutableCodeDelegationDelegationAccount.
|
||||
*
|
||||
* @param worldUpdater the world updater.
|
||||
* @param wrappedAccount the account that has delegated code to be loaded into it.
|
||||
* @param codeDelegationAddress the address of the delegated code.
|
||||
* @param gasCalculator the gas calculator to check for precompiles.
|
||||
*/
|
||||
public MutableDelegatedCodeAccount(
|
||||
public MutableCodeDelegationDelegationAccount(
|
||||
final WorldUpdater worldUpdater,
|
||||
final MutableAccount wrappedAccount,
|
||||
final Address codeDelegationAddress,
|
||||
@@ -62,8 +62,8 @@ public class MutableDelegatedCodeAccount extends AbstractDelegatedCodeAccount
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Address> delegatedCodeAddress() {
|
||||
return super.delegatedCodeAddress();
|
||||
public Optional<Address> codeDelegationAddress() {
|
||||
return super.codeDelegationAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,7 +26,7 @@ import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||
import org.hyperledger.besu.evm.frame.MessageFrame.State;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper;
|
||||
import org.hyperledger.besu.evm.worldstate.CodeDelegationGasCostHelper;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
@@ -191,24 +191,24 @@ public abstract class AbstractCallOperation extends AbstractOperation {
|
||||
|
||||
final Account contract = frame.getWorldUpdater().get(to);
|
||||
|
||||
if (contract != null && contract.hasDelegatedCode()) {
|
||||
if (contract.getDelegatedCode().isEmpty()) {
|
||||
if (contract != null && contract.hasCodeDelegation()) {
|
||||
if (contract.getCodeDelegationTargetCode().isEmpty()) {
|
||||
throw new RuntimeException("A delegated code account must have delegated code");
|
||||
}
|
||||
|
||||
if (contract.getDelegatedCodeHash().isEmpty()) {
|
||||
if (contract.getCodeDelegationTargetHash().isEmpty()) {
|
||||
throw new RuntimeException("A delegated code account must have a delegated code hash");
|
||||
}
|
||||
|
||||
final long delegatedCodeResolutionGas =
|
||||
DelegatedCodeGasCostHelper.delegatedCodeGasCost(frame, gasCalculator(), contract);
|
||||
final long codeDelegationResolutionGas =
|
||||
CodeDelegationGasCostHelper.codeDelegationGasCost(frame, gasCalculator(), contract);
|
||||
|
||||
if (frame.getRemainingGas() < delegatedCodeResolutionGas) {
|
||||
if (frame.getRemainingGas() < codeDelegationResolutionGas) {
|
||||
return new Operation.OperationResult(
|
||||
delegatedCodeResolutionGas, ExceptionalHaltReason.INSUFFICIENT_GAS);
|
||||
codeDelegationResolutionGas, ExceptionalHaltReason.INSUFFICIENT_GAS);
|
||||
}
|
||||
|
||||
frame.decrementRemainingGas(delegatedCodeResolutionGas);
|
||||
frame.decrementRemainingGas(codeDelegationResolutionGas);
|
||||
}
|
||||
|
||||
final Account account = frame.getWorldUpdater().get(frame.getRecipientAddress());
|
||||
@@ -357,8 +357,9 @@ public abstract class AbstractCallOperation extends AbstractOperation {
|
||||
return CodeV0.EMPTY_CODE;
|
||||
}
|
||||
|
||||
if (account.hasDelegatedCode()) {
|
||||
return evm.getCode(account.getDelegatedCodeHash().get(), account.getDelegatedCode().get());
|
||||
if (account.hasCodeDelegation()) {
|
||||
return evm.getCode(
|
||||
account.getCodeDelegationTargetHash().get(), account.getCodeDelegationTargetCode().get());
|
||||
}
|
||||
|
||||
return evm.getCode(account.getCodeHash(), account.getCode());
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.internal.Words;
|
||||
import org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper;
|
||||
import org.hyperledger.besu.evm.worldstate.CodeDelegationGasCostHelper;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@@ -125,24 +125,24 @@ public abstract class AbstractExtCallOperation extends AbstractCallOperation {
|
||||
Address to = Words.toAddress(toBytes);
|
||||
final Account contract = frame.getWorldUpdater().get(to);
|
||||
|
||||
if (contract != null && contract.hasDelegatedCode()) {
|
||||
if (contract.getDelegatedCode().isEmpty()) {
|
||||
if (contract != null && contract.hasCodeDelegation()) {
|
||||
if (contract.getCodeDelegationTargetCode().isEmpty()) {
|
||||
throw new RuntimeException("A delegated code account must have delegated code");
|
||||
}
|
||||
|
||||
if (contract.getDelegatedCodeHash().isEmpty()) {
|
||||
if (contract.getCodeDelegationTargetHash().isEmpty()) {
|
||||
throw new RuntimeException("A delegated code account must have a delegated code hash");
|
||||
}
|
||||
|
||||
final long delegatedCodeResolutionGas =
|
||||
DelegatedCodeGasCostHelper.delegatedCodeGasCost(frame, gasCalculator(), contract);
|
||||
final long codeDelegationResolutionGas =
|
||||
CodeDelegationGasCostHelper.codeDelegationGasCost(frame, gasCalculator(), contract);
|
||||
|
||||
if (frame.getRemainingGas() < delegatedCodeResolutionGas) {
|
||||
if (frame.getRemainingGas() < codeDelegationResolutionGas) {
|
||||
return new Operation.OperationResult(
|
||||
delegatedCodeResolutionGas, ExceptionalHaltReason.INSUFFICIENT_GAS);
|
||||
codeDelegationResolutionGas, ExceptionalHaltReason.INSUFFICIENT_GAS);
|
||||
}
|
||||
|
||||
frame.decrementRemainingGas(delegatedCodeResolutionGas);
|
||||
frame.decrementRemainingGas(codeDelegationResolutionGas);
|
||||
}
|
||||
|
||||
boolean accountCreation = (contract == null || contract.isEmpty()) && !zeroValue;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright contributors to Besu.
|
||||
*
|
||||
* 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 org.hyperledger.besu.evm.operation;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.worldstate.CodeDelegationHelper;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
/**
|
||||
* ExtCode* operations treat EOAs with delegated code differently than other operations. This
|
||||
* abstract class contains common methods for this behaviour.
|
||||
*/
|
||||
abstract class AbstractExtCodeOperation extends AbstractOperation {
|
||||
/**
|
||||
* Instantiates a new Abstract operation.
|
||||
*
|
||||
* @param opcode the opcode
|
||||
* @param name the name
|
||||
* @param stackItemsConsumed the stack items consumed
|
||||
* @param stackItemsProduced the stack items produced
|
||||
* @param gasCalculator the gas calculator
|
||||
*/
|
||||
protected AbstractExtCodeOperation(
|
||||
final int opcode,
|
||||
final String name,
|
||||
final int stackItemsConsumed,
|
||||
final int stackItemsProduced,
|
||||
final GasCalculator gasCalculator) {
|
||||
super(opcode, name, stackItemsConsumed, stackItemsProduced, gasCalculator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code for standard accounts or a special designator for EOAs with delegated code
|
||||
*
|
||||
* @param account The account
|
||||
* @return the code or the special 7702 designator
|
||||
*/
|
||||
protected Bytes getCode(final Account account) {
|
||||
if (account == null) {
|
||||
return Bytes.EMPTY;
|
||||
}
|
||||
|
||||
return account.hasCodeDelegation()
|
||||
? CodeDelegationHelper.getCodeDelegationForRead()
|
||||
: account.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the code hash for standard accounts or a special designator for EOAs with delegated
|
||||
* code
|
||||
*
|
||||
* @param account The account
|
||||
* @return the code hash or the hash of the special 7702 designator
|
||||
*/
|
||||
protected Hash getCodeHash(final Account account) {
|
||||
if (account.hasCodeDelegation()) {
|
||||
return Hash.hash(CodeDelegationHelper.getCodeDelegationForRead());
|
||||
}
|
||||
|
||||
return account.getCodeHash();
|
||||
}
|
||||
}
|
||||
@@ -25,12 +25,11 @@ import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
|
||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.internal.Words;
|
||||
import org.hyperledger.besu.evm.worldstate.DelegateCodeHelper;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
/** The Ext code copy operation. */
|
||||
public class ExtCodeCopyOperation extends AbstractOperation {
|
||||
public class ExtCodeCopyOperation extends AbstractExtCodeOperation {
|
||||
|
||||
/** This is the "code" legacy contracts see when copying code from an EOF contract. */
|
||||
public static final Bytes EOF_REPLACEMENT_CODE = Bytes.fromHexString("0xef00");
|
||||
@@ -108,14 +107,4 @@ public class ExtCodeCopyOperation extends AbstractOperation {
|
||||
|
||||
return new OperationResult(cost, null);
|
||||
}
|
||||
|
||||
private static Bytes getCode(final Account account) {
|
||||
if (account == null) {
|
||||
return Bytes.EMPTY;
|
||||
}
|
||||
|
||||
return account.hasDelegatedCode()
|
||||
? DelegateCodeHelper.getDelegatedCodeForRead()
|
||||
: account.getCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,11 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.internal.OverflowException;
|
||||
import org.hyperledger.besu.evm.internal.UnderflowException;
|
||||
import org.hyperledger.besu.evm.internal.Words;
|
||||
import org.hyperledger.besu.evm.worldstate.DelegateCodeHelper;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
/** The Ext code hash operation. */
|
||||
public class ExtCodeHashOperation extends AbstractOperation {
|
||||
public class ExtCodeHashOperation extends AbstractExtCodeOperation {
|
||||
|
||||
// // 0x9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5
|
||||
static final Hash EOF_REPLACEMENT_HASH = Hash.hash(ExtCodeCopyOperation.EOF_REPLACEMENT_CODE);
|
||||
@@ -93,7 +92,7 @@ public class ExtCodeHashOperation extends AbstractOperation {
|
||||
&& code.get(1) == 0) {
|
||||
frame.pushStackItem(EOF_REPLACEMENT_HASH);
|
||||
} else {
|
||||
frame.pushStackItem(account.getCodeHash());
|
||||
frame.pushStackItem(getCodeHash(account));
|
||||
}
|
||||
}
|
||||
return new OperationResult(cost, null);
|
||||
@@ -104,12 +103,4 @@ public class ExtCodeHashOperation extends AbstractOperation {
|
||||
return new OperationResult(cost(true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS);
|
||||
}
|
||||
}
|
||||
|
||||
private static Bytes getCode(final Account account) {
|
||||
if (!account.hasDelegatedCode()) {
|
||||
return account.getCode();
|
||||
}
|
||||
|
||||
return DelegateCodeHelper.getDelegatedCodeForRead();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,11 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.hyperledger.besu.evm.internal.OverflowException;
|
||||
import org.hyperledger.besu.evm.internal.UnderflowException;
|
||||
import org.hyperledger.besu.evm.internal.Words;
|
||||
import org.hyperledger.besu.evm.worldstate.DelegateCodeHelper;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
/** The Ext code size operation. */
|
||||
public class ExtCodeSizeOperation extends AbstractOperation {
|
||||
public class ExtCodeSizeOperation extends AbstractExtCodeOperation {
|
||||
|
||||
static final Bytes EOF_SIZE = Bytes.of(2);
|
||||
|
||||
@@ -103,14 +102,4 @@ public class ExtCodeSizeOperation extends AbstractOperation {
|
||||
return new OperationResult(cost(true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS);
|
||||
}
|
||||
}
|
||||
|
||||
private static Bytes getCode(final Account account) {
|
||||
if (account == null) {
|
||||
return Bytes.EMPTY;
|
||||
}
|
||||
|
||||
return account.hasDelegatedCode()
|
||||
? DelegateCodeHelper.getDelegatedCodeForRead()
|
||||
: account.getCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,10 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
* be executed when a contract has delegated code. This process is necessary to determine the
|
||||
* contract that will be executed and to ensure that the contract is warm in the cache.
|
||||
*/
|
||||
public class DelegatedCodeGasCostHelper {
|
||||
public class CodeDelegationGasCostHelper {
|
||||
|
||||
/** Private constructor to prevent instantiation. */
|
||||
private DelegatedCodeGasCostHelper() {
|
||||
private CodeDelegationGasCostHelper() {
|
||||
// empty constructor
|
||||
}
|
||||
|
||||
@@ -41,25 +41,25 @@ public class DelegatedCodeGasCostHelper {
|
||||
* @param account the account
|
||||
* @return the gas cost and result of the operation
|
||||
*/
|
||||
public static long delegatedCodeGasCost(
|
||||
public static long codeDelegationGasCost(
|
||||
final MessageFrame frame, final GasCalculator gasCalculator, final Account account) {
|
||||
if (!account.hasDelegatedCode()) {
|
||||
if (!account.hasCodeDelegation()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (account.delegatedCodeAddress().isEmpty()) {
|
||||
if (account.codeDelegationAddress().isEmpty()) {
|
||||
throw new RuntimeException("A delegated code account must have a delegated code address");
|
||||
}
|
||||
|
||||
return calculateDelegatedCodeResolutionGas(
|
||||
frame, gasCalculator, account.delegatedCodeAddress().get());
|
||||
return calculateCodeDelegationResolutionGas(
|
||||
frame, gasCalculator, account.codeDelegationAddress().get());
|
||||
}
|
||||
|
||||
private static long calculateDelegatedCodeResolutionGas(
|
||||
private static long calculateCodeDelegationResolutionGas(
|
||||
final MessageFrame frame, final GasCalculator gasCalculator, final Address delegateeAddress) {
|
||||
final boolean delegatedCodeIsWarm =
|
||||
final boolean isWarm =
|
||||
frame.warmUpAddress(delegateeAddress) || gasCalculator.isPrecompile(delegateeAddress);
|
||||
return delegatedCodeIsWarm
|
||||
return isWarm
|
||||
? gasCalculator.getWarmStorageReadCost()
|
||||
: gasCalculator.getColdAccountAccessCost();
|
||||
}
|
||||
@@ -19,20 +19,20 @@ import org.hyperledger.besu.datatypes.Address;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
/** Helper class for 7702 delegated code interactions */
|
||||
public class DelegateCodeHelper {
|
||||
public class CodeDelegationHelper {
|
||||
/**
|
||||
* The designator that is returned when a ExtCode* operation calls a contract with delegated code
|
||||
*/
|
||||
public static final Bytes DELEGATED_CODE_DESIGNATOR = Bytes.fromHexString("ef01");
|
||||
|
||||
/** The prefix that is used to identify delegated code */
|
||||
public static final Bytes DELEGATED_CODE_PREFIX = Bytes.fromHexString("ef0100");
|
||||
public static final Bytes CODE_DELEGATION_PREFIX = Bytes.fromHexString("ef0100");
|
||||
|
||||
/** The size of the delegated code */
|
||||
public static final int DELEGATED_CODE_SIZE = DELEGATED_CODE_PREFIX.size() + Address.SIZE;
|
||||
public static final int DELEGATED_CODE_SIZE = CODE_DELEGATION_PREFIX.size() + Address.SIZE;
|
||||
|
||||
/** create a new DelegateCodeHelper */
|
||||
public DelegateCodeHelper() {
|
||||
public CodeDelegationHelper() {
|
||||
// empty
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ public class DelegateCodeHelper {
|
||||
* @param code the code to check.
|
||||
* @return {@code true} if the code is delegated code, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean hasDelegatedCode(final Bytes code) {
|
||||
public static boolean hasCodeDelegation(final Bytes code) {
|
||||
return code != null
|
||||
&& code.size() == DELEGATED_CODE_SIZE
|
||||
&& code.slice(0, DELEGATED_CODE_PREFIX.size()).equals(DELEGATED_CODE_PREFIX);
|
||||
&& code.slice(0, CODE_DELEGATION_PREFIX.size()).equals(CODE_DELEGATION_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +53,7 @@ public class DelegateCodeHelper {
|
||||
*
|
||||
* @return the hardcoded designator for delegated code: ef01
|
||||
*/
|
||||
public static Bytes getDelegatedCodeForRead() {
|
||||
public static Bytes getCodeDelegationForRead() {
|
||||
return DELEGATED_CODE_DESIGNATOR;
|
||||
}
|
||||
}
|
||||
@@ -14,29 +14,29 @@
|
||||
*/
|
||||
package org.hyperledger.besu.evm.worldstate;
|
||||
|
||||
import static org.hyperledger.besu.evm.worldstate.DelegateCodeHelper.DELEGATED_CODE_PREFIX;
|
||||
import static org.hyperledger.besu.evm.worldstate.DelegateCodeHelper.hasDelegatedCode;
|
||||
import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.CODE_DELEGATION_PREFIX;
|
||||
import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.hasCodeDelegation;
|
||||
|
||||
import org.hyperledger.besu.datatypes.Address;
|
||||
import org.hyperledger.besu.evm.account.Account;
|
||||
import org.hyperledger.besu.evm.account.DelegatedCodeAccount;
|
||||
import org.hyperledger.besu.evm.account.CodeDelegationAccount;
|
||||
import org.hyperledger.besu.evm.account.MutableAccount;
|
||||
import org.hyperledger.besu.evm.account.MutableDelegatedCodeAccount;
|
||||
import org.hyperledger.besu.evm.account.MutableCodeDelegationDelegationAccount;
|
||||
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
|
||||
/** A service that manages the code injection of delegated code. */
|
||||
public class DelegatedCodeService {
|
||||
public class CodeDelegationService {
|
||||
|
||||
private final GasCalculator gasCalculator;
|
||||
|
||||
/**
|
||||
* Creates a new DelegatedCodeService.
|
||||
* Creates a new CodeDelegationService.
|
||||
*
|
||||
* @param gasCalculator the gas calculator to check for pre compiles.
|
||||
*/
|
||||
public DelegatedCodeService(final GasCalculator gasCalculator) {
|
||||
public CodeDelegationService(final GasCalculator gasCalculator) {
|
||||
this.gasCalculator = gasCalculator;
|
||||
}
|
||||
|
||||
@@ -45,17 +45,17 @@ public class DelegatedCodeService {
|
||||
* address. If the address is 0, it will set the code to empty.
|
||||
*
|
||||
* @param account the account to which the delegated code is added.
|
||||
* @param delegatedCodeAddress the address of the target of the authorization.
|
||||
* @param codeDelegationAddress the address of the target of the authorization.
|
||||
*/
|
||||
public void processDelegatedCodeAuthorization(
|
||||
final MutableAccount account, final Address delegatedCodeAddress) {
|
||||
// authorization to zero address removes any delegated code
|
||||
if (delegatedCodeAddress.equals(Address.ZERO)) {
|
||||
public void processCodeDelegation(
|
||||
final MutableAccount account, final Address codeDelegationAddress) {
|
||||
// code delegation to zero address removes any delegated code
|
||||
if (codeDelegationAddress.equals(Address.ZERO)) {
|
||||
account.setCode(Bytes.EMPTY);
|
||||
return;
|
||||
}
|
||||
|
||||
account.setCode(Bytes.concatenate(DELEGATED_CODE_PREFIX, delegatedCodeAddress));
|
||||
account.setCode(Bytes.concatenate(CODE_DELEGATION_PREFIX, codeDelegationAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,8 +64,8 @@ public class DelegatedCodeService {
|
||||
* @param account the account to check.
|
||||
* @return {@code true} if the account can set delegated code, {@code false} otherwise.
|
||||
*/
|
||||
public boolean canSetDelegatedCode(final Account account) {
|
||||
return account.getCode().isEmpty() || hasDelegatedCode(account.getCode());
|
||||
public boolean canSetCodeDelegation(final Account account) {
|
||||
return account.getCode().isEmpty() || hasCodeDelegation(account.getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,11 +77,11 @@ public class DelegatedCodeService {
|
||||
* otherwise.
|
||||
*/
|
||||
public Account processAccount(final WorldUpdater worldUpdater, final Account account) {
|
||||
if (account == null || !hasDelegatedCode(account.getCode())) {
|
||||
if (account == null || !hasCodeDelegation(account.getCode())) {
|
||||
return account;
|
||||
}
|
||||
|
||||
return new DelegatedCodeAccount(
|
||||
return new CodeDelegationAccount(
|
||||
worldUpdater, account, resolveDelegatedAddress(account.getCode()), gasCalculator);
|
||||
}
|
||||
|
||||
@@ -95,15 +95,15 @@ public class DelegatedCodeService {
|
||||
*/
|
||||
public MutableAccount processMutableAccount(
|
||||
final WorldUpdater worldUpdater, final MutableAccount account) {
|
||||
if (account == null || !hasDelegatedCode(account.getCode())) {
|
||||
if (account == null || !hasCodeDelegation(account.getCode())) {
|
||||
return account;
|
||||
}
|
||||
|
||||
return new MutableDelegatedCodeAccount(
|
||||
return new MutableCodeDelegationDelegationAccount(
|
||||
worldUpdater, account, resolveDelegatedAddress(account.getCode()), gasCalculator);
|
||||
}
|
||||
|
||||
private Address resolveDelegatedAddress(final Bytes code) {
|
||||
return Address.wrap(code.slice(DELEGATED_CODE_PREFIX.size()));
|
||||
return Address.wrap(code.slice(CODE_DELEGATION_PREFIX.size()));
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,11 @@ import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The EVM world updater. This class is a wrapper around a WorldUpdater that provides an
|
||||
* AuthorizedCodeService to manage the authorized code for accounts.
|
||||
* CodeDelegationService to manage the code delegations for accounts.
|
||||
*/
|
||||
public class EVMWorldUpdater implements WorldUpdater {
|
||||
private final WorldUpdater rootWorldUpdater;
|
||||
private final DelegatedCodeService delegatedCodeService;
|
||||
private final CodeDelegationService codeDelegationService;
|
||||
|
||||
/**
|
||||
* Instantiates a new EVM world updater.
|
||||
@@ -39,49 +39,49 @@ public class EVMWorldUpdater implements WorldUpdater {
|
||||
* @param gasCalculator the gas calculator to check for precompiles.
|
||||
*/
|
||||
public EVMWorldUpdater(final WorldUpdater rootWorldUpdater, final GasCalculator gasCalculator) {
|
||||
this(rootWorldUpdater, new DelegatedCodeService(gasCalculator));
|
||||
this(rootWorldUpdater, new CodeDelegationService(gasCalculator));
|
||||
}
|
||||
|
||||
private EVMWorldUpdater(
|
||||
final WorldUpdater rootWorldUpdater, final DelegatedCodeService delegatedCodeService) {
|
||||
final WorldUpdater rootWorldUpdater, final CodeDelegationService codeDelegationService) {
|
||||
this.rootWorldUpdater = rootWorldUpdater;
|
||||
this.delegatedCodeService = delegatedCodeService;
|
||||
this.codeDelegationService = codeDelegationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorized code service.
|
||||
* Code delegation service.
|
||||
*
|
||||
* @return the authorized code service
|
||||
* @return the code delegation service
|
||||
*/
|
||||
public DelegatedCodeService authorizedCodeService() {
|
||||
return delegatedCodeService;
|
||||
public CodeDelegationService codeDelegationService() {
|
||||
return codeDelegationService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) {
|
||||
return delegatedCodeService.processMutableAccount(
|
||||
return codeDelegationService.processMutableAccount(
|
||||
this, rootWorldUpdater.createAccount(address, nonce, balance));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableAccount getAccount(final Address address) {
|
||||
return delegatedCodeService.processMutableAccount(this, rootWorldUpdater.getAccount(address));
|
||||
return codeDelegationService.processMutableAccount(this, rootWorldUpdater.getAccount(address));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableAccount getOrCreate(final Address address) {
|
||||
return delegatedCodeService.processMutableAccount(this, rootWorldUpdater.getOrCreate(address));
|
||||
return codeDelegationService.processMutableAccount(this, rootWorldUpdater.getOrCreate(address));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableAccount getOrCreateSenderAccount(final Address address) {
|
||||
return delegatedCodeService.processMutableAccount(
|
||||
return codeDelegationService.processMutableAccount(
|
||||
this, rootWorldUpdater.getOrCreateSenderAccount(address));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableAccount getSenderAccount(final MessageFrame frame) {
|
||||
return delegatedCodeService.processMutableAccount(
|
||||
return codeDelegationService.processMutableAccount(
|
||||
this, rootWorldUpdater.getSenderAccount(frame));
|
||||
}
|
||||
|
||||
@@ -114,17 +114,17 @@ public class EVMWorldUpdater implements WorldUpdater {
|
||||
public Optional<WorldUpdater> parentUpdater() {
|
||||
return rootWorldUpdater.parentUpdater().isPresent()
|
||||
? Optional.of(
|
||||
new EVMWorldUpdater(rootWorldUpdater.parentUpdater().get(), delegatedCodeService))
|
||||
new EVMWorldUpdater(rootWorldUpdater.parentUpdater().get(), codeDelegationService))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldUpdater updater() {
|
||||
return new EVMWorldUpdater(rootWorldUpdater.updater(), delegatedCodeService);
|
||||
return new EVMWorldUpdater(rootWorldUpdater.updater(), codeDelegationService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account get(final Address address) {
|
||||
return delegatedCodeService.processAccount(this, rootWorldUpdater.get(address));
|
||||
return codeDelegationService.processAccount(this, rootWorldUpdater.get(address));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user