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

EIP-7702: devnet-4 changes #7809

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
c71d4af
warm up to address at tx start if account is delegated, restrict auth…
daniellehrner Oct 2, 2024
67bab68
Merge branch 'main' into fix/issue-7706/warmup_to_when_delegated
daniellehrner Oct 3, 2024
49a4411
rename requestsRoot to requestsHash
jframe Oct 9, 2024
196bf10
return no code if account has delegated code to precompile, treat pre…
daniellehrner Oct 9, 2024
a2abff2
make accessListWarmAddresses generic again
daniellehrner Oct 9, 2024
dcefdce
Merge branch 'fix/issue-7706/warmup_to_when_delegated' into pectra-de…
daniellehrner Oct 9, 2024
6393399
warm delegatee account if transaction destination has delegated code
daniellehrner Oct 9, 2024
1269cc1
Merge branch 'main' into pectra-devnet4-7702
daniellehrner Oct 10, 2024
d7e5686
* verify auth nonce less than 2**64-1 during auth processing
daniellehrner Oct 10, 2024
cdc9bd5
generalised requests flat encoding and engine api changes
jframe Oct 14, 2024
cee6abc
javadoc
jframe Oct 14, 2024
8f346f4
get tests passing
jframe Oct 15, 2024
4e12780
get tests passing
jframe Oct 15, 2024
42e6865
Merge remote-tracking branch 'upstream/main' into 7685_flat_encoding
jframe Oct 15, 2024
f0d5a24
clean code
jframe Oct 15, 2024
0424317
change requests to single requestData for each requestType
jframe Oct 15, 2024
86f5049
fix PoWBlockCreatorTest after requests data type change
jframe Oct 15, 2024
722823e
don't return request type in getPayload result
jframe Oct 15, 2024
24a33e7
include requests in t8n response
jframe Oct 16, 2024
24de847
update contract addresses for consolidation requests and withdrawal r…
jframe Oct 16, 2024
532cb9d
fix requestHash calculation
jframe Oct 16, 2024
079bcfd
Ensure that execution requests always return a response
jframe Oct 16, 2024
9a98c12
Merge branch 'main' into pectra-devnet4-7702
daniellehrner Oct 16, 2024
c19f93f
Merge remote-tracking branch 'jason/7685_flat_encoding' into pectra-d…
daniellehrner Oct 16, 2024
bdb0cb3
added and fixed bound checks, fixed some compilation errors after the…
daniellehrner Oct 16, 2024
eff46b0
revert changes to evm tool spec tests
jframe Oct 17, 2024
1fdf0db
clean up
jframe Oct 17, 2024
9c2a623
replace AbstractSystemCallRequestProcessor to concrete class and remo…
jframe Oct 17, 2024
afd9023
spotless
jframe Oct 17, 2024
20ca19e
update evmtool tests for 7685 changes
jframe Oct 17, 2024
3ee1b31
use empty requests hash prague fork at genesis
jframe Oct 17, 2024
21b7aae
review suggestions
jframe Oct 17, 2024
6457be5
Merge remote-tracking branch 'jason/7685_flat_encoding' into pectra-d…
daniellehrner Oct 17, 2024
7522a77
temporarily comment out osakaTime from Prague
daniellehrner Oct 17, 2024
89d4950
Merge branch 'main' into pectra-devnet4-7702
daniellehrner Oct 17, 2024
7574c84
engine API validation
jframe Oct 18, 2024
ac812b2
Merge remote-tracking branch 'upstream/main' into 7685_flat_encoding
jframe Oct 18, 2024
95d1606
update plugin API hash
jframe Oct 18, 2024
4c62cae
fix GenesisStateTest
jframe Oct 18, 2024
9a317b1
Merge remote-tracking branch 'jason/7685_flat_encoding' into pectra-d…
daniellehrner Oct 18, 2024
8ab3aac
comment out unused evmWorldUpdater.parentUpdater() check
daniellehrner Oct 21, 2024
9ebc32b
Merge branch 'main' into pectra-devnet-4
daniellehrner Oct 24, 2024
75a3397
added CodeDelegationProcessorTest
daniellehrner Oct 27, 2024
759fab9
Merge branch 'main' into pectra-devnet-4
daniellehrner Nov 8, 2024
97af121
Merge branch 'main' into pectra-devnet-4
daniellehrner Nov 25, 2024
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 @@ -214,7 +214,7 @@ public SECPSignature createSignature(final BigInteger r, final BigInteger s, fin

@Override
public CodeDelegationSignature createCodeDelegationSignature(
final BigInteger r, final BigInteger s, final BigInteger yParity) {
final BigInteger r, final BigInteger s, final byte yParity) {
return CodeDelegationSignature.create(r, s, yParity);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public CodeDelegationSignature(final BigInteger r, final BigInteger s, final byt
* @return the new CodeDelegationSignature
*/
public static CodeDelegationSignature create(
final BigInteger r, final BigInteger s, final BigInteger yParity) {
final BigInteger r, final BigInteger s, final byte yParity) {
checkNotNull(r);
checkNotNull(s);

Expand All @@ -56,11 +56,6 @@ public static CodeDelegationSignature create(
"Invalid 's' value, should be < 2^256 but got " + s.toString(16));
}

if (yParity.compareTo(TWO_POW_256) >= 0) {
throw new IllegalArgumentException(
"Invalid 'yParity' value, should be < 2^256 but got " + yParity.toString(16));
}

return new CodeDelegationSignature(r, s, yParity.byteValue());
return new CodeDelegationSignature(r, s, yParity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ Optional<SECPPublicKey> recoverPublicKeyFromSignature(
* @return the code delegation signature
*/
CodeDelegationSignature createCodeDelegationSignature(
final BigInteger r, final BigInteger s, final BigInteger yParity);
final BigInteger r, final BigInteger s, final byte yParity);

/**
* Decode secp signature.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ class CodeDelegationSignatureTest {
void testValidInputs() {
BigInteger r = BigInteger.ONE;
BigInteger s = BigInteger.TEN;
BigInteger yParity = BigInteger.ONE;
byte yParity = (byte) 1;

CodeDelegationSignature result = CodeDelegationSignature.create(r, s, yParity);

assertThat(r).isEqualTo(result.getR());
assertThat(s).isEqualTo(result.getS());
assertThat(yParity.byteValue()).isEqualTo(result.getRecId());
assertThat(yParity).isEqualTo(result.getRecId());
}

@Test
void testNullRValue() {
BigInteger s = BigInteger.TEN;
BigInteger yParity = BigInteger.ZERO;
byte yParity = (byte) 0;

assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> CodeDelegationSignature.create(null, s, yParity));
Expand All @@ -50,7 +50,7 @@ void testNullRValue() {
@Test
void testNullSValue() {
BigInteger r = BigInteger.ONE;
BigInteger yParity = BigInteger.ZERO;
byte yParity = (byte) 0;

assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> CodeDelegationSignature.create(r, null, yParity));
Expand All @@ -60,7 +60,7 @@ void testNullSValue() {
void testRValueExceedsTwoPow256() {
BigInteger r = TWO_POW_256;
BigInteger s = BigInteger.TEN;
BigInteger yParity = BigInteger.ZERO;
byte yParity = (byte) 0;

assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> CodeDelegationSignature.create(r, s, yParity))
Expand All @@ -71,34 +71,23 @@ void testRValueExceedsTwoPow256() {
void testSValueExceedsTwoPow256() {
BigInteger r = BigInteger.ONE;
BigInteger s = TWO_POW_256;
BigInteger yParity = BigInteger.ZERO;
byte yParity = (byte) 0;

assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> CodeDelegationSignature.create(r, s, yParity))
.withMessageContainingAll("Invalid 's' value, should be < 2^256");
}

@Test
void testYParityExceedsTwoPow256() {
BigInteger r = BigInteger.ONE;
BigInteger s = BigInteger.TWO;
BigInteger yParity = TWO_POW_256;

assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> CodeDelegationSignature.create(r, s, yParity))
.withMessageContainingAll("Invalid 'yParity' value, should be < 2^256");
}

@Test
void testValidYParityZero() {
BigInteger r = BigInteger.ONE;
BigInteger s = BigInteger.TEN;
BigInteger yParity = BigInteger.ZERO;
byte yParity = (byte) 0;

CodeDelegationSignature result = CodeDelegationSignature.create(r, s, yParity);

assertThat(r).isEqualTo(result.getR());
assertThat(s).isEqualTo(result.getS());
assertThat(yParity.byteValue()).isEqualTo(result.getRecId());
assertThat(yParity).isEqualTo(result.getRecId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*/
public interface CodeDelegation {
/** The cost of delegating code on an existing account. */
long PER_AUTH_BASE_COST = 2_500L;
long PER_AUTH_BASE_COST = 12_500L;

/**
* Return the chain id.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ public JsonRpcResponse process(
case INVALID_PROPOSAL_PARAMS:
case INVALID_REMOTE_CAPABILITIES_PARAMS:
case INVALID_REWARD_PERCENTILES_PARAMS:
case INVALID_REQUESTS_PARAMS:
case INVALID_SEALER_ID_PARAMS:
case INVALID_STORAGE_KEYS_PARAMS:
case INVALID_SUBSCRIPTION_PARAMS:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public enum RpcErrorType implements RpcMethodError {
INVALID_REMOTE_CAPABILITIES_PARAMS(
INVALID_PARAMS_ERROR_CODE, "Invalid remote capabilities params"),
INVALID_REWARD_PERCENTILES_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid reward percentiles params"),
INVALID_REQUESTS_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid requests params"),
INVALID_SEALER_ID_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid sealer ID params"),
INVALID_STORAGE_KEYS_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid storage keys params"),
INVALID_SUBSCRIPTION_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid subscription params"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationEncoder;
import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationTransactionEncoder;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;

import java.math.BigInteger;
Expand Down Expand Up @@ -140,7 +140,7 @@ public BigInteger s() {

private Optional<Address> computeAuthority() {
BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
CodeDelegationEncoder.encodeSingleCodeDelegationWithoutSignature(this, rlpOutput);
CodeDelegationTransactionEncoder.encodeSingleCodeDelegationWithoutSignature(this, rlpOutput);

final Hash hash = Hash.hash(Bytes.concatenate(MAGIC, rlpOutput.encoded()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.encoding.AccessListTransactionEncoder;
import org.hyperledger.besu.ethereum.core.encoding.BlobTransactionEncoder;
import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationEncoder;
import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationTransactionEncoder;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
Expand Down Expand Up @@ -937,7 +937,8 @@ private static Bytes codeDelegationPreimage(
chainId,
accessList,
rlpOutput);
CodeDelegationEncoder.encodeCodeDelegationInner(authorizationList, rlpOutput);
CodeDelegationTransactionEncoder.encodeCodeDelegationInner(
authorizationList, rlpOutput);
rlpOutput.endList();
});
return Bytes.concatenate(Bytes.of(TransactionType.DELEGATE_CODE.getSerializedType()), encoded);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static CodeDelegation decodeInnerPayload(final RLPInput input) {
final Address address = Address.wrap(input.readBytes());
final long nonce = input.readLongScalar();

final BigInteger yParity = input.readUInt256Scalar().toUnsignedBigInteger();
final byte yParity = (byte) input.readUnsignedByteScalar();
final BigInteger r = input.readUInt256Scalar().toUnsignedBigInteger();
final BigInteger s = input.readUInt256Scalar().toUnsignedBigInteger();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@

import org.apache.tuweni.bytes.Bytes;

public class CodeDelegationEncoder {
public class CodeDelegationTransactionEncoder {

private CodeDelegationEncoder() {
private CodeDelegationTransactionEncoder() {
// private constructor
}

Expand All @@ -49,7 +49,7 @@ public static void encodeSingleCodeDelegation(
final CodeDelegation payload, final RLPOutput rlpOutput) {
rlpOutput.startList();
encodeAuthorizationDetails(payload, rlpOutput);
rlpOutput.writeIntScalar(payload.signature().getRecId());
rlpOutput.writeUnsignedByte(payload.signature().getRecId() & 0xFF);
rlpOutput.writeBigIntegerScalar(payload.signature().getR());
rlpOutput.writeBigIntegerScalar(payload.signature().getS());
rlpOutput.endList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ interface Encoder {
TransactionType.BLOB,
BlobTransactionEncoder::encode,
TransactionType.DELEGATE_CODE,
CodeDelegationEncoder::encode);
CodeDelegationTransactionEncoder::encode);

private static final ImmutableMap<TransactionType, Encoder> POOLED_TRANSACTION_ENCODERS =
ImmutableMap.of(TransactionType.BLOB, BlobPooledTransactionEncoder::encode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.mainnet;

import static org.hyperledger.besu.evm.account.Account.MAX_NONCE;

import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.core.CodeDelegation;
import org.hyperledger.besu.ethereum.core.Transaction;
Expand All @@ -30,9 +32,12 @@ public class CodeDelegationProcessor {
private static final Logger LOG = LoggerFactory.getLogger(CodeDelegationProcessor.class);

private final Optional<BigInteger> maybeChainId;
private final BigInteger halfCurveOrder;

public CodeDelegationProcessor(final Optional<BigInteger> maybeChainId) {
public CodeDelegationProcessor(
final Optional<BigInteger> maybeChainId, final BigInteger halfCurveOrder) {
this.maybeChainId = maybeChainId;
this.halfCurveOrder = halfCurveOrder;
}

/**
Expand Down Expand Up @@ -89,6 +94,22 @@ private void processAuthorization(
return;
}

if (codeDelegation.nonce() == MAX_NONCE) {
LOG.trace("Nonce of code delegation must be less than 2^64-1");
return;
}

if (codeDelegation.signature().getS().compareTo(halfCurveOrder) > 0) {
LOG.trace(
"Invalid signature for code delegation. S value must be less or equal than the half curve order.");
return;
}

if (codeDelegation.signature().getRecId() != 0 && codeDelegation.signature().getRecId() != 1) {
LOG.trace("Invalid signature for code delegation. RecId must be 0 or 1.");
return;
}

final Optional<Address> authorizer = codeDelegation.authorizer();
if (authorizer.isEmpty()) {
LOG.trace("Invalid signature for code delegation");
Expand Down Expand Up @@ -128,7 +149,9 @@ private void processAuthorization(
result.incremenentAlreadyExistingDelegators();
}

evmWorldUpdater.authorizedCodeService().addDelegatedCode(authority, codeDelegation.address());
evmWorldUpdater
.authorizedCodeService()
.processDelegatedCodeAuthorization(authority, codeDelegation.address());
authority.incrementNonce();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.PowAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
Expand Down Expand Up @@ -80,6 +82,8 @@
import java.util.Set;
import java.util.stream.IntStream;

import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.io.Resources;
import io.vertx.core.json.JsonArray;

Expand All @@ -89,6 +93,9 @@ public abstract class MainnetProtocolSpecs {
private static final Address RIPEMD160_PRECOMPILE =
Address.fromHexString("0x0000000000000000000000000000000000000003");

private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);

// A consensus bug at Ethereum mainnet transaction 0xcf416c53
// deleted an empty account even when the message execution scope
// failed, but the transaction itself succeeded.
Expand Down Expand Up @@ -714,7 +721,8 @@ static ProtocolSpecBuilder cancunDefinition(
evmConfiguration.evmStackSize(),
feeMarket,
CoinbaseFeePriceCalculator.eip1559(),
new CodeDelegationProcessor(chainId)))
new CodeDelegationProcessor(
chainId, SIGNATURE_ALGORITHM.get().getHalfCurveOrder())))
// change to check for max blob gas per block for EIP-4844
.transactionValidatorFactoryBuilder(
(evm, gasLimitCalculator, feeMarket) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public TransactionProcessingResult processTransaction(
final TransactionValidationParams transactionValidationParams,
final PrivateMetadataUpdater privateMetadataUpdater,
final Wei blobGasPrice) {
final EVMWorldUpdater evmWorldUpdater = new EVMWorldUpdater(worldState);
final EVMWorldUpdater evmWorldUpdater = new EVMWorldUpdater(worldState, gasCalculator);
try {
final var transactionValidator = transactionValidatorFactory.get();
LOG.trace("Starting execution of {}", transaction);
Expand Down Expand Up @@ -346,12 +346,26 @@ public TransactionProcessingResult processTransaction(
throw new RuntimeException("Code delegation processor is required for 7702 transactions");
}

// if (evmWorldUpdater.parentUpdater().isEmpty()) {
// throw new RuntimeException("Code delegation needs the underlying world state");
// }

// get the underlying world state to commit code delegations without the transaction having
// to succeed
// final EVMWorldUpdater parentUpdater =
// (EVMWorldUpdater) evmWorldUpdater.parentUpdater().get();

final CodeDelegationResult codeDelegationResult =
maybeCodeDelegationProcessor.get().process(evmWorldUpdater, transaction);
warmAddressList.addAll(codeDelegationResult.accessedDelegatorAddresses());
codeDelegationRefund =
gasCalculator.calculateDelegateCodeGasRefund(
(codeDelegationResult.alreadyExistingDelegators()));

evmWorldUpdater.commit();

// authorizations will always be commited independently if the transaction succeeds or not
// parentUpdater.commit();
}

final List<AccessListEntry> accessListEntries = transaction.getAccessList().orElse(List.of());
Expand Down Expand Up @@ -415,7 +429,6 @@ public TransactionProcessingResult processTransaction(
.miningBeneficiary(miningBeneficiary)
.blockHashLookup(blockHashLookup)
.contextVariables(contextVariablesBuilder.build())
.accessListWarmAddresses(warmAddressList)
.accessListWarmStorage(storageList);

if (transaction.getVersionedHashes().isPresent()) {
Expand All @@ -439,11 +452,17 @@ public TransactionProcessingResult processTransaction(
.contract(contractAddress)
.inputData(initCodeBytes.slice(code.getSize()))
.code(code)
.accessListWarmAddresses(warmAddressList)
.build();
} else {
@SuppressWarnings("OptionalGetWithoutIsPresent") // isContractCall tests isPresent
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());
}

initialFrame =
commonMessageFrameBuilder
.type(MessageFrame.Type.MESSAGE_CALL)
Expand All @@ -454,6 +473,7 @@ public TransactionProcessingResult processTransaction(
maybeContract
.map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode()))
.orElse(CodeV0.EMPTY_CODE))
.accessListWarmAddresses(warmAddressList)
.build();
}
Deque<MessageFrame> messageFrameStack = initialFrame.getMessageFrameStack();
Expand Down
Loading
Loading