From 980bde841c9cb8333716dbd7174c2a97db476ff1 Mon Sep 17 00:00:00 2001 From: fmacleal Date: Mon, 8 Jul 2024 17:00:18 +0200 Subject: [PATCH] Adding the effectiveGasPrice to the eth_getTransactionReceipt In order to let the transactionReceipt compatible with the Ethereum one, we are adding the field effectiveGasPrice, that it's basically the same value of the gasPrice on the transaction. --- doc/rpc/components/schemas/Receipt.json | 8 ++++- .../methods/eth_getTransactionReceipt.json | 3 +- .../rpc/dto/TransactionReceiptDTO.java | 7 +++++ .../java/org/ethereum/rpc/Web3ImplTest.java | 4 +++ .../rpc/dto/TransactionReceiptDTOTest.java | 29 ++++++++++++++++++- 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/doc/rpc/components/schemas/Receipt.json b/doc/rpc/components/schemas/Receipt.json index 24bec42347a..c788d04d81e 100644 --- a/doc/rpc/components/schemas/Receipt.json +++ b/doc/rpc/components/schemas/Receipt.json @@ -15,7 +15,8 @@ "to", "transactionHash", "transactionIndex", - "type" + "type", + "effectiveGasPrice" ], "properties": { "blockHash": { @@ -79,6 +80,11 @@ "description": "is a positive unsigned 8-bit number that represents the type of the transaction.", "type": "string" }, + "effectiveGasPrice": { + "title": "ReceiptEffectiveGasPrice", + "description": "The actual value per gas deducted on the transaction.", + "$ref": "#/components/schemas/IntegerHex" + }, "root": { "title": "Receipt Root", "description": "32 bytes of post-transaction `stateroot` (pre Byzantium).", diff --git a/doc/rpc/methods/eth_getTransactionReceipt.json b/doc/rpc/methods/eth_getTransactionReceipt.json index e27c9c31e1c..b143f8f276f 100644 --- a/doc/rpc/methods/eth_getTransactionReceipt.json +++ b/doc/rpc/methods/eth_getTransactionReceipt.json @@ -58,7 +58,8 @@ ], "logsBloom": "0x00...0", "status": "0x1", - "type": "0x0" + "type": "0x0", + "effectiveGasPrice": "0x1" } ] } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/dto/TransactionReceiptDTO.java b/rskj-core/src/main/java/org/ethereum/rpc/dto/TransactionReceiptDTO.java index 3cd7f0efa69..28d86e2d6aa 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/dto/TransactionReceiptDTO.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/dto/TransactionReceiptDTO.java @@ -46,6 +46,8 @@ public class TransactionReceiptDTO { private String status; // either 1 (success) or 0 (failure) private String logsBloom; // Bloom filter for light clients to quickly retrieve related logs. private String type = TRANSACTION_TYPE; // is a positive unsigned 8-bit number that represents the type of the transaction. + private String effectiveGasPrice; // The actual value per gas deducted on the transaction. + public TransactionReceiptDTO(Block block, TransactionInfo txInfo, SignatureCache signatureCache) { TransactionReceipt receipt = txInfo.getReceipt(); @@ -74,6 +76,7 @@ public TransactionReceiptDTO(Block block, TransactionInfo txInfo, SignatureCache transactionHash = receipt.getTransaction().getHash().toJsonString(); transactionIndex = HexUtils.toQuantityJsonHex(txInfo.getIndex()); logsBloom = HexUtils.toUnformattedJsonHex(txInfo.getReceipt().getBloomFilter().getData()); + effectiveGasPrice = HexUtils.toQuantityJsonHex(txInfo.getReceipt().getTransaction().getGasPrice().getBytes()); } public String getTransactionHash() { @@ -127,4 +130,8 @@ public String getLogsBloom() { public String getType() { return type; } + + public String getEffectiveGasPrice() { + return effectiveGasPrice; + } } \ No newline at end of file diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java index f538ce0f2fb..f23da51c182 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -99,6 +99,7 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; +import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import java.util.function.Function; @@ -820,6 +821,9 @@ void getTransactionReceipt() { String blockNumberAsHex = "0x" + Long.toHexString(block1.getNumber()); assertEquals(blockNumberAsHex, tr.getBlockNumber()); + String effectiveGasPrice = "0x" + tx.getGasPrice().asBigInteger(); + assertEquals(effectiveGasPrice, tr.getEffectiveGasPrice()); + String rawTransactionReceipt = web3.rsk_getRawTransactionReceiptByHash(hashString); String expectedRawTxReceipt = "0xf9010c01825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c082520801"; assertEquals(expectedRawTxReceipt, rawTransactionReceipt); diff --git a/rskj-core/src/test/java/org/ethereum/rpc/dto/TransactionReceiptDTOTest.java b/rskj-core/src/test/java/org/ethereum/rpc/dto/TransactionReceiptDTOTest.java index 6fed79858be..8af3b758845 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/dto/TransactionReceiptDTOTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/dto/TransactionReceiptDTOTest.java @@ -17,6 +17,7 @@ */ package org.ethereum.rpc.dto; +import co.rsk.core.Coin; import co.rsk.core.RskAddress; import co.rsk.crypto.Keccak256; import org.ethereum.core.*; @@ -36,10 +37,11 @@ class TransactionReceiptDTOTest { @Test void testOkStatusField() { + //given RskAddress rskAddress = RskAddress.nullAddress(); Keccak256 hash = Keccak256.ZERO_HASH; Bloom bloom = new Bloom(); - + Coin gasPrice = Coin.valueOf(100); Block block = mock(Block.class); when(block.getHash()).thenReturn(hash); @@ -47,6 +49,7 @@ void testOkStatusField() { when(transaction.getHash()).thenReturn(hash); when(transaction.getSender(any(SignatureCache.class))).thenReturn(rskAddress); when(transaction.getReceiveAddress()).thenReturn(rskAddress); + when(transaction.getGasPrice()).thenReturn(gasPrice); TransactionReceipt txReceipt = mock(TransactionReceipt.class); when(txReceipt.getTransaction()).thenReturn(transaction); @@ -58,17 +61,21 @@ void testOkStatusField() { TransactionReceiptDTO transactionReceiptDTO = new TransactionReceiptDTO(block, txInfo, new BlockTxSignatureCache(new ReceivedTxSignatureCache())); + //when String actualStatus = transactionReceiptDTO.getStatus(); + //then assertNotNull(actualStatus); assertEquals("0x1", actualStatus); } @Test void testErrorStatusField() { + //given RskAddress rskAddress = RskAddress.nullAddress(); Keccak256 hash = Keccak256.ZERO_HASH; Bloom bloom = new Bloom(); + Coin gasPrice = Coin.valueOf(100); Block block = mock(Block.class); when(block.getHash()).thenReturn(hash); @@ -77,6 +84,7 @@ void testErrorStatusField() { when(transaction.getHash()).thenReturn(hash); when(transaction.getSender(any(SignatureCache.class))).thenReturn(rskAddress); when(transaction.getReceiveAddress()).thenReturn(rskAddress); + when(transaction.getGasPrice()).thenReturn(gasPrice); TransactionReceipt txReceipt = mock(TransactionReceipt.class); when(txReceipt.getTransaction()).thenReturn(transaction); @@ -88,17 +96,21 @@ void testErrorStatusField() { TransactionReceiptDTO transactionReceiptDTO = new TransactionReceiptDTO(block, txInfo, new BlockTxSignatureCache(new ReceivedTxSignatureCache())); + //when String actualStatus = transactionReceiptDTO.getStatus(); + //then assertNotNull(actualStatus); assertEquals("0x0", actualStatus); } @Test void testErrorStatusFieldUsingEmptyByteArray() { + //given RskAddress rskAddress = RskAddress.nullAddress(); Keccak256 hash = Keccak256.ZERO_HASH; Bloom bloom = new Bloom(); + Coin gasPrice = Coin.valueOf(100); Block block = mock(Block.class); when(block.getHash()).thenReturn(hash); @@ -107,6 +119,7 @@ void testErrorStatusFieldUsingEmptyByteArray() { when(transaction.getHash()).thenReturn(hash); when(transaction.getSender(any(SignatureCache.class))).thenReturn(rskAddress); when(transaction.getReceiveAddress()).thenReturn(rskAddress); + when(transaction.getGasPrice()).thenReturn(gasPrice); TransactionReceipt txReceipt = mock(TransactionReceipt.class); when(txReceipt.getTransaction()).thenReturn(transaction); @@ -118,17 +131,21 @@ void testErrorStatusFieldUsingEmptyByteArray() { TransactionReceiptDTO transactionReceiptDTO = new TransactionReceiptDTO(block, txInfo, new BlockTxSignatureCache(new ReceivedTxSignatureCache())); + //when String actualStatus = transactionReceiptDTO.getStatus(); + //then assertNotNull(actualStatus); assertEquals("0x0", actualStatus); } @Test void testErrorStatusFieldUsingNullByteArray() { + //given RskAddress rskAddress = RskAddress.nullAddress(); Keccak256 hash = Keccak256.ZERO_HASH; Bloom bloom = new Bloom(); + Coin gasPrice = Coin.valueOf(100); Block block = mock(Block.class); when(block.getHash()).thenReturn(hash); @@ -137,26 +154,33 @@ void testErrorStatusFieldUsingNullByteArray() { when(transaction.getHash()).thenReturn(hash); when(transaction.getSender(any(SignatureCache.class))).thenReturn(rskAddress); when(transaction.getReceiveAddress()).thenReturn(rskAddress); + when(transaction.getGasPrice()).thenReturn(gasPrice); TransactionReceipt txReceipt = mock(TransactionReceipt.class); when(txReceipt.getTransaction()).thenReturn(transaction); when(txReceipt.getLogInfoList()).thenReturn(Collections.emptyList()); when(txReceipt.getBloomFilter()).thenReturn(bloom); when(txReceipt.getStatus()).thenReturn(null); + when(txReceipt.getStatus()).thenReturn(null); + TransactionInfo txInfo = new TransactionInfo(txReceipt, hash.getBytes(), 0); TransactionReceiptDTO transactionReceiptDTO = new TransactionReceiptDTO(block, txInfo, new BlockTxSignatureCache(new ReceivedTxSignatureCache())); + //when String actualStatus = transactionReceiptDTO.getStatus(); + //then assertNotNull(actualStatus); assertEquals("0x0", actualStatus); } @Test void testTypeField() { + //given RskAddress rskAddress = RskAddress.nullAddress(); Keccak256 hash = Keccak256.ZERO_HASH; + Coin gasPrice = Coin.valueOf(100); Bloom bloom = new Bloom(); Block block = mock(Block.class); @@ -166,6 +190,7 @@ void testTypeField() { when(transaction.getHash()).thenReturn(hash); when(transaction.getSender(any(SignatureCache.class))).thenReturn(rskAddress); when(transaction.getReceiveAddress()).thenReturn(rskAddress); + when(transaction.getGasPrice()).thenReturn(gasPrice); TransactionReceipt txReceipt = mock(TransactionReceipt.class); when(txReceipt.getTransaction()).thenReturn(transaction); @@ -177,8 +202,10 @@ void testTypeField() { TransactionReceiptDTO transactionReceiptDTO = new TransactionReceiptDTO(block, txInfo, new BlockTxSignatureCache(new ReceivedTxSignatureCache())); + //when String actualType = transactionReceiptDTO.getType(); + //then assertNotNull(actualType); assertEquals("0x0", actualType); }