Skip to content

Commit

Permalink
Adapt gas_consumed migration query to get failed initcode from contra…
Browse files Browse the repository at this point in the history
…ct_result for failed contract create transactions (#7883)

This PR adapts migration query for gas_consumed to check if failed_initcode column is not null, this way we handle the case where if a contract create transaction is failed and we haven't populated the contract table we will still factor the initcode in the intrinsic gas calculation.

---------

Signed-off-by: Valentin Valkanov <[email protected]>
  • Loading branch information
Valentin Valkanov authored Mar 8, 2024
1 parent d64ac13 commit 2360f6b
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@ with contract_action_gas_usage as (
e.created_timestamp,
-- Correctly assign `payload` based on whether it's a contract creation or call.
coalesce(
case
when cr.consensus_timestamp = e.created_timestamp then c.initcode
else cr.function_parameters
end, ''::bytea) as payload,
case
when cr.consensus_timestamp = e.created_timestamp then c.initcode
when cr.failed_initcode is not null then cr.failed_initcode
else cr.function_parameters
end, ''::bytea) as payload,
-- Contract creation has an extra cost of 32000
case when cr.consensus_timestamp = e.created_timestamp then 32000 else 0 end as creation_cost
case
when cr.consensus_timestamp = e.created_timestamp then 32000
when cr.failed_initcode is not null then 32000
else 0
end as creation_cost
from
contract_result cr
left join contract c on cr.contract_id = c.id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ void migrate() {
ethTx1.getConsensusTimestamp(),
domainBuilder.entityId(),
domainBuilder.entityId().getId(),
null,
domainBuilder);
persistMigrationContractResult(migrationContractResult, jdbcTemplate);

Expand Down Expand Up @@ -161,7 +162,7 @@ private List<MigrationContractResult> findAllContractResults() {
return jdbcTemplate.query(
"""
select amount, bloom, call_result, consensus_timestamp, contract_id, created_contract_ids,
error_message, function_parameters, function_result, gas_limit, gas_used, payer_account_id,
error_message, failed_initcode, function_parameters, function_result, gas_limit, gas_used, payer_account_id,
sender_id, transaction_hash, transaction_index, transaction_nonce,
transaction_result from contract_result
""",
Expand All @@ -178,6 +179,7 @@ private List<MigrationContractResult> findAllContractResults() {
.createdContractIds(
createdContractIds == null ? null : List.of((Long[]) createdContractIds.getArray()))
.errorMessage(rs.getString("error_message"))
.failedInitcode(rs.getBytes("failed_initcode"))
.functionParameters(rs.getBytes("function_parameters"))
.functionResult(rs.getBytes("function_result"))
.gasLimit(rs.getLong("gas_limit"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ void migrate() {
.persist();

var migrationContractResult1 = createMigrationContractResult(
transferTimestamp1, spender1, domainBuilder.entityId().getId(), domainBuilder);
transferTimestamp1, spender1, domainBuilder.entityId().getId(), null, domainBuilder);
persistMigrationContractResult(migrationContractResult1, jdbcTemplate);

// Token1 allowances granted by owner1, note the first token allowance's amount didn't change while the
Expand Down Expand Up @@ -113,7 +113,7 @@ void migrate() {
.persist();

var migrationContractResult2 = createMigrationContractResult(
transferTimestamp2, spender1, domainBuilder.entityId().getId(), domainBuilder);
transferTimestamp2, spender1, domainBuilder.entityId().getId(), null, domainBuilder);
persistMigrationContractResult(migrationContractResult2, jdbcTemplate);

// Token2 allowance granted by owner1 to spender2
Expand All @@ -135,7 +135,7 @@ void migrate() {
.persist();

var migrationContractResult3 = createMigrationContractResult(
transferTimestamp3, spender2, domainBuilder.entityId().getId(), domainBuilder);
transferTimestamp3, spender2, domainBuilder.entityId().getId(), null, domainBuilder);
persistMigrationContractResult(migrationContractResult3, jdbcTemplate);
// A normal token transfer using token allowance, note due to the inaccuracy in how we mark a transfer as
// is_approval, the aggregated spent amount is 1000 + 4100 > granted amount 5000, the migration should have a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class GasConsumedMigrationTest extends ImporterIntegrationTest {

private final JdbcTemplate jdbcTemplate;

@Value("classpath:db/migration/v1/V1.94.1__add_gas_consumed_field.sql")
@Value("classpath:db/migration/v1/V1.94.1.1__add_gas_consumed_field.sql")
private final Resource sql;

private final TransactionTemplate transactionTemplate;
Expand Down Expand Up @@ -87,36 +87,42 @@ void empty() {
void migrate() {
// Given
final var ethTxCreate = domainBuilder.ethereumTransaction(true).persist();
final var ethTxCreate1 = domainBuilder.ethereumTransaction(true).persist();
final var ethTxCall = domainBuilder.ethereumTransaction(true).persist();

// run migration to create gas_consumed column
runMigration();

persistData(ethTxCreate, true);
persistData(ethTxCall, false);
persistData(ethTxCreate, true, null);
persistData(ethTxCreate1, false, new byte[] {1, 0, 0, 1, 1, 1});
persistData(ethTxCall, false, null);

// run migration to populate gas_consumed column
runMigration();

// then
assertThat(contractResultRepository.findAll())
.extracting(ContractResult::getGasConsumed)
.containsExactly(53296L, 22224L);
.containsExactly(53296L, 53272L, 22224L);
}

private void persistData(EthereumTransaction ethTx, boolean topLevelCreate) {
private void persistData(EthereumTransaction ethTx, boolean successTopLevelCreate, byte[] failedInitCode) {
final var contract = domainBuilder
.contract()
.customize(c -> c.initcode(new byte[] {1, 0, 0, 0, 0, 1, 1, 1, 1}))
.persist();
domainBuilder
.entity()
.customize(e -> e.createdTimestamp(
topLevelCreate ? ethTx.getConsensusTimestamp() : ethTx.getConsensusTimestamp() + 1))
successTopLevelCreate ? ethTx.getConsensusTimestamp() : ethTx.getConsensusTimestamp() + 1))
.customize(e -> e.id(contract.getId()))
.persist();
var migrateContractResult = createMigrationContractResult(
ethTx.getConsensusTimestamp(), domainBuilder.entityId(), contract.getId(), domainBuilder);
ethTx.getConsensusTimestamp(),
domainBuilder.entityId(),
contract.getId(),
failedInitCode,
domainBuilder);
persistMigrationContractResult(migrateContractResult, jdbcTemplate);
domainBuilder
.contractAction()
Expand Down Expand Up @@ -154,6 +160,7 @@ public static class MigrationContractResult {
private long contractId;
private List<Long> createdContractIds;
private String errorMessage;
private byte[] failedInitcode;
private byte[] functionParameters;
private byte[] functionResult;
private Long gasLimit;
Expand All @@ -167,7 +174,7 @@ public static class MigrationContractResult {
}

public static MigrationContractResult createMigrationContractResult(
long timestamp, EntityId senderId, long contractId, DomainBuilder domainBuilder) {
long timestamp, EntityId senderId, long contractId, byte[] failedInitcode, DomainBuilder domainBuilder) {
return MigrationContractResult.builder()
.amount(1000L)
.bloom(domainBuilder.bytes(256))
Expand All @@ -176,6 +183,7 @@ public static MigrationContractResult createMigrationContractResult(
.contractId(contractId)
.createdContractIds(List.of(domainBuilder.entityId().getId()))
.errorMessage("")
.failedInitcode(failedInitcode)
.functionParameters(domainBuilder.bytes(64))
.functionResult(domainBuilder.bytes(128))
.gasLimit(200L)
Expand All @@ -194,9 +202,9 @@ public static void persistMigrationContractResult(final MigrationContractResult
"""
insert into contract_result
(amount, bloom, call_result, consensus_timestamp, contract_id, created_contract_ids,
error_message, function_parameters, function_result, gas_limit, gas_used,
error_message, failed_initcode, function_parameters, function_result, gas_limit, gas_used,
payer_account_id, sender_id, transaction_hash, transaction_index, transaction_nonce,
transaction_result) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
transaction_result) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""";

jdbcTemplate.update(sql, ps -> {
Expand All @@ -211,16 +219,17 @@ public static void persistMigrationContractResult(final MigrationContractResult
ps.getConnection().createArrayOf("bigint", createdContractIdsArray);
ps.setArray(6, createdContractIdsSqlArray);
ps.setString(7, result.getErrorMessage());
ps.setBytes(8, result.getFunctionParameters());
ps.setBytes(9, result.getFunctionResult());
ps.setLong(10, result.getGasLimit());
ps.setLong(11, result.getGasUsed());
ps.setObject(12, result.getPayerAccountId().getId());
ps.setObject(13, result.getSenderId().getId());
ps.setBytes(14, result.getTransactionHash());
ps.setInt(15, result.getTransactionIndex());
ps.setInt(16, result.getTransactionNonce());
ps.setInt(17, result.getTransactionResult());
ps.setBytes(8, result.getFailedInitcode());
ps.setBytes(9, result.getFunctionParameters());
ps.setBytes(10, result.getFunctionResult());
ps.setLong(11, result.getGasLimit());
ps.setLong(12, result.getGasUsed());
ps.setObject(13, result.getPayerAccountId().getId());
ps.setObject(14, result.getSenderId().getId());
ps.setBytes(15, result.getTransactionHash());
ps.setInt(16, result.getTransactionIndex());
ps.setInt(17, result.getTransactionNonce());
ps.setInt(18, result.getTransactionResult());
});
}
}

0 comments on commit 2360f6b

Please sign in to comment.