Add a method to get the encoded preimage of a transaction (#8414)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
This commit is contained in:
Fabio Di Fabio
2025-03-14 12:19:14 +01:00
committed by GitHub
parent a190be3f3c
commit ca2e5692f7
3 changed files with 95 additions and 1 deletions

View File

@@ -228,6 +228,13 @@ public interface Transaction {
*/
Bytes encoded();
/**
* Returns the preimage of the transaction with the proper encoding
*
* @return the encoded preimage of the transaction as Bytes
*/
Bytes encodedPreimage();
/**
* Returns the size in bytes of the encoded transaction.
*

View File

@@ -727,6 +727,59 @@ public class Transaction
if (transactionType.requiresChainId()) {
checkArgument(chainId.isPresent(), "Transaction type %s requires chainId", transactionType);
}
final Bytes preimage =
getPreimage(
transactionType,
nonce,
gasPrice,
maxPriorityFeePerGas,
maxFeePerGas,
maxFeePerBlobGas,
gasLimit,
to,
value,
payload,
accessList,
versionedHashes,
codeDelegationList,
chainId);
return keccak256(preimage);
}
@Override
public Bytes encodedPreimage() {
return getPreimage(
transactionType,
nonce,
gasPrice.orElse(null),
maxPriorityFeePerGas.orElse(null),
maxFeePerGas.orElse(null),
maxFeePerBlobGas.orElse(null),
gasLimit,
to,
value,
payload,
maybeAccessList,
versionedHashes.orElse(null),
maybeCodeDelegationList,
chainId);
}
private static Bytes getPreimage(
final TransactionType transactionType,
final long nonce,
final Wei gasPrice,
final Wei maxPriorityFeePerGas,
final Wei maxFeePerGas,
final Wei maxFeePerBlobGas,
final long gasLimit,
final Optional<Address> to,
final Wei value,
final Bytes payload,
final Optional<List<AccessListEntry>> accessList,
final List<VersionedHash> versionedHashes,
final Optional<List<CodeDelegation>> codeDelegationList,
final Optional<BigInteger> chainId) {
final Bytes preimage =
switch (transactionType) {
case FRONTIER -> frontierPreimage(nonce, gasPrice, gasLimit, to, value, payload, chainId);
@@ -783,7 +836,7 @@ public class Transaction
new IllegalStateException(
"Developer error: the transaction should be guaranteed to have a code delegations here")));
};
return keccak256(preimage);
return preimage;
}
private static Bytes frontierPreimage(

View File

@@ -16,17 +16,28 @@ package org.hyperledger.besu.ethereum.core;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.crypto.KeyPair;
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;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import java.math.BigInteger;
import java.util.Optional;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.Test;
public class TransactionIntegrationTest {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
private static final KeyPair senderKeys = SIGNATURE_ALGORITHM.get().generateKeyPair();
@Test
public void
@@ -70,4 +81,27 @@ public class TransactionIntegrationTest {
assertThat(transaction.getTo())
.contains(Address.fromHexString("0xd30c3d13b07029deba00de1da369cd69a02c2056"));
}
@Test
public void shouldReturnEncodedPreimageCorrectly() {
final var tx =
new TransactionTestFixture()
.type(TransactionType.EIP1559)
.chainId(Optional.of(BigInteger.ONE))
.nonce(2)
.gasLimit(23456)
.to(Optional.of(Address.fromHexString("0x1234000000000000000000000000000000004321")))
.value(Wei.of(2048))
.payload(Bytes.fromHexString("0xabcd"))
.maxFeePerGas(Optional.of(Wei.of(12345)))
.maxPriorityFeePerGas(Optional.of(Wei.of(6789)))
.createTransaction(senderKeys);
final var encodedPreimage = tx.encodedPreimage();
final var expectedEncodedPreimage =
"0x02e70102821a85823039825ba094123400000000000000000000000000000000432182080082abcdc0";
assertThat(encodedPreimage.toString()).isEqualTo(expectedEncodedPreimage);
}
}