Skip to content

Commit

Permalink
Merge pull request #2243 from rsksmart/fix_eth_getStorageAt_for_block…
Browse files Browse the repository at this point in the history
…_hash

Fix the web 3 retriever with block hash as identifier
  • Loading branch information
Vovchyk authored Mar 5, 2024
2 parents ada6771 + da2864d commit 6dfdb03
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 11 deletions.
36 changes: 28 additions & 8 deletions rskj-core/src/main/java/co/rsk/rpc/Web3InformationRetriever.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import co.rsk.core.bc.AccountInformationProvider;
import co.rsk.db.RepositoryLocator;
import co.rsk.util.HexUtils;
import org.bouncycastle.util.encoders.DecoderException;
import org.ethereum.core.Block;
import org.ethereum.core.Blockchain;
import org.ethereum.core.Transaction;
Expand All @@ -30,6 +31,7 @@
import java.util.List;
import java.util.Optional;

import static co.rsk.crypto.Keccak256.HASH_LEN;
import static org.ethereum.rpc.exception.RskJsonRpcRequestException.blockNotFound;
import static org.ethereum.rpc.exception.RskJsonRpcRequestException.invalidParamError;

Expand Down Expand Up @@ -70,14 +72,22 @@ public Web3InformationRetriever(TransactionPool transactionPool,
*/
public Optional<Block> getBlock(String identifier) {
Block block;
if (PENDING.equals(identifier)) {
block = executionBlockRetriever.retrieveExecutionBlock(identifier).getBlock();
} else if (LATEST.equals(identifier)) {
block = blockchain.getBestBlock();
} else if (EARLIEST.equals(identifier)) {
block = blockchain.getBlockByNumber(0);
} else {
block = this.blockchain.getBlockByNumber(getBlockNumber(identifier));

switch (identifier) {
case PENDING:
block = executionBlockRetriever.retrieveExecutionBlock(identifier).getBlock();
break;
case LATEST:
block = blockchain.getBestBlock();
break;
case EARLIEST:
block = blockchain.getBlockByNumber(0);
break;
default:
byte[] hash = getBlockHash(identifier);
block = hash.length == HASH_LEN ?
blockchain.getBlockByHash(hash)
: blockchain.getBlockByNumber(getBlockNumber(identifier));
}

return Optional.ofNullable(block);
Expand Down Expand Up @@ -134,4 +144,14 @@ private long getBlockNumber(String identifier) {
}
return blockNumber;
}

private byte[] getBlockHash(String identifier) {
byte[] blockHash;
try {
blockHash = HexUtils.stringHexToByteArray(identifier);
} catch (DecoderException e) {
throw invalidParamError(String.format("invalid blockhash %s", identifier));
}
return blockHash;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import co.rsk.crypto.Keccak256;
import co.rsk.db.RepositoryLocator;
import co.rsk.db.RepositorySnapshot;
import co.rsk.util.HexUtils;
import org.ethereum.TestUtils;
import org.ethereum.core.*;
import org.ethereum.rpc.exception.RskJsonRpcRequestException;
Expand Down Expand Up @@ -90,6 +91,18 @@ void getBlock_number() {
assertEquals(secondBlock, result.get());
}

@Test
void getBlock_hash() {
String hash = "0x0000000000000000000000000000000000000000000000000000000000000002";
byte[] bytesHash = HexUtils.stringHexToByteArray(hash);
Block secondBlock = mock(Block.class);
when(blockchain.getBlockByHash(bytesHash)).thenReturn(secondBlock);
Optional<Block> result = target.getBlock(hash);

assertTrue(result.isPresent());
assertEquals(secondBlock, result.get());
}

@Test
void getBlock_notFound() {
Optional<Block> result = target.getBlock("0x2");
Expand Down
34 changes: 31 additions & 3 deletions rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,34 @@ void getStorageAtAccountAndBlockHash() {
new BlockRefParam(blockRef)));
}

@Test
//[ "0x<address>", "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" -> return storage at given address in genesis block
void getStorageAtAccountAndBlockHashWithSingleIdentifier() {
//given
final ChainParams chain = chainWithAccount10kBalance(false);
// when
String result = chain.web3.eth_getStorageAt(
new HexAddressParam(chain.accountAddress),
new HexNumberParam("0x0"),
new BlockRefParam( "0x" + chain.block.getPrintableHash()));
// then
assertEquals(NON_EXISTING_KEY_RESPONSE, result );
}

@Test
//[ "0x<address>", "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" -> return storage at given address in genesis block
void getStorageAtAccountAndBlockHashWithSingleIdentifier_whenItsAInvalidHash() {
//given
String invalidBlockIdentifier = "0x00011231234123";
final ChainParams chain = chainWithAccount10kBalance(false);
//when-then
Exception ex = assertThrows(RskJsonRpcRequestException.class, () -> chain.web3.eth_getStorageAt(
new HexAddressParam(chain.accountAddress),
new HexNumberParam("0x0"),
new BlockRefParam( invalidBlockIdentifier)));
assertEquals("Block " + invalidBlockIdentifier + " not found", ex.getMessage());
}

@Test
//[ "0x<address>", { "blockHash": "0x<non-existent-block-hash>" } -> raise block-not-found error
void getStorageAtAccountAndNonExistentBlockHash() {
Expand Down Expand Up @@ -810,7 +838,7 @@ void getTransactionReceiptNotInMainBlockchain() {
txs.add(tx);
Block genesis = world.getBlockChain().getBestBlock();
Block block1 = new BlockBuilder(world.getBlockChain(), world.getBridgeSupportFactory(),
world.getBlockStore()).trieStore(world.getTrieStore()).parent(genesis).difficulty(3l).transactions(txs).build();
world.getBlockStore()).trieStore(world.getTrieStore()).parent(genesis).difficulty(3L).transactions(txs).build();
assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block1));
Block block1b = new BlockBuilder(world.getBlockChain(), world.getBridgeSupportFactory(),
world.getBlockStore()).trieStore(world.getTrieStore()).parent(genesis)
Expand Down Expand Up @@ -1018,7 +1046,7 @@ void getTransactionCount() {
Transaction tx = new TransactionBuilder().sender(acc1).receiver(acc2).value(BigInteger.valueOf(1000000)).build();
List<Transaction> txs = new ArrayList<>();
txs.add(tx);
Block block1 = createCanonicalBlock(world, txs);
createCanonicalBlock(world, txs);

String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes());

Expand Down Expand Up @@ -3108,7 +3136,7 @@ void transactionReceiptAndResultHasTypeField() {
Transaction tx = new TransactionBuilder().sender(acc1).receiver(acc2).value(BigInteger.valueOf(1000000)).build();
List<Transaction> txs = new ArrayList<>();
txs.add(tx);
Block block1 = createCanonicalBlock(world, txs);
createCanonicalBlock(world, txs);

String hashString = tx.getHash().toHexString();
TxHashParam txHashParam = new TxHashParam(hashString);
Expand Down

0 comments on commit 6dfdb03

Please sign in to comment.