From af96058811cea05c490c48b8ba667c00525a7983 Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Wed, 9 Aug 2023 18:18:45 +0200 Subject: [PATCH 01/47] Updating BlockHash related methods having validated parameters. Added blockHash, Tx Hash and Hex Index parameters and deserializers --- .../main/java/co/rsk/rpc/Web3EthModule.java | 8 +- .../src/main/java/co/rsk/util/HexUtils.java | 6 +- .../main/java/org/ethereum/rpc/Web3Impl.java | 70 ++++--- .../rpc/parameters/BlockHashParam.java | 42 +++++ .../ethereum/rpc/parameters/HashParam32.java | 53 ++++++ .../rpc/parameters/HexIndexParam.java | 55 ++++++ .../ethereum/rpc/parameters/TxHashParam.java | 44 +++++ .../rpc/netty/JsonRPCParamValidationTest.java | 160 ++++++++++++++++ .../java/org/ethereum/rpc/Web3ImplTest.java | 174 ++++++++++-------- .../rpc/parameters/HashParamTest.java | 46 +++++ .../rpc/parameters/HexIndexParamTest.java | 46 +++++ 11 files changed, 589 insertions(+), 115 deletions(-) create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockHashParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java create mode 100644 rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/HashParamTest.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index 9fd71f12c57..ba023596174 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -25,6 +25,8 @@ import org.ethereum.rpc.dto.CompilationResultDTO; import org.ethereum.rpc.dto.TransactionReceiptDTO; import org.ethereum.rpc.dto.TransactionResultDTO; +import org.ethereum.rpc.parameters.BlockHashParam; +import org.ethereum.rpc.parameters.HexIndexParam; import java.math.BigInteger; import java.util.Map; @@ -108,19 +110,19 @@ default String eth_sendTransaction(CallArguments args) { return getEthModule().sendTransaction(args); } - BlockResultDTO eth_getBlockByHash(String blockHash, Boolean fullTransactionObjects) throws Exception; + BlockResultDTO eth_getBlockByHash(BlockHashParam blockHash, Boolean fullTransactionObjects) throws Exception; BlockResultDTO eth_getBlockByNumber(String bnOrId, Boolean fullTransactionObjects) throws Exception; TransactionResultDTO eth_getTransactionByHash(String transactionHash) throws Exception; - TransactionResultDTO eth_getTransactionByBlockHashAndIndex(String blockHash, String index) throws Exception; + TransactionResultDTO eth_getTransactionByBlockHashAndIndex(BlockHashParam blockHash, HexIndexParam index) throws Exception; TransactionResultDTO eth_getTransactionByBlockNumberAndIndex(String bnOrId, String index) throws Exception; TransactionReceiptDTO eth_getTransactionReceipt(String transactionHash) throws Exception; - BlockResultDTO eth_getUncleByBlockHashAndIndex(String blockHash, String uncleIdx) throws Exception; + BlockResultDTO eth_getUncleByBlockHashAndIndex(BlockHashParam blockHash, HexIndexParam uncleIdx) throws Exception; BlockResultDTO eth_getUncleByBlockNumberAndIndex(String blockId, String uncleIdx) throws Exception; diff --git a/rskj-core/src/main/java/co/rsk/util/HexUtils.java b/rskj-core/src/main/java/co/rsk/util/HexUtils.java index 3007001e23d..f2081af8347 100644 --- a/rskj-core/src/main/java/co/rsk/util/HexUtils.java +++ b/rskj-core/src/main/java/co/rsk/util/HexUtils.java @@ -22,12 +22,12 @@ import org.bouncycastle.util.encoders.Hex; import org.ethereum.util.ByteUtil; -import static org.ethereum.rpc.exception.RskJsonRpcRequestException.invalidParamError; - import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.util.regex.Pattern; +import static org.ethereum.rpc.exception.RskJsonRpcRequestException.invalidParamError; + /** * Hex utils */ @@ -353,7 +353,7 @@ public static byte[] decode(byte[] dataBytes) { * decodes a hexadecimal encoded with the 0x prefix into a integer */ public static int jsonHexToInt(final String param) { - if (!hasHexPrefix(param)) { + if (!hasHexPrefix(param) && !HexUtils.isHex(param)) { throw invalidParamError(INCORRECT_HEX_SYNTAX); } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index 7692daff857..99846927f8f 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -59,6 +59,8 @@ import org.ethereum.rpc.dto.CompilationResultDTO; import org.ethereum.rpc.dto.TransactionReceiptDTO; import org.ethereum.rpc.dto.TransactionResultDTO; +import org.ethereum.rpc.parameters.BlockHashParam; +import org.ethereum.rpc.parameters.HexIndexParam; import org.ethereum.util.BuildInfo; import org.ethereum.vm.DataWord; import org.slf4j.Logger; @@ -235,8 +237,7 @@ public String net_version() { try { byte netVersion = config.getNetworkConstants().getChainId(); return s = Byte.toString(netVersion); - } - finally { + } finally { if (logger.isDebugEnabled()) { logger.debug("net_version(): {}", s); } @@ -411,10 +412,10 @@ public String eth_getCode(String address, Map inputs) { @Override public String eth_getBalance(String address, String block) { /* HEX String - an integer block number - * String "earliest" for the earliest/genesis block - * String "latest" - for the latest mined block - * String "pending" - for the pending state/transactions - */ + * String "earliest" for the earliest/genesis block + * String "latest" - for the latest mined block + * String "pending" - for the pending state/transactions + */ AccountInformationProvider accountInformationProvider = web3InformationRetriever.getInformationProvider(block); @@ -445,7 +446,7 @@ public String eth_getBalance(String address) { @Override public String eth_getStorageAt(String address, String storageIdx, Map blockRef) { - return invokeByBlockRef(blockRef, blockNumber -> this.eth_getStorageAt(address,storageIdx, blockNumber)); + return invokeByBlockRef(blockRef, blockNumber -> this.eth_getStorageAt(address, storageIdx, blockNumber)); } @Override @@ -485,7 +486,8 @@ public String eth_getTransactionCount(String address, Map inputs * It processes inputs maps ex: { "blockNumber": "0x0" }, * { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } * and invoke a function after processing. - * @param inputs map + * + * @param inputs map * @param toInvokeByBlockNumber a function that returns a string based on the block number * @return function invocation result */ @@ -493,8 +495,8 @@ protected String invokeByBlockRef(Map inputs, UnaryOperator this.toInvokeByBlockHash(blockHash, requireCanonical, toInvokeByBlockNumber)) .orElseGet(() -> applyIfPresent(inputs, "blockNumber", toInvokeByBlockNumber) - .orElseThrow(() -> invalidParamError("Invalid block input")) - ); + .orElseThrow(() -> invalidParamError("Invalid block input")) + ); } private String toInvokeByBlockHash(String blockHash, boolean requireCanonical, Function toInvokeByBlockNumber) { @@ -644,10 +646,14 @@ public BlockInformationResult[] eth_getBlocksByNumber(String number) { } @Override - public BlockResultDTO eth_getBlockByHash(String blockHash, Boolean fullTransactionObjects) { + public BlockResultDTO eth_getBlockByHash(BlockHashParam blockHash, Boolean fullTransactionObjects) { + if (blockHash == null) { + throw invalidParamError("blockHash is null"); + } + BlockResultDTO s = null; try { - Block b = getBlockByJSonHash(blockHash); + Block b = this.blockchain.getBlockByHash(blockHash.getHash().getBytes()); s = (b == null ? null : getBlockResult(b, fullTransactionObjects)); return s; } finally { @@ -684,7 +690,7 @@ public TransactionResultDTO eth_getTransactionByHash(String transactionHash) { TransactionInfo txInfo = this.receiptStore.getInMainChain(txHash.getBytes(), blockStore).orElse(null); if (txInfo == null) { - List txs = web3InformationRetriever.getTransactions("pending"); + List txs = web3InformationRetriever.getTransactions("pending"); for (Transaction tx : txs) { if (tx.getHash().equals(txHash)) { @@ -713,16 +719,24 @@ public TransactionResultDTO eth_getTransactionByHash(String transactionHash) { } @Override - public TransactionResultDTO eth_getTransactionByBlockHashAndIndex(String blockHash, String index) { + public TransactionResultDTO eth_getTransactionByBlockHashAndIndex(BlockHashParam blockHash, HexIndexParam index) { + if (blockHash == null) { + throw invalidParamError("blockHash is null"); + } + + if (index == null) { + throw invalidParamError("index is null"); + } + TransactionResultDTO s = null; try { - Block b = getBlockByJSonHash(blockHash); + Block b = blockchain.getBlockByHash(blockHash.getHash().getBytes()); if (b == null) { return null; } - int idx = jsonHexToInt(index); + int idx = index.getIndex(); if (idx >= b.getTransactionsList().size()) { return null; @@ -782,17 +796,17 @@ public TransactionReceiptDTO eth_getTransactionReceipt(String transactionHash) { } @Override - public BlockResultDTO eth_getUncleByBlockHashAndIndex(String blockHash, String uncleIdx) { + public BlockResultDTO eth_getUncleByBlockHashAndIndex(BlockHashParam blockHash, HexIndexParam uncleIdx) { BlockResultDTO s = null; try { - Block block = blockchain.getBlockByHash(stringHexToByteArray(blockHash)); + Block block = blockchain.getBlockByHash(blockHash.getHash().getBytes()); if (block == null) { return null; } - s = getUncleResultDTO(uncleIdx, block); + s = getUncleResultDTO(uncleIdx.getIndex(), block); return s; } finally { @@ -802,14 +816,13 @@ public BlockResultDTO eth_getUncleByBlockHashAndIndex(String blockHash, String u } } - private BlockResultDTO getUncleResultDTO(String uncleIdx, Block block) { - int idx = jsonHexToInt(uncleIdx); + private BlockResultDTO getUncleResultDTO(Integer uncleIdx, Block block) { - if (idx >= block.getUncleList().size()) { + if (uncleIdx >= block.getUncleList().size()) { return null; } - BlockHeader uncleHeader = block.getUncleList().get(idx); + BlockHeader uncleHeader = block.getUncleList().get(uncleIdx); Block uncle = blockchain.getBlockByHash(uncleHeader.getHash().getBytes()); if (uncle == null) { @@ -829,8 +842,8 @@ public BlockResultDTO eth_getUncleByBlockNumberAndIndex(String blockId, String u if (!block.isPresent()) { return null; } - - s = getUncleResultDTO(uncleIdx, block.get()); + int idx = jsonHexToInt(uncleIdx); + s = getUncleResultDTO(idx, block.get()); return s; } finally { @@ -871,7 +884,7 @@ public Map eth_compileSolidity(String contract) { public String eth_newFilter(FilterRequest fr) throws Exception { String str = null; try { - Filter filter = LogFilter.fromFilterRequest(fr, blockchain, blocksBloomStore, config.getRpcEthGetLogsMaxBlockToQuery(),config.getRpcEthGetLogsMaxLogsToReturn()); + Filter filter = LogFilter.fromFilterRequest(fr, blockchain, blocksBloomStore, config.getRpcEthGetLogsMaxBlockToQuery(), config.getRpcEthGetLogsMaxLogsToReturn()); int id = filterManager.registerFilter(filter); str = toQuantityJsonHex(id); @@ -1103,7 +1116,7 @@ public RskModule getRskModule() { /** * Adds an address or block to the list of banned addresses * It supports IPV4 and IPV6 addresses with an optional number of bits to ignore - * + *

* "192.168.51.1" is a valid address * "192.168.51.1/16" is a valid block * @@ -1125,7 +1138,7 @@ public void sco_banAddress(String address) { /** * Removes an address or block to the list of banned addresses * It supports IPV4 and IPV6 addresses with an optional number of bits to ignore - * + *

* "192.168.51.1" is a valid address * "192.168.51.1/16" is a valid block * @@ -1182,7 +1195,6 @@ public PeerScoringReputationSummary sco_reputationSummary() { * Clears scoring for the received id * * @param id peer identifier: firstly tried as an InetAddress, used as a NodeId otherwise - * * @return the list of scoring information, per node id and address */ @SuppressWarnings("squid:S1166") diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockHashParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockHashParam.java new file mode 100644 index 00000000000..f48a3ab8c1a --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockHashParam.java @@ -0,0 +1,42 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.ethereum.rpc.parameters; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.io.IOException; + +@JsonDeserialize(using = BlockHashParam.Deserializer.class) +public class BlockHashParam extends HashParam32 { + private static final String HASH_TYPE = "block hash"; + + public BlockHashParam(String hash) { + super(HASH_TYPE, hash); + } + + public static class Deserializer extends JsonDeserializer { + @Override + public BlockHashParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String hash = jp.getText(); + return new BlockHashParam(hash); + } + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java new file mode 100644 index 00000000000..aeeee8475cc --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java @@ -0,0 +1,53 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.ethereum.rpc.parameters; + +import co.rsk.crypto.Keccak256; +import co.rsk.util.HexUtils; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; + +import static co.rsk.util.HexUtils.stringHexToByteArray; + +public abstract class HashParam32 { + private static final int HASH_BYTE_LENGTH = 32; + private final Keccak256 hash; + + HashParam32(String hashType, String hash) { + if (hash == null || hash.isEmpty()) { + throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + ": empty or null."); + } + + byte[] hashBytes; + + try { + hashBytes = HexUtils.stringHexToByteArray(hash); + } catch (Exception e) { + throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + " format. " + e.getMessage()); + } + + if (HASH_BYTE_LENGTH != hashBytes.length) { + throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + ": incorrect length."); + } + + this.hash = new Keccak256(stringHexToByteArray(hash)); + } + + public Keccak256 getHash() { + return hash; + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java new file mode 100644 index 00000000000..fccaaed5bac --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -0,0 +1,55 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package org.ethereum.rpc.parameters; + +import co.rsk.util.HexUtils; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; + +import java.io.IOException; + +@JsonDeserialize(using = HexIndexParam.Deserializer.class) +public class HexIndexParam { + private final Integer index; + + public HexIndexParam(String indexString) { + if (!HexUtils.hasHexPrefix(indexString) || !HexUtils.isHex(indexString,2)) { + throw RskJsonRpcRequestException.invalidParamError("Invalid argument: " + indexString + ": param should be a hex value string."); + } + String preResult = HexUtils.removeHexPrefix(indexString); + this.index = Integer.parseInt(preResult, 16); + } + + public Integer getIndex() { + return index; + } + + public static class Deserializer extends JsonDeserializer { + + @Override + public HexIndexParam deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException { + String indexString = jp.getText(); + return new HexIndexParam(indexString); + } + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java new file mode 100644 index 00000000000..b74b6df70e4 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java @@ -0,0 +1,44 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package org.ethereum.rpc.parameters; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.io.IOException; + +@JsonDeserialize(using = TxHashParam.Deserializer.class) +public class TxHashParam extends HashParam32 { + private static final String HASH_TYPE = "transaction hash"; + public TxHashParam(String hash) { + super(HASH_TYPE, hash); + } + + public static class Deserializer extends JsonDeserializer { + + @Override + public TxHashParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String hash = jp.getText(); + return new TxHashParam(hash); + + } + } +} + diff --git a/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java b/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java new file mode 100644 index 00000000000..ca3b09a473c --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java @@ -0,0 +1,160 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package co.rsk.rpc.netty; + +import co.rsk.rpc.Web3EthModule; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.googlecode.jsonrpc4j.AnnotationsErrorResolver; +import com.googlecode.jsonrpc4j.DefaultErrorResolver; +import com.googlecode.jsonrpc4j.JsonResponse; +import com.googlecode.jsonrpc4j.MultipleErrorResolver; +import org.ethereum.rpc.dto.BlockResultDTO; +import org.ethereum.rpc.dto.TransactionResultDTO; +import org.ethereum.rpc.exception.RskErrorResolver; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class JsonRPCParamValidationTest { + private final ObjectMapper objectMapper = new ObjectMapper(); + private JsonRpcCustomServer jsonRpcServer; + private Web3EthModule handler; + + @BeforeEach + void setUp() { + handler = mock(Web3EthModule.class); + this.jsonRpcServer = new JsonRpcCustomServer(handler, handler.getClass(), Collections.emptyList()); + jsonRpcServer.setErrorResolver(new MultipleErrorResolver(new RskErrorResolver(), AnnotationsErrorResolver.INSTANCE, DefaultErrorResolver.INSTANCE)); + } + + @Test + void eth_getBlockByHash() throws Exception { + BlockResultDTO blockResultDTO = mock(BlockResultDTO.class); + + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getBlockByHash\",\n" + + "\t\"params\":[\n" + + "\t\t\"0xec576a07c263125c864bce15dee5046774f474ea123c581c08008bea2\"\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + + when(handler.eth_getBlockByHash(any(), any())).thenReturn(blockResultDTO); + + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertNotNull(response); + } + + @Test + void eth_getBlockByHash_invalidHexCharInHash_returnsError() throws Exception { + BlockResultDTO blockResultDTO = mock(BlockResultDTO.class); + + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getBlockByHash\",\n" + + "\t\"params\":[\n" + + "\t\t\"0xc2b835zzz172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8\", \n" + + "\t\ttrue\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + + when(handler.eth_getBlockByHash(any(), any())).thenReturn(blockResultDTO); + + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertEquals(-32602, response.getCode()); + String message = response.getResponse().get("error").get("message").asText(); + assertEquals("Invalid block hash format. exception decoding Hex string: invalid characters encountered in Hex string",message); + } + + @Test + void eth_getBlockByHash_invalidHashLength_returnsError() throws Exception { + BlockResultDTO blockResultDTO = mock(BlockResultDTO.class); + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getBlockByHash\",\n" + + "\t\"params\":[\n" + + "\t\t\"0xec576f474ea123c581c08008bea2\", \n" + + "\t\ttrue\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + + when(handler.eth_getBlockByHash(any(), any())).thenReturn(blockResultDTO); + + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertEquals(-32602, response.getCode()); + String message = response.getResponse().get("error").get("message").asText(); + assertEquals("Invalid block hash: incorrect length.",message); + + } + + @Test + void eth_getTransactionByBlockHashAndIndex_invalidHash_returnsError() throws Exception{ + TransactionResultDTO resultDTO = mock(TransactionResultDTO.class); + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getTransactionByBlockHashAndIndex\",\n" + + "\t\"params\":[\n" + + "\t\t\"0x3c82bc62179602b6731037c49cba84e31ffe6e465a21c521a7\", \n" + + "\t\t\"0x0\"\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + when(handler.eth_getTransactionByBlockHashAndIndex(any(), any())).thenReturn(resultDTO); + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertEquals(-32602, response.getCode()); + String message = response.getResponse().get("error").get("message").asText(); + assertEquals("Invalid block hash: incorrect length.",message); + } + + + @Test + void eth_getTransactionByBlockHashAndIndex_invalidIndex_returnsError() throws Exception{ + TransactionResultDTO resultDTO = mock(TransactionResultDTO.class); + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getTransactionByBlockHashAndIndex\",\n" + + "\t\"params\":[\n" + + "\t\t\"0x3c82bc62179602b67318c013c10f99011037c49cba84e31ffe6e465a21c521a7\", \n" + + "\t\t\"abc\"\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + when(handler.eth_getTransactionByBlockHashAndIndex(any(), any())).thenReturn(resultDTO); + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertEquals(-32602, response.getCode()); + String message = response.getResponse().get("error").get("message").asText(); + assertEquals("Invalid argument: abc: param should be a hex value string.",message); + } + +} \ 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 0672034fcc1..5ddf45bf409 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -77,6 +77,8 @@ import org.ethereum.rpc.dto.TransactionReceiptDTO; import org.ethereum.rpc.dto.TransactionResultDTO; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.BlockHashParam; +import org.ethereum.rpc.parameters.HexIndexParam; import org.ethereum.util.BuildInfo; import org.ethereum.util.ByteUtil; import org.ethereum.vm.PrecompiledContracts; @@ -160,7 +162,7 @@ void net_peerCount() { @Test void web3_sha3() throws Exception { - String toHashInHex = "0x696e7465726e6574"; // 'internet' in hexa + String toHashInHex = "0x696e7465726e6574"; // 'internet' in hexa Web3 web3 = createWeb3(); @@ -174,7 +176,7 @@ void web3_sha3() throws Exception { @Test void web3_sha3_expect_exception() { - Web3 web3 = createWeb3(); + Web3 web3 = createWeb3(); Assertions.assertThrows(RskJsonRpcRequestException.class, () -> web3.web3_sha3("internet")); } @@ -253,35 +255,35 @@ void getBalanceWithAccountAndBlock() { } @Test - //[ "0x

", { "blockNumber": "0x0" } -> return balance at given address in genesis block + //[ "0x
", { "blockNumber": "0x0" } -> return balance at given address in genesis block void getBalanceWithAccountAndBlockNumber() { final ChainParams chain = chainWithAccount10kBalance(false); assertByBlockNumber(BALANCE_10K_HEX, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException + //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException void getBalanceWithAccountAndInvalidInputThrowsException() { final ChainParams chain = chainWithAccount10kBalance(false); assertInvalidInput(blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return balance at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return balance at given address in genesis block void getBalanceWithAccountAndBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); assertByBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonExistentBlockHash(blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); @@ -289,14 +291,14 @@ void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { @Test - //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error + // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); @@ -304,28 +306,28 @@ void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return balance at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return balance at given address in genesis block void getBalanceWithAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertCanonicalBlockHashWhenCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return balance at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return balance at given address in genesis block void getBalanceWithAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return balance at given address in specified block + // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return balance at given address in specified block void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); } @Test - // [ "0x
", { "blockHash": "0x" } -> return balance at given address in specified bloc + // [ "0x
", { "blockHash": "0x" } -> return balance at given address in specified bloc void getBalanceWithAccountAndNonCanonicalBlockHash() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); @@ -358,21 +360,21 @@ void getBalanceWithAccountAndBlockWithTransaction() { } @Test - //[ "0x
", { "blockNumber": "0x0" } -> return storage at given address in genesis block + //[ "0x
", { "blockNumber": "0x0" } -> return storage at given address in genesis block void getStorageAtAccountAndBlockNumber() { final ChainParams chain = chainWithAccount10kBalance(false); assertByBlockNumber("0x0", blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return storage at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return storage at given address in genesis block void getStorageAtAccountAndBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); assertByBlockHash("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); } @Test - //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getStorageAtAccountAndNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonExistentBlockHash(blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); @@ -380,49 +382,49 @@ void getStorageAtAccountAndNonExistentBlockHash() { @Test - //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void getStorageAtAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); } @Test - //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void getStorageAtAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error + // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getStorageAtAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return storage at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return storage at given address in genesis block void getStorageAtAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertCanonicalBlockHashWhenCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return storage at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return storage at given address in genesis block void getStorageAtAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertCanonicalBlockHashWhenNotCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return storage at given address in specified block + // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return storage at given address in specified block void getStorageAtAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHashWhenNotCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); } @Test - // [ "0x
", { "blockHash": "0x" } -> return storage at given address in specified bloc + // [ "0x
", { "blockHash": "0x" } -> return storage at given address in specified bloc void getStorageAtAccountAndNonCanonicalBlockHash() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHash("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); @@ -430,217 +432,217 @@ void getStorageAtAccountAndNonCanonicalBlockHash() { } @Test - //[ "0x
", { "blockNumber": "0x0" } -> return code at given address in genesis block + //[ "0x
", { "blockNumber": "0x0" } -> return code at given address in genesis block void getCodeAtAccountAndBlockNumber() { final ChainParams chain = createChainWithAContractCode(false); assertByBlockNumber("0x010203", blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return code at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return code at given address in genesis block void getCodeAtAccountAndBlockHash() { final ChainParams chain = createChainWithAContractCode(false); assertByBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHash() { final ChainParams chain = createChainWithAContractCode(false); assertNonExistentBlockHash(blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(false); assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(false); assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error + // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getCodeAtAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(true); assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return code at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return code at given address in genesis block void getCodeAtAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(false); assertCanonicalBlockHashWhenCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return code at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return code at given address in genesis block void getCodeAtAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(false); assertCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return code at given address in specified block + // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return code at given address in specified block void getCodeAtAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(true); assertNonCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - // [ "0x
", { "blockHash": "0x" } -> return code at given address in specified bloc + // [ "0x
", { "blockHash": "0x" } -> return code at given address in specified bloc void getCodeAtAccountAndNonCanonicalBlockHash() { final ChainParams chain = createChainWithAContractCode(true); assertNonCanonicalBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); } @Test - //[ {argsForCall}, { "blockNumber": "0x0" } -> return contract call respond at given args for call in genesis block + //[ {argsForCall}, { "blockNumber": "0x0" } -> return contract call respond at given args for call in genesis block void callByBlockNumber() { final ChainParams chain = createChainWithACall(false); assertByBlockNumber(CALL_RESPOND, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return contract call respond at given address in genesis block + //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return contract call respond at given address in genesis block void callByBlockHash() { final ChainParams chain = createChainWithACall(false); assertByBlockHash(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - //[ {argsForCall}, { "blockHash": "0x" } -> raise block-not-found error + //[ {argsForCall}, { "blockHash": "0x" } -> raise block-not-found error void callByNonExistentBlockHash() { final ChainParams chain = createChainWithACall(false); assertNonExistentBlockHash(blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - //[ {argsForCall}, { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error + //[ {argsForCall}, { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void callByNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithACall(false); assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - //[ {argsForCall}, { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error + //[ {argsForCall}, { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void callByNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithACall(false); assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - // [ {argsForCall} { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error + // [ {argsForCall} { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void callByNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithACall(true); assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return contract call respond at given address in genesis block + //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return contract call respond at given address in genesis block void callByCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithACall(false); assertCanonicalBlockHashWhenCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return contract call respond at given address in genesis block + //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return contract call respond at given address in genesis block void callByCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithACall(false); assertCanonicalBlockHashWhenNotCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - // [ {argsForCall}, { "blockHash": "0x", "requireCanonical": false } -> return contract call respond at given address in specified block + // [ {argsForCall}, { "blockHash": "0x", "requireCanonical": false } -> return contract call respond at given address in specified block void callByNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithACall(true); assertNonCanonicalBlockHashWhenNotCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - // [ {argsForCall}, { "blockHash": "0x" } -> return contract call respond at given address in specified bloc + // [ {argsForCall}, { "blockHash": "0x" } -> return contract call respond at given address in specified bloc void callByNonCanonicalBlockHash() { final ChainParams chain = createChainWithACall(true); assertNonCanonicalBlockHash(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); } @Test - //[ "0x
", { "blockNumber": "0x0" } -> return code at given address in genesis block + //[ "0x
", { "blockNumber": "0x0" } -> return code at given address in genesis block void invokeByBlockNumber() { final ChainParams chain = chainWithAccount10kBalance(false); assertByBlockNumber("0x1", blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException + //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException void invokeByInvalidInputThrowsException() { final ChainParams chain = chainWithAccount10kBalance(false); assertInvalidInput(blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return data at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return data at given address in genesis block void invokeByBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); assertByBlockHash("0x1", chain.block, blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void invokeByNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonExistentBlockHash(blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void invokeByNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonBlockHashWhenCanonical(blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void invokeByNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error + // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void invokeByNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return data at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return data at given address in genesis block void invokeCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertCanonicalBlockHashWhenCanonical("0x1", chain.block, blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return data at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return data at given address in genesis block void invokeByCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); assertCanonicalBlockHashWhenNotCanonical("0x1", chain.block, blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return data at given address in specified block + // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return data at given address in specified block void invokeByNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHashWhenNotCanonical("0x1", chain.block, blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); } @Test - // [ "0x
", { "blockHash": "0x" } -> return data at given address in specified block + // [ "0x
", { "blockHash": "0x" } -> return data at given address in specified block void invokeByNonCanonicalBlockHash() { final ChainParams chain = chainWithAccount10kBalance(true); assertNonCanonicalBlockHash("0x1", chain.block, blockRef -> chain.web3.invokeByBlockRef(blockRef, b -> b)); @@ -821,7 +823,7 @@ void getTransactionByHash() { // Check the v value used to encode the transaction // NOT the v value used in signature // the encoded value includes chain id - Assertions.assertArrayEquals(new byte[] {tx.getEncodedV()}, HexUtils.stringHexToByteArray(tr.getV())); + Assertions.assertArrayEquals(new byte[]{tx.getEncodedV()}, HexUtils.stringHexToByteArray(tr.getV())); MatcherAssert.assertThat(HexUtils.stringHexToBigInteger(tr.getS()), is(tx.getSignature().getS())); MatcherAssert.assertThat(HexUtils.stringHexToBigInteger(tr.getR()), is(tx.getSignature().getR())); } @@ -902,8 +904,9 @@ void getTransactionByBlockHashAndIndex() { String hashString = tx.getHash().toHexString(); String blockHashString = block1.getHash().toHexString(); - - TransactionResultDTO tr = web3.eth_getTransactionByBlockHashAndIndex(blockHashString, "0x0"); + BlockHashParam blockHashParam = new BlockHashParam(blockHashString); + HexIndexParam hexIndexParam = new HexIndexParam("0x0"); + TransactionResultDTO tr = web3.eth_getTransactionByBlockHashAndIndex(blockHashParam, hexIndexParam); assertNotNull(tr); assertEquals("0x" + hashString, tr.getHash()); @@ -923,8 +926,9 @@ void getUnknownTransactionByBlockHashAndIndex() { assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block1)); String blockHashString = block1.getHash().toString(); - - TransactionResultDTO tr = web3.eth_getTransactionByBlockHashAndIndex(blockHashString, "0x0"); + BlockHashParam blockHashParam = new BlockHashParam(blockHashString); + HexIndexParam hexIndexParam = new HexIndexParam("0x0"); + TransactionResultDTO tr = web3.eth_getTransactionByBlockHashAndIndex(blockHashParam, hexIndexParam); Assertions.assertNull(tr); } @@ -996,42 +1000,42 @@ void getTransactionCount() { } @Test - //[ "0x
", { "blockNumber": "0x0" } -> return tx count at given address in genesis block + //[ "0x
", { "blockNumber": "0x0" } -> return tx count at given address in genesis block void getTransactionCountByBlockNumber() { final ChainParams chain = createChainWithATransaction(false); assertByBlockNumber("0x1", blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException + //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException void getTransactionCountAndInvalidInputThrowsException() { final ChainParams chain = createChainWithATransaction(false); assertInvalidInput(blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return tx count at given address in genesis block + //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return tx count at given address in genesis block void getTransactionCountByBlockHash() { final ChainParams chain = createChainWithATransaction(false); assertByBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); } @Test - //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error + //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getTransactionCountByNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); assertNonExistentBlockHash(blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); } @Test - // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error + // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getTransactionCountByNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithATransaction(true); assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); } @Test - // [ "0x
", { "blockHash": "0x" } -> return tx count at given address in specified bloc + // [ "0x
", { "blockHash": "0x" } -> return tx count at given address in specified bloc void getTransactionCountByNonCanonicalBlockHash() { final ChainParams chain = createChainWithATransaction(true); assertNonCanonicalBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); @@ -1226,8 +1230,11 @@ void getBlockByHash() { String block1HashString = "0x" + block1.getHash(); String block1bHashString = "0x" + block1b.getHash(); String block2bHashString = "0x" + block2b.getHash(); + BlockHashParam blockHashParam1 = new BlockHashParam(block1HashString); + BlockHashParam blockHashParam1b = new BlockHashParam(block1bHashString); + BlockHashParam blockHashParam2 = new BlockHashParam(block2bHashString); - BlockResultDTO bresult = web3.eth_getBlockByHash(block1HashString, false); + BlockResultDTO bresult = web3.eth_getBlockByHash(blockHashParam1, false); assertNotNull(bresult); assertEquals(block1HashString, bresult.getHash()); @@ -1236,7 +1243,7 @@ void getBlockByHash() { assertEquals(0, bresult.getUncles().size()); assertEquals("0xa", bresult.getDifficulty()); assertEquals("0xb", bresult.getTotalDifficulty()); - bresult = web3.eth_getBlockByHash(block1bHashString, true); + bresult = web3.eth_getBlockByHash(blockHashParam1b, true); assertNotNull(bresult); assertEquals(block1bHashString, bresult.getHash()); @@ -1245,7 +1252,7 @@ void getBlockByHash() { Keccak256 blockHash = new Keccak256(HashUtil.keccak256(Hex.decode(hexString))); assertEquals(blockHash.toJsonString(), block1bHashString); - bresult = web3.eth_getBlockByHash(block2bHashString, true); + bresult = web3.eth_getBlockByHash(blockHashParam2, true); assertNotNull(bresult); assertEquals(block2bHashString, bresult.getHash()); @@ -1274,8 +1281,8 @@ void getBlockByHashWithFullTransactionsAsResult() { assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block1)); String block1HashString = block1.getHashJsonString(); - - BlockResultDTO bresult = web3.eth_getBlockByHash(block1HashString, true); + BlockHashParam blockHashParam = new BlockHashParam(block1HashString); + BlockResultDTO bresult = web3.eth_getBlockByHash(blockHashParam, true); assertNotNull(bresult); assertEquals(block1HashString, bresult.getHash()); @@ -1304,8 +1311,9 @@ void getBlockByHashWithTransactionsHashAsResult() { assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block1)); String block1HashString = block1.getHashJsonString(); + BlockHashParam blockHashParam = new BlockHashParam(block1HashString); - BlockResultDTO bresult = web3.eth_getBlockByHash(block1HashString, false); + BlockResultDTO bresult = web3.eth_getBlockByHash(blockHashParam, false); assertNotNull(bresult); assertEquals(block1HashString, bresult.getHash()); @@ -1321,7 +1329,9 @@ void getBlockByHashBlockDoesNotExists() { Web3Impl web3 = createWeb3(world); String blockHash = "0x1234000000000000000000000000000000000000000000000000000000000000"; - BlockResultDTO blockResult = web3.eth_getBlockByHash(blockHash, false); + BlockHashParam blockHashParam = new BlockHashParam(blockHash); + + BlockResultDTO blockResult = web3.eth_getBlockByHash(blockHashParam, false); Assertions.assertNull(blockResult); @@ -1376,8 +1386,8 @@ void getBlockByHashBlockWithUncles() { String block1bHashString = "0x" + block1b.getHash(); String block1cHashString = "0x" + block1c.getHash(); String block2HashString = "0x" + block2.getHash(); - - BlockResultDTO result = web3.eth_getBlockByHash(block2HashString, false); + BlockHashParam block2HashStringParam = new BlockHashParam(block2HashString); + BlockResultDTO result = web3.eth_getBlockByHash(block2HashStringParam, false); assertEquals(block2HashString, result.getHash()); assertEquals(block1HashString, result.getParentHash()); @@ -1499,8 +1509,10 @@ void getUncleByBlockHashAndIndexBlockWithUncles() { String blockEhash = "0x" + blockE.getHash(); String blockBhash = "0x" + blockB.getHash(); String blockChash = "0x" + blockC.getHash(); + BlockHashParam blockFhashParam = new BlockHashParam(blockFhash); + HexIndexParam hexIndexParam = new HexIndexParam("0x00"); - BlockResultDTO result = web3.eth_getUncleByBlockHashAndIndex(blockFhash, "0x00"); + BlockResultDTO result = web3.eth_getUncleByBlockHashAndIndex(blockFhashParam, hexIndexParam); assertEquals(blockEhash, result.getHash()); assertEquals(2, result.getUncles().size()); @@ -1564,8 +1576,10 @@ void getUncleByBlockHashAndIndexBlockWithUnclesCorrespondingToAnUnknownBlock() { String blockFhash = "0x" + blockF.getHash(); String blockEhash = "0x" + blockE.getHash(); + BlockHashParam blockFhashParam = new BlockHashParam(blockFhash); + HexIndexParam hexIndexParam = new HexIndexParam("0x00"); - BlockResultDTO result = web3.eth_getUncleByBlockHashAndIndex(blockFhash, "0x00"); + BlockResultDTO result = web3.eth_getUncleByBlockHashAndIndex(blockFhashParam, hexIndexParam); assertEquals(blockEhash, result.getHash()); assertEquals(0, result.getUncles().size()); @@ -2147,7 +2161,7 @@ void sendPersonalTransaction() throws Exception { when(ethereumMock.submitTransaction(expectedTx)).thenReturn(pendingTransactionResult); // ***** Executes the transaction ******************* - String txHash = web3.personal_sendTransaction(args, "passphrase1"); + String txHash = web3.personal_sendTransaction(args, "passphrase1"); // ***** Checking expected result ******************* @@ -2155,7 +2169,7 @@ void sendPersonalTransaction() throws Exception { } @Test - void sendPersonalTransactionFailsIfTransactionIsNotQueued(){ + void sendPersonalTransactionFailsIfTransactionIsNotQueued() { Ethereum ethereumMock = Web3Mocks.getMockEthereum(); Web3Impl web3 = createWeb3(ethereumMock); @@ -2199,8 +2213,8 @@ void sendPersonalTransactionFailsIfTransactionIsNotQueued(){ web3.personal_sendTransaction(args, "passphrase1"); }); - assertEquals(-32010,thrownEx.getCode(), "Unexpected exception code"); - assertEquals(pendingTransactionResult.getErrorMessage(),thrownEx.getMessage(),"Exception message should be the same as the one from add transaction result."); + assertEquals(-32010, thrownEx.getCode(), "Unexpected exception code"); + assertEquals(pendingTransactionResult.getErrorMessage(), thrownEx.getMessage(), "Exception message should be the same as the one from add transaction result."); } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HashParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HashParamTest.java new file mode 100644 index 00000000000..80396db89dc --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HashParamTest.java @@ -0,0 +1,46 @@ +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class HashParamTest { + + @Test + void testBlockHashParam() { + String validHash = "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8"; + String invalidHash = "invalidhash"; + String shorterHash = "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a3568"; + String invalidCharHash = "0xc2b835124172db5bdzz1bb94fa123721eacac43b5cba2499b22c7583a3568"; + + BlockHashParam blockHashParam = new BlockHashParam(validHash); + + assertEquals(validHash, blockHashParam.getHash().toJsonString()); + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam(null)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam("")); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam(invalidHash)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam(shorterHash)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam(invalidCharHash)); + } + + @Test + void testTxHashParam() { + String validHash = "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8"; + String invalidHash = "invalidhash"; + String shorterHash = "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a3568"; + String invalidCharHash = "0xc2b835124172db5bdzz1bb94fa123721eacac43b5cba2499b22c7583a3568"; + + TxHashParam txHashParam = new TxHashParam(validHash); + + assertEquals(validHash, txHashParam.getHash().toJsonString()); + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam(null)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam("")); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam(invalidHash)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam(shorterHash)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockHashParam(invalidCharHash)); + } +} \ No newline at end of file diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java new file mode 100644 index 00000000000..21cd89ce9f7 --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java @@ -0,0 +1,46 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class HexIndexParamTest { + + @Test + void testValidHexIndexParam() { + String validHexValue = "0x123"; + HexIndexParam hexIndexParam = new HexIndexParam(validHexValue); + + assertNotNull(hexIndexParam); + assertEquals(291, hexIndexParam.getIndex()); + } + + @Test + void testInvalidHexIndexParam() { + String invalidHexValue = "123"; // Missing hex prefix + String nonNumericHexValue = "0xabcz"; // Non-valid hex value + + assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(invalidHexValue)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(nonNumericHexValue)); + } + +} \ No newline at end of file From 22cc178a270aa302b8fae8e7ff572976c3e4300e Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Thu, 10 Aug 2023 17:13:18 +0200 Subject: [PATCH 02/47] Updated deserializers parent class and updated new eth_getTransaction.. related methods having parameter validation --- .../main/java/co/rsk/rpc/Web3EthModule.java | 5 +- .../main/java/org/ethereum/rpc/Web3Impl.java | 13 ++- .../rpc/parameters/BlockHashParam.java | 16 +++- .../rpc/parameters/HexIndexParam.java | 14 ++- .../ethereum/rpc/parameters/TxHashParam.java | 16 +++- .../rpc/netty/JsonRPCParamValidationTest.java | 95 +++++++++++++++++-- .../java/org/ethereum/rpc/Web3ImplTest.java | 17 ++-- 7 files changed, 144 insertions(+), 32 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index ba023596174..dbe9b123a70 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -27,6 +27,7 @@ import org.ethereum.rpc.dto.TransactionResultDTO; import org.ethereum.rpc.parameters.BlockHashParam; import org.ethereum.rpc.parameters.HexIndexParam; +import org.ethereum.rpc.parameters.TxHashParam; import java.math.BigInteger; import java.util.Map; @@ -88,7 +89,7 @@ default String eth_chainId() { String eth_getTransactionCount(String address, String blockId) throws Exception ; - String eth_getBlockTransactionCountByHash(String blockHash)throws Exception; + String eth_getBlockTransactionCountByHash(BlockHashParam blockHash)throws Exception; String eth_getBlockTransactionCountByNumber(String bnOrId)throws Exception; @@ -114,7 +115,7 @@ default String eth_sendTransaction(CallArguments args) { BlockResultDTO eth_getBlockByNumber(String bnOrId, Boolean fullTransactionObjects) throws Exception; - TransactionResultDTO eth_getTransactionByHash(String transactionHash) throws Exception; + TransactionResultDTO eth_getTransactionByHash(TxHashParam transactionHash) throws Exception; TransactionResultDTO eth_getTransactionByBlockHashAndIndex(BlockHashParam blockHash, HexIndexParam index) throws Exception; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index 99846927f8f..92fc8e519c3 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -61,6 +61,7 @@ import org.ethereum.rpc.dto.TransactionResultDTO; import org.ethereum.rpc.parameters.BlockHashParam; import org.ethereum.rpc.parameters.HexIndexParam; +import org.ethereum.rpc.parameters.TxHashParam; import org.ethereum.util.BuildInfo; import org.ethereum.vm.DataWord; import org.slf4j.Logger; @@ -77,9 +78,7 @@ import static co.rsk.util.HexUtils.*; import static java.lang.Math.max; -import static org.ethereum.rpc.exception.RskJsonRpcRequestException.blockNotFound; -import static org.ethereum.rpc.exception.RskJsonRpcRequestException.invalidParamError; -import static org.ethereum.rpc.exception.RskJsonRpcRequestException.unimplemented; +import static org.ethereum.rpc.exception.RskJsonRpcRequestException.*; public class Web3Impl implements Web3 { private static final Logger logger = LoggerFactory.getLogger("web3"); @@ -539,10 +538,10 @@ public Block getBlockByJSonHash(String blockHash) { } @Override - public String eth_getBlockTransactionCountByHash(String blockHash) { + public String eth_getBlockTransactionCountByHash(BlockHashParam blockHash) { String s = null; try { - Block b = getBlockByJSonHash(blockHash); + Block b = blockchain.getBlockByHash(blockHash.getHash().getBytes()); if (b == null) { return null; @@ -681,10 +680,10 @@ public BlockResultDTO eth_getBlockByNumber(String bnOrId, Boolean fullTransactio } @Override - public TransactionResultDTO eth_getTransactionByHash(String transactionHash) { + public TransactionResultDTO eth_getTransactionByHash(TxHashParam transactionHash) { TransactionResultDTO s = null; try { - Keccak256 txHash = new Keccak256(stringHexToByteArray(transactionHash)); + Keccak256 txHash = transactionHash.getHash(); Block block = null; TransactionInfo txInfo = this.receiptStore.getInMainChain(txHash.getBytes(), blockStore).orElse(null); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockHashParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockHashParam.java index f48a3ab8c1a..a2cfbf97967 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockHashParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockHashParam.java @@ -19,20 +19,32 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; @JsonDeserialize(using = BlockHashParam.Deserializer.class) public class BlockHashParam extends HashParam32 { + private static final String HASH_TYPE = "block hash"; public BlockHashParam(String hash) { super(HASH_TYPE, hash); } - public static class Deserializer extends JsonDeserializer { + public static class Deserializer extends StdDeserializer { + + private static final long serialVersionUID = 8071595037666226210L; + + public Deserializer() { + this(null); + } + + public Deserializer(Class vc) { + super(vc); + } + @Override public BlockHashParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { String hash = jp.getText(); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java index fccaaed5bac..2a522a9c2a0 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -21,8 +21,8 @@ import co.rsk.util.HexUtils; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import java.io.IOException; @@ -33,7 +33,7 @@ public class HexIndexParam { public HexIndexParam(String indexString) { if (!HexUtils.hasHexPrefix(indexString) || !HexUtils.isHex(indexString,2)) { - throw RskJsonRpcRequestException.invalidParamError("Invalid argument: " + indexString + ": param should be a hex value string."); + throw RskJsonRpcRequestException.invalidParamError("Invalid argument \"" + indexString + "\": param should be a hex value string."); } String preResult = HexUtils.removeHexPrefix(indexString); this.index = Integer.parseInt(preResult, 16); @@ -43,7 +43,15 @@ public Integer getIndex() { return index; } - public static class Deserializer extends JsonDeserializer { + public static class Deserializer extends StdDeserializer { + + public Deserializer() { + this(null); + } + + public Deserializer(Class vc) { + super(vc); + } @Override public HexIndexParam deserialize(JsonParser jp, DeserializationContext ctxt) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java index b74b6df70e4..e2e0bc3814b 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java @@ -17,10 +17,11 @@ */ package org.ethereum.rpc.parameters; + import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; @@ -31,13 +32,22 @@ public TxHashParam(String hash) { super(HASH_TYPE, hash); } - public static class Deserializer extends JsonDeserializer { + public static class Deserializer extends StdDeserializer { + + private static final long serialVersionUID = 2669501504172497269L; + + public Deserializer() { + this(null); + } + + public Deserializer(Class vc) { + super(vc); + } @Override public TxHashParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { String hash = jp.getText(); return new TxHashParam(hash); - } } } diff --git a/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java b/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java index ca3b09a473c..79131429524 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java @@ -58,7 +58,8 @@ void eth_getBlockByHash() throws Exception { "\t\"jsonrpc\":\"2.0\",\n" + "\t\"method\":\"eth_getBlockByHash\",\n" + "\t\"params\":[\n" + - "\t\t\"0xec576a07c263125c864bce15dee5046774f474ea123c581c08008bea2\"\n" + + "\t\t\"0xad1328d13f833b8af722117afdc406a762033321df8e48c00cd372d462f48169\", \n" + + "\t\ttrue\n" + "\t],\n" + "\t\"id\":1\n" + "}"; @@ -68,6 +69,7 @@ void eth_getBlockByHash() throws Exception { JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); assertNotNull(response); + assertEquals(0, response.getCode()); } @Test @@ -90,7 +92,7 @@ void eth_getBlockByHash_invalidHexCharInHash_returnsError() throws Exception { JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); assertEquals(-32602, response.getCode()); String message = response.getResponse().get("error").get("message").asText(); - assertEquals("Invalid block hash format. exception decoding Hex string: invalid characters encountered in Hex string",message); + assertEquals("Invalid block hash format. exception decoding Hex string: invalid characters encountered in Hex string", message); } @Test @@ -112,12 +114,12 @@ void eth_getBlockByHash_invalidHashLength_returnsError() throws Exception { JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); assertEquals(-32602, response.getCode()); String message = response.getResponse().get("error").get("message").asText(); - assertEquals("Invalid block hash: incorrect length.",message); + assertEquals("Invalid block hash: incorrect length.", message); } @Test - void eth_getTransactionByBlockHashAndIndex_invalidHash_returnsError() throws Exception{ + void eth_getTransactionByBlockHashAndIndex_invalidHash_returnsError() throws Exception { TransactionResultDTO resultDTO = mock(TransactionResultDTO.class); String requestBody = "{\n" + "\t\"jsonrpc\":\"2.0\",\n" + @@ -133,12 +135,12 @@ void eth_getTransactionByBlockHashAndIndex_invalidHash_returnsError() throws Exc JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); assertEquals(-32602, response.getCode()); String message = response.getResponse().get("error").get("message").asText(); - assertEquals("Invalid block hash: incorrect length.",message); + assertEquals("Invalid block hash: incorrect length.", message); } @Test - void eth_getTransactionByBlockHashAndIndex_invalidIndex_returnsError() throws Exception{ + void eth_getTransactionByBlockHashAndIndex_invalidIndex_returnsError() throws Exception { TransactionResultDTO resultDTO = mock(TransactionResultDTO.class); String requestBody = "{\n" + "\t\"jsonrpc\":\"2.0\",\n" + @@ -154,7 +156,86 @@ void eth_getTransactionByBlockHashAndIndex_invalidIndex_returnsError() throws Ex JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); assertEquals(-32602, response.getCode()); String message = response.getResponse().get("error").get("message").asText(); - assertEquals("Invalid argument: abc: param should be a hex value string.",message); + assertEquals("Invalid argument: abc: param should be a hex value string.", message); + } + + @Test + void eth_getBlockTransactionCountByHash_invalidHash_returnsError() throws Exception { + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getBlockTransactionCountByHash\",\n" + + "\t\"params\":[\n" + + "\t\t\"0x3c82bc62179602b6731037c49cba84e31ffe6e465a21c521a7\"\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + when(handler.eth_getBlockTransactionCountByHash(any())).thenReturn("0x0"); + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertEquals(-32602, response.getCode()); + String message = response.getResponse().get("error").get("message").asText(); + assertEquals("Invalid block hash: incorrect length.", message); + } + + @Test + void eth_getTransactionByHash_invalidHash_returnsError() throws Exception { + TransactionResultDTO resultDTO = mock(TransactionResultDTO.class); + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getTransactionByHash\",\n" + + "\t\"params\":[\n" + + "\t\t\"0xc2b835zzz172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8\"\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertEquals(-32602, response.getCode()); + String message = response.getResponse().get("error").get("message").asText(); + assertEquals("Invalid transaction hash format. exception decoding Hex string: invalid characters encountered in Hex string", message); + } + + @Test + void eth_getUncleByBlockHashAndIndex_invalidHash_returnsError() throws Exception { + BlockResultDTO blockResultDTO = mock(BlockResultDTO.class); + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getUncleByBlockHashAndIndex\",\n" + + "\t\"params\":[\n" + + "\t\t\"0x3c82bc62179602b6731037c49cba84e31ffe6e465a21c521a7\", \n" + + "\t\t\"0x0\"\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + + when(handler.eth_getUncleByBlockHashAndIndex(any(), any())).thenReturn(blockResultDTO); + + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertEquals(-32602, response.getCode()); + String message = response.getResponse().get("error").get("message").asText(); + assertEquals("Invalid block hash: incorrect length.", message); } + @Test + void eth_getUncleByBlockHashAndIndex_invalidIndex_returnsError() throws Exception { + BlockResultDTO blockResultDTO = mock(BlockResultDTO.class); + String requestBody = "{\n" + + "\t\"jsonrpc\":\"2.0\",\n" + + "\t\"method\":\"eth_getUncleByBlockHashAndIndex\",\n" + + "\t\"params\":[\n" + + "\t\t\"0x3c82bc62179602b67318c013c10f99011037c49cba84e31ffe6e465a21c521a7\", \n" + + "\t\t\"122\"\n" + + "\t],\n" + + "\t\"id\":1\n" + + "}"; + JsonNode request = objectMapper.readTree(requestBody); + + when(handler.eth_getUncleByBlockHashAndIndex(any(), any())).thenReturn(blockResultDTO); + + JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); + assertEquals(-32602, response.getCode()); + String message = response.getResponse().get("error").get("message").asText(); + assertEquals("Invalid argument \"122\": param should be a hex value string.", message); + } } \ 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 5ddf45bf409..a7d4529fafb 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -79,6 +79,7 @@ import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockHashParam; import org.ethereum.rpc.parameters.HexIndexParam; +import org.ethereum.rpc.parameters.TxHashParam; import org.ethereum.util.BuildInfo; import org.ethereum.util.ByteUtil; import org.ethereum.vm.PrecompiledContracts; @@ -808,8 +809,8 @@ void getTransactionByHash() { Block block1 = createCanonicalBlock(world, txs); String hashString = tx.getHash().toHexString(); - - TransactionResultDTO tr = web3.eth_getTransactionByHash(hashString); + TxHashParam txHashParam = new TxHashParam(hashString); + TransactionResultDTO tr = web3.eth_getTransactionByHash(txHashParam); assertNotNull(tr); assertEquals("0x" + hashString, tr.getHash()); @@ -846,8 +847,8 @@ void getPendingTransactionByHash() { transactionPool.addTransaction(tx); String hashString = tx.getHash().toHexString(); - - TransactionResultDTO tr = web3.eth_getTransactionByHash(hashString); + TxHashParam txHashParam = new TxHashParam(hashString); + TransactionResultDTO tr = web3.eth_getTransactionByHash(txHashParam); assertNotNull(tr); @@ -883,8 +884,8 @@ void getTransactionByHashNotInMainBlockchain() { assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block2b)); String hashString = tx.getHash().toHexString(); - - TransactionResultDTO tr = web3.eth_getTransactionByHash(hashString); + TxHashParam txHashParam = new TxHashParam(hashString); + TransactionResultDTO tr = web3.eth_getTransactionByHash(txHashParam); Assertions.assertNull(tr); } @@ -2994,9 +2995,9 @@ void transactionReceiptAndResultHasTypeField() { Block block1 = createCanonicalBlock(world, txs); String hashString = tx.getHash().toHexString(); - + TxHashParam txHashParam = new TxHashParam(hashString); TransactionReceiptDTO txReceipt = web3.eth_getTransactionReceipt(hashString); - TransactionResultDTO txResult = web3.eth_getTransactionByHash(hashString); + TransactionResultDTO txResult = web3.eth_getTransactionByHash(txHashParam); assertEquals("0x0", txReceipt.getType()); assertEquals("0x0", txResult.getType()); From f1baf1998bc52761fc0d9f4326d6fe13e353a8bb Mon Sep 17 00:00:00 2001 From: maximo santoro Date: Tue, 15 Aug 2023 20:53:41 -0300 Subject: [PATCH 03/47] fix hex input validation --- rskj-core/src/main/java/co/rsk/util/HexUtils.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rskj-core/src/main/java/co/rsk/util/HexUtils.java b/rskj-core/src/main/java/co/rsk/util/HexUtils.java index f2081af8347..f04aae64aef 100644 --- a/rskj-core/src/main/java/co/rsk/util/HexUtils.java +++ b/rskj-core/src/main/java/co/rsk/util/HexUtils.java @@ -353,6 +353,16 @@ public static byte[] decode(byte[] dataBytes) { * decodes a hexadecimal encoded with the 0x prefix into a integer */ public static int jsonHexToInt(final String param) { + if (!hasHexPrefix(param)) { + throw invalidParamError(INCORRECT_HEX_SYNTAX); + } + + String preResult = removeHexPrefix(param); + + return Integer.parseInt(preResult, 16); + } + + public static int jsonHexToIntOptionalPrefix(final String param) { if (!hasHexPrefix(param) && !HexUtils.isHex(param)) { throw invalidParamError(INCORRECT_HEX_SYNTAX); } From d45a14f69e8c52f17b237730f78817ab4579357e Mon Sep 17 00:00:00 2001 From: maximo santoro Date: Tue, 15 Aug 2023 20:55:58 -0300 Subject: [PATCH 04/47] fix unit test exception message --- .../test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java b/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java index 79131429524..3c70c2eae48 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java @@ -156,7 +156,7 @@ void eth_getTransactionByBlockHashAndIndex_invalidIndex_returnsError() throws Ex JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); assertEquals(-32602, response.getCode()); String message = response.getResponse().get("error").get("message").asText(); - assertEquals("Invalid argument: abc: param should be a hex value string.", message); + assertEquals("Invalid argument \"abc\": param should be a hex value string.", message); } @Test From 17220174d18299cc1f07dad159ce19ce8285afbc Mon Sep 17 00:00:00 2001 From: maximo santoro Date: Wed, 16 Aug 2023 12:28:54 -0300 Subject: [PATCH 05/47] fix sonarqube warning --- .../main/java/org/ethereum/rpc/parameters/HexIndexParam.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java index 2a522a9c2a0..ef7f34e5a9e 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -26,9 +26,12 @@ import org.ethereum.rpc.exception.RskJsonRpcRequestException; import java.io.IOException; +import java.io.Serializable; @JsonDeserialize(using = HexIndexParam.Deserializer.class) -public class HexIndexParam { +public class HexIndexParam implements Serializable { + private static final long serialVersionUID = 1L; + private final Integer index; public HexIndexParam(String indexString) { From 50df9f9114c2bbda337bc5ef8b27e9eb35e5479a Mon Sep 17 00:00:00 2001 From: maximo santoro Date: Thu, 17 Aug 2023 09:56:02 -0300 Subject: [PATCH 06/47] add serialVersionUID to deserializer --- .../main/java/org/ethereum/rpc/parameters/HexIndexParam.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java index ef7f34e5a9e..7f9bfdef205 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -48,6 +48,8 @@ public Integer getIndex() { public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + public Deserializer() { this(null); } From bc6baa58f402757c01d7f702c4c11ae9b04f22d1 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Sat, 26 Aug 2023 09:48:53 -0400 Subject: [PATCH 07/47] Add deserializers for CallArguments, RawData, Address and BlockIdentifier --- .../rpc/parameters/BlockIdentifierParam.java | 50 ++++++++ .../rpc/parameters/CallArgumentsParam.java | 112 ++++++++++++++++++ .../rpc/parameters/HexAddressParam.java | 48 ++++++++ .../rpc/parameters/HexRawDataParam.java | 50 ++++++++ .../parameters/BlockIdentifierParamTest.java | 45 +++++++ .../parameters/CallArgumentsParamTest.java | 105 ++++++++++++++++ .../rpc/parameters/HexAddressParamTest.java | 29 +++++ .../rpc/parameters/HexRawDataParamTest.java | 28 +++++ 8 files changed, 467 insertions(+) create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/HexRawDataParam.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/CallArgumentsParamTest.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/HexAddressParamTest.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/HexRawDataParamTest.java diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java new file mode 100644 index 00000000000..b214a47df48 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java @@ -0,0 +1,50 @@ +package org.ethereum.rpc.parameters; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.util.Utils; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +@JsonDeserialize(using = BlockIdentifierParam.Deserializer.class) +public class BlockIdentifierParam implements Serializable { + private static final long serialVersionUID = 1L; + + private static final List STRING_IDENTIFIERS = Arrays.asList("earliest", "latest", "pending"); + + private final String identifier; + + public BlockIdentifierParam(String identifier) { + if(!STRING_IDENTIFIERS.contains(identifier) + && !Utils.isDecimalString(identifier) + && !Utils.isHexadecimalString(identifier)) { + throw RskJsonRpcRequestException.invalidParamError("Invalid block identifier '" + identifier + "'"); + } + + this.identifier = identifier; + } + + public String getIdentifier() { + return identifier; + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public Deserializer() { this(null); } + + public Deserializer(Class vc) { super(vc); } + + @Override + public BlockIdentifierParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String identifier = jp.getText(); + return new BlockIdentifierParam(identifier); + } + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java new file mode 100644 index 00000000000..01b3a73c482 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java @@ -0,0 +1,112 @@ +package org.ethereum.rpc.parameters; + +import co.rsk.util.HexUtils; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.CallArguments; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; + +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Field; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +@JsonDeserialize(using = CallArgumentsParam.Deserializer.class) +public class CallArgumentsParam implements Serializable { + private static final long serialVersionUID = 1L; + + private static final List ADDRESS_PROPERTIES = Arrays.asList("to", "from"); + private static final List NUMBER_PROPERTIES = Arrays.asList("gas", "gasPrice", "gasLimit", "nonce", "chainId", "value"); + + private final CallArguments callArguments; + + public CallArgumentsParam(CallArguments callArguments) { + Field[] fields = CallArguments.class.getDeclaredFields(); + Arrays.stream(fields).forEach(field -> { + String fieldName = field.getName(); + Object fieldValue = null; + try { + field.setAccessible(true); + fieldValue = field.get(callArguments); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + validateProperty(fieldValue, fieldName); + }); + + this.callArguments = callArguments; + } + + public CallArguments getCallArguments() { + return callArguments; + } + + private boolean isPropertyValidHex(String propertyValue) { + boolean hasPrefix = HexUtils.hasHexPrefix(propertyValue); + return HexUtils.isHex(propertyValue.toLowerCase(), hasPrefix ? 2 : 0); + } + + private void validateAddressProperty(String propertyValue, String propertyName) { + if (propertyValue == null || propertyValue.isEmpty()) { + throw RskJsonRpcRequestException.invalidParamError("Invalid param " + propertyName + ": empty or null."); + } + + if (!isPropertyValidHex(propertyValue)) { + throw RskJsonRpcRequestException.invalidParamError("Invalid param " + propertyName + ": invalid character in hex input."); + } + } + + private void validateNumberProperty(String propertyValue, String propertyName) { + if(propertyValue == null) { + return; + } + + if (!isPropertyValidHex(propertyValue)) { + try { + new BigInteger(propertyValue); + } catch(Exception e) { + throw RskJsonRpcRequestException.invalidParamError("Invalid param " + propertyName + ": value must be a valid hex or string number."); + } + } + } + + private void validateDataProperty(String propertyValue) { + if(propertyValue == null) { + return; + } + + if(!isPropertyValidHex(propertyValue)) { + throw RskJsonRpcRequestException.invalidParamError("Invalid param data: invalid character in hex input."); + } + } + + private void validateProperty(Object propertyValue, String propertyName) { + if(ADDRESS_PROPERTIES.contains(propertyName)) { + validateAddressProperty((String) propertyValue, propertyName); + } else if(NUMBER_PROPERTIES.contains(propertyName)) { + validateNumberProperty((String) propertyValue, propertyName); + } else if(propertyName.equals("data")) { + validateDataProperty((String) propertyValue); + } + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + private final ObjectMapper mapper = new ObjectMapper(); + + public Deserializer() { this(null); } + + public Deserializer(Class vc) { super(vc); } + + @Override + public CallArgumentsParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + CallArguments callArguments = mapper.readValue(jp, CallArguments.class); + return new CallArgumentsParam(callArguments); + } + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java new file mode 100644 index 00000000000..9c57a9dac3b --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java @@ -0,0 +1,48 @@ +package org.ethereum.rpc.parameters; + +import co.rsk.core.RskAddress; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; + +import java.io.IOException; +import java.io.Serializable; + +@JsonDeserialize(using = HexAddressParam.Deserializer.class) +public class HexAddressParam implements Serializable { + private static final long serialVersionUID = 1L; + + private final RskAddress address; + + public HexAddressParam(String hexAddress) { + if (hexAddress == null || hexAddress.isEmpty()) { + throw RskJsonRpcRequestException.invalidParamError("Invalid address: empty or null."); + } + + try { + this.address = new RskAddress(hexAddress); + } catch (Exception e) { + throw RskJsonRpcRequestException.invalidParamError("Invalid address format. " + e.getMessage()); + } + } + + public RskAddress getAddress() { + return address; + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public Deserializer() { this(null); } + + public Deserializer(Class vc) { super(vc); } + + @Override + public HexAddressParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String hexAddress = jp.getText(); + return new HexAddressParam(hexAddress); + } + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexRawDataParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexRawDataParam.java new file mode 100644 index 00000000000..215425ac557 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexRawDataParam.java @@ -0,0 +1,50 @@ +package org.ethereum.rpc.parameters; + +import co.rsk.util.HexUtils; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; + +import java.io.IOException; +import java.io.Serializable; + +@JsonDeserialize(using = HexRawDataParam.Deserializer.class) +public class HexRawDataParam implements Serializable { + private static final long serialVersionUID = 1L; + + private static final int HASH_BYTE_LENGTH = 148; + + private final byte[] rawDataBytes; + + public HexRawDataParam(String rawData){ + try { + this.rawDataBytes = HexUtils.stringHexToByteArray(rawData); + } catch (Exception e) { + throw RskJsonRpcRequestException.invalidParamError("Invalid data format. " + e.getMessage()); + } + + if (HASH_BYTE_LENGTH != rawDataBytes.length) { + throw RskJsonRpcRequestException.invalidParamError("Invalid data: incorrect length."); + } + } + + public byte[] getRawDataBytes() { + return rawDataBytes; + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public Deserializer() { this(null); } + + public Deserializer(Class vc) { super(vc); } + + @Override + public HexRawDataParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String hexRawData = jp.getText(); + return new HexRawDataParam(hexRawData); + } + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java new file mode 100644 index 00000000000..31c8ccc1305 --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java @@ -0,0 +1,45 @@ +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class BlockIdentifierParamTest { + @Test + public void testValidStringBlockIdentifier() { + String validBlockIdentifier = "latest"; + + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam(validBlockIdentifier); + + assertEquals(validBlockIdentifier, blockIdentifierParam.getIdentifier()); + } + + @Test + public void testValidHexBlockIdentifier() { + String validBlockIdentifier = "0xf892038609184e"; + + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam(validBlockIdentifier); + + assertEquals(validBlockIdentifier, blockIdentifierParam.getIdentifier()); + } + + @Test + public void testValidDecimalBlockIdentifier() { + String validBlockIdentifier = "1028"; + + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam(validBlockIdentifier); + + assertEquals(validBlockIdentifier, blockIdentifierParam.getIdentifier()); + } + + @Test + public void testInvalidHexAddressParam() { + String invalidStringIdentifier = "first"; + String invalidHexIdentifier = "0xf89203860918sv"; + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockIdentifierParam(invalidStringIdentifier)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockIdentifierParam(invalidHexIdentifier)); + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/CallArgumentsParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/CallArgumentsParamTest.java new file mode 100644 index 00000000000..19d4027446a --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/CallArgumentsParamTest.java @@ -0,0 +1,105 @@ +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.CallArguments; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class CallArgumentsParamTest { + private CallArguments buildCallArguments() { + CallArguments callArguments = new CallArguments(); + + callArguments.setFrom("0x7986b3df570230288501eea3d890bd66948c9b79"); + callArguments.setTo("0xE7B8E91401bF4d1669f54Dc5f98109D7EfBC4EEa"); + callArguments.setGas("0x76c0"); + callArguments.setGasPrice("0x9184e72a000"); + callArguments.setValue("0x9184e72a"); + callArguments.setData("0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"); + callArguments.setNonce("0x1"); + callArguments.setChainId("0x539"); + + return callArguments; + } + + @Test + public void testValidCallArgumentsParam() { + CallArguments validCallArguments = buildCallArguments(); + + CallArgumentsParam callArgumentsParam = new CallArgumentsParam(validCallArguments); + + assertEquals(validCallArguments.getFrom(), callArgumentsParam.getCallArguments().getFrom()); + assertEquals(validCallArguments.getTo(), callArgumentsParam.getCallArguments().getTo()); + assertEquals(validCallArguments.getGas(), callArgumentsParam.getCallArguments().getGas()); + assertEquals(validCallArguments.getGasPrice(), callArgumentsParam.getCallArguments().getGasPrice()); + assertEquals(validCallArguments.getValue(), callArgumentsParam.getCallArguments().getValue()); + assertEquals(validCallArguments.getData(), callArgumentsParam.getCallArguments().getData()); + assertEquals(validCallArguments.getNonce(), callArgumentsParam.getCallArguments().getNonce()); + assertEquals(validCallArguments.getChainId(), callArgumentsParam.getCallArguments().getChainId()); + } + + @Test + public void testInvalidFromInCallArgumentsParam() { + CallArguments invalidCallArguments = buildCallArguments(); + invalidCallArguments.setFrom("0x7986b3df570230288501eea3d890bd66948c9bzx"); + + assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + } + + @Test + public void testInvalidToInCallArgumentsParam() { + CallArguments invalidCallArguments = buildCallArguments(); + invalidCallArguments.setTo("0xE7B8E91401bF4d1669f54Dc5f98109D7EfBC4Eqw"); + + assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + } + + @Test + public void testInvalidGasInCallArgumentsParam() { + CallArguments invalidCallArguments = buildCallArguments(); + invalidCallArguments.setGas("0x76cZ"); + + assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + } + + @Test + public void testInvalidGasPriceInCallArgumentsParam() { + CallArguments invalidCallArguments = buildCallArguments(); + invalidCallArguments.setGasPrice("12tb45"); + + assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + } + + @Test + public void testInvalidValueInCallArgumentsParam() { + CallArguments invalidCallArguments = buildCallArguments(); + invalidCallArguments.setValue("0x9184e7gt"); + + assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + } + + @Test + public void testInvalidDataInCallArgumentsParam() { + CallArguments invalidCallArguments = buildCallArguments(); + invalidCallArguments.setData("0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445phm"); + + assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + } + + @Test + public void testInvalidNonceInCallArgumentsParam() { + CallArguments invalidCallArguments = buildCallArguments(); + invalidCallArguments.setNonce("0xJ"); + + assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + } + + @Test + public void testInvalidChainIdInCallArgumentsParam() { + CallArguments invalidCallArguments = buildCallArguments(); + invalidCallArguments.setChainId("0xB2R"); + + assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexAddressParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexAddressParamTest.java new file mode 100644 index 00000000000..86255b7d7fb --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexAddressParamTest.java @@ -0,0 +1,29 @@ +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class HexAddressParamTest { + + @Test + public void testValidHexAddressParam() { + String validHexAddress = "0x407d73d8a49eeb85d32cf465507dd71d507100c1"; + + HexAddressParam hexAddressParam = new HexAddressParam(validHexAddress); + + assertEquals(validHexAddress, hexAddressParam.getAddress().toJsonString()); + } + + @Test + public void testInvalidHexAddressParam() { + String invalidHexAddress = "0x407d73d8a4sseb85d32cf465507dd71d507100c1"; + String shorterHexAddress = "0x407d73"; + + assertThrows(RskJsonRpcRequestException.class, () -> new HexAddressParam(null)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexAddressParam(invalidHexAddress)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexAddressParam(shorterHexAddress)); + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexRawDataParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexRawDataParamTest.java new file mode 100644 index 00000000000..cfb4fa494ee --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexRawDataParamTest.java @@ -0,0 +1,28 @@ +package org.ethereum.rpc.parameters; + +import co.rsk.util.HexUtils; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class HexRawDataParamTest { + @Test + public void testValidHexRawDataParam() { + String validHexRawData = "0xf892038609184e72a0008276c094e7b8e91401bf4d1669f54dc5f98109d7efbc4eea849184e72aa9d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f07244567565a0ea179f22ab9149013f3330a0921cef8fc8fddc84f3e51746ef8d5a35e04bfd8ba020e5640606a3257f32b9ef2f706c7294666d4bf759093769d40e7fdd2ac2f49e"; + + HexRawDataParam hexRawDataParam = new HexRawDataParam(validHexRawData); + + assertEquals(validHexRawData, HexUtils.toUnformattedJsonHex(hexRawDataParam.getRawDataBytes())); + } + + @Test + public void testInvalidHexRawDataParam() { + String invalidHexRawData = "0xsv92038609184e72a0008276c094e7b8e91401bf4d1669f54dc5f98109d7efbc4eea849184e72aa9d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f07244567565a0ea179f22ab9149013f3330a0921cef8fc8fddc84f3e51746ef8d5a35e04bfd8ba020e5640606a3257f32b9ef2f706c7294666d4bf759093769d40e7fdd2ac2f49e"; + String shorterHexRawData = "0xf892038609184e72a00082"; + + assertThrows(RskJsonRpcRequestException.class, () -> new HexRawDataParam(invalidHexRawData)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexRawDataParam(shorterHexRawData)); + } +} From ba11d0f39ada95acc040fefee3c415a944fade47 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Mon, 28 Aug 2023 08:58:31 -0400 Subject: [PATCH 08/47] Fix sonarcloud issues --- .../rpc/parameters/CallArgumentsParam.java | 39 +++++-------------- .../rpc/parameters/HexAddressParam.java | 2 +- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java index 01b3a73c482..24978297b5c 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java @@ -11,33 +11,24 @@ import java.io.IOException; import java.io.Serializable; -import java.lang.reflect.Field; import java.math.BigInteger; -import java.util.Arrays; -import java.util.List; @JsonDeserialize(using = CallArgumentsParam.Deserializer.class) public class CallArgumentsParam implements Serializable { private static final long serialVersionUID = 1L; - private static final List ADDRESS_PROPERTIES = Arrays.asList("to", "from"); - private static final List NUMBER_PROPERTIES = Arrays.asList("gas", "gasPrice", "gasLimit", "nonce", "chainId", "value"); - - private final CallArguments callArguments; + private transient final CallArguments callArguments; public CallArgumentsParam(CallArguments callArguments) { - Field[] fields = CallArguments.class.getDeclaredFields(); - Arrays.stream(fields).forEach(field -> { - String fieldName = field.getName(); - Object fieldValue = null; - try { - field.setAccessible(true); - fieldValue = field.get(callArguments); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - validateProperty(fieldValue, fieldName); - }); + validateAddressProperty(callArguments.getFrom(), "from"); + validateAddressProperty(callArguments.getTo(), "to"); + validateNumberProperty(callArguments.getGas(), "gas"); + validateNumberProperty(callArguments.getGasPrice(), "gasPrice"); + validateNumberProperty(callArguments.getGasLimit(), "gasLimit"); + validateNumberProperty(callArguments.getNonce(), "nonce"); + validateNumberProperty(callArguments.getChainId(), "chainId"); + validateNumberProperty(callArguments.getValue(), "value"); + validateDataProperty(callArguments.getData()); this.callArguments = callArguments; } @@ -85,16 +76,6 @@ private void validateDataProperty(String propertyValue) { } } - private void validateProperty(Object propertyValue, String propertyName) { - if(ADDRESS_PROPERTIES.contains(propertyName)) { - validateAddressProperty((String) propertyValue, propertyName); - } else if(NUMBER_PROPERTIES.contains(propertyName)) { - validateNumberProperty((String) propertyValue, propertyName); - } else if(propertyName.equals("data")) { - validateDataProperty((String) propertyValue); - } - } - public static class Deserializer extends StdDeserializer { private static final long serialVersionUID = 1L; private final ObjectMapper mapper = new ObjectMapper(); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java index 9c57a9dac3b..2e624235ab0 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java @@ -14,7 +14,7 @@ public class HexAddressParam implements Serializable { private static final long serialVersionUID = 1L; - private final RskAddress address; + private transient final RskAddress address; public HexAddressParam(String hexAddress) { if (hexAddress == null || hexAddress.isEmpty()) { From e9f27a07500fc30726256447e3165815a11cf735 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Mon, 28 Aug 2023 15:09:41 -0400 Subject: [PATCH 09/47] Refactor deserializers --- .../rpc/parameters/CallArgumentsParam.java | 4 ++-- ...{HexRawDataParam.java => HexDataParam.java} | 18 ++++++------------ ...ataParamTest.java => HexDataParamTest.java} | 14 ++++++-------- 3 files changed, 14 insertions(+), 22 deletions(-) rename rskj-core/src/main/java/org/ethereum/rpc/parameters/{HexRawDataParam.java => HexDataParam.java} (67%) rename rskj-core/src/test/java/org/ethereum/rpc/parameters/{HexRawDataParamTest.java => HexDataParamTest.java} (71%) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java index 24978297b5c..1dc5f440e3f 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java @@ -43,8 +43,8 @@ private boolean isPropertyValidHex(String propertyValue) { } private void validateAddressProperty(String propertyValue, String propertyName) { - if (propertyValue == null || propertyValue.isEmpty()) { - throw RskJsonRpcRequestException.invalidParamError("Invalid param " + propertyName + ": empty or null."); + if (propertyValue == null) { + return; } if (!isPropertyValidHex(propertyValue)) { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexRawDataParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java similarity index 67% rename from rskj-core/src/main/java/org/ethereum/rpc/parameters/HexRawDataParam.java rename to rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java index 215425ac557..e124e73564d 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexRawDataParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java @@ -10,31 +10,25 @@ import java.io.IOException; import java.io.Serializable; -@JsonDeserialize(using = HexRawDataParam.Deserializer.class) -public class HexRawDataParam implements Serializable { +@JsonDeserialize(using = HexDataParam.Deserializer.class) +public class HexDataParam implements Serializable { private static final long serialVersionUID = 1L; - private static final int HASH_BYTE_LENGTH = 148; - private final byte[] rawDataBytes; - public HexRawDataParam(String rawData){ + public HexDataParam(String rawData){ try { this.rawDataBytes = HexUtils.stringHexToByteArray(rawData); } catch (Exception e) { throw RskJsonRpcRequestException.invalidParamError("Invalid data format. " + e.getMessage()); } - - if (HASH_BYTE_LENGTH != rawDataBytes.length) { - throw RskJsonRpcRequestException.invalidParamError("Invalid data: incorrect length."); - } } public byte[] getRawDataBytes() { return rawDataBytes; } - public static class Deserializer extends StdDeserializer { + public static class Deserializer extends StdDeserializer { private static final long serialVersionUID = 1L; public Deserializer() { this(null); } @@ -42,9 +36,9 @@ public static class Deserializer extends StdDeserializer { public Deserializer(Class vc) { super(vc); } @Override - public HexRawDataParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + public HexDataParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { String hexRawData = jp.getText(); - return new HexRawDataParam(hexRawData); + return new HexDataParam(hexRawData); } } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexRawDataParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDataParamTest.java similarity index 71% rename from rskj-core/src/test/java/org/ethereum/rpc/parameters/HexRawDataParamTest.java rename to rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDataParamTest.java index cfb4fa494ee..a49070d5a8a 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexRawDataParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDataParamTest.java @@ -7,22 +7,20 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -public class HexRawDataParamTest { +public class HexDataParamTest { @Test - public void testValidHexRawDataParam() { + public void testValidHexDataParam() { String validHexRawData = "0xf892038609184e72a0008276c094e7b8e91401bf4d1669f54dc5f98109d7efbc4eea849184e72aa9d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f07244567565a0ea179f22ab9149013f3330a0921cef8fc8fddc84f3e51746ef8d5a35e04bfd8ba020e5640606a3257f32b9ef2f706c7294666d4bf759093769d40e7fdd2ac2f49e"; - HexRawDataParam hexRawDataParam = new HexRawDataParam(validHexRawData); + HexDataParam hexDataParam = new HexDataParam(validHexRawData); - assertEquals(validHexRawData, HexUtils.toUnformattedJsonHex(hexRawDataParam.getRawDataBytes())); + assertEquals(validHexRawData, HexUtils.toUnformattedJsonHex(hexDataParam.getRawDataBytes())); } @Test - public void testInvalidHexRawDataParam() { + public void testInvalidHexDataParam() { String invalidHexRawData = "0xsv92038609184e72a0008276c094e7b8e91401bf4d1669f54dc5f98109d7efbc4eea849184e72aa9d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f07244567565a0ea179f22ab9149013f3330a0921cef8fc8fddc84f3e51746ef8d5a35e04bfd8ba020e5640606a3257f32b9ef2f706c7294666d4bf759093769d40e7fdd2ac2f49e"; - String shorterHexRawData = "0xf892038609184e72a00082"; - assertThrows(RskJsonRpcRequestException.class, () -> new HexRawDataParam(invalidHexRawData)); - assertThrows(RskJsonRpcRequestException.class, () -> new HexRawDataParam(shorterHexRawData)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexDataParam(invalidHexRawData)); } } From 9e04a89ddb45673bc052dec94b4d55a0963a7d82 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Wed, 30 Aug 2023 14:46:07 -0400 Subject: [PATCH 10/47] Add BlockRef and BlockRefParam classes --- .../main/java/org/ethereum/rpc/BlockRef.java | 24 ++++++ .../rpc/parameters/BlockRefParam.java | 76 +++++++++++++++++++ .../rpc/parameters/BlockRefParamTest.java | 68 +++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/BlockRef.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java diff --git a/rskj-core/src/main/java/org/ethereum/rpc/BlockRef.java b/rskj-core/src/main/java/org/ethereum/rpc/BlockRef.java new file mode 100644 index 00000000000..302d1e7c0d6 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/BlockRef.java @@ -0,0 +1,24 @@ +package org.ethereum.rpc; + +import java.util.Map; + +public class BlockRef { + private String identifier; + private Map inputs; + + public BlockRef(String identifier) { + this.identifier = identifier; + } + + public BlockRef(Map inputs) { + this.inputs = inputs; + } + + public String getIdentifier() { + return identifier; + } + + public Map getInputs() { + return inputs; + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java new file mode 100644 index 00000000000..e7912bdb2ad --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java @@ -0,0 +1,76 @@ +package org.ethereum.rpc.parameters; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.BlockRef; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.util.Utils; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +@JsonDeserialize(using = BlockRefParam.Deserializer.class) +public class BlockRefParam implements Serializable { + private static final long serialVersionUID = 1L; + + private static final List IDENTIFIERS = Arrays.asList("earliest", "latest", "pending"); + private static final List BLOCK_INPUT_KEYS = Arrays.asList("blockHash", "blockNumber"); + + private final String identifier; + private final Map inputs; + + public BlockRefParam(BlockRef blockRef) { + if(blockRef.getIdentifier() != null) { + validateString(blockRef.getIdentifier()); + } else { + validateMap(blockRef.getInputs()); + } + + this.identifier = blockRef.getIdentifier(); + this.inputs = blockRef.getInputs(); + } + + private void validateString(String identifier) { + if(!IDENTIFIERS.contains(identifier) + && !Utils.isDecimalString(identifier) + && !Utils.isHexadecimalString(identifier)) { + throw RskJsonRpcRequestException.invalidParamError("Invalid block identifier '" + identifier + "'"); + } + } + + private void validateMap(Map inputs) { + if(!inputs.containsKey(BLOCK_INPUT_KEYS.get(0)) + && !inputs.containsKey(BLOCK_INPUT_KEYS.get(1))) { + throw RskJsonRpcRequestException.invalidParamError("Invalid block input"); + } + } + + public String getIdentifier() { + return identifier; + } + + public Map getInputs() { + return inputs; + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + private final ObjectMapper mapper = new ObjectMapper(); + + public Deserializer() { this(null); } + + public Deserializer(Class vc) { super(vc); } + + @Override + public BlockRefParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + BlockRef blockRef = mapper.readValue(jp, BlockRef.class); + return new BlockRefParam(blockRef); + } + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java new file mode 100644 index 00000000000..e624de4a61d --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java @@ -0,0 +1,68 @@ +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.BlockRef; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class BlockRefParamTest { + @Test + public void testValidIdentifier() { + String identifier = "latest"; + BlockRef blockRef = new BlockRef(identifier); + + BlockRefParam blockRefParam = new BlockRefParam(blockRef); + + assertEquals(identifier, blockRefParam.getIdentifier()); + assertNull(blockRefParam.getInputs()); + } + + @Test + public void testValidInputs() { + Map inputs = new HashMap() { + { + put("blockHash", "0x0011223344556677880011223344556677889900"); + } + }; + BlockRef blockRef = new BlockRef(inputs); + + BlockRefParam blockRefParam = new BlockRefParam(blockRef); + + assertEquals(inputs, blockRefParam.getInputs()); + assertNull(blockRefParam.getIdentifier()); + } + + @Test + public void testInvalidIdentifierString() { + String invalidStringIdentifier = "first"; + BlockRef blockRef = new BlockRef(invalidStringIdentifier); + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(blockRef)); + } + + @Test + public void testInvalidIdentifierHexString() { + String invalidStringIdentifier = "0x1aw"; + BlockRef blockRef = new BlockRef(invalidStringIdentifier); + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(blockRef)); + } + + @Test + public void testInvalidInputsInvalidKey() { + Map inputs = new HashMap() { + { + put("invalidKey", "0x0011223344556677880011223344556677889900"); + } + }; + BlockRef blockRef = new BlockRef(inputs); + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(blockRef)); + } +} From 63e7dd6b653232c6b0f59d106bcb51999a92ec77 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 31 Aug 2023 09:14:06 -0400 Subject: [PATCH 11/47] Refactor BlockRefParam --- .../java/org/ethereum/rpc/parameters/BlockRefParam.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java index e7912bdb2ad..ac970f5080d 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java @@ -19,8 +19,8 @@ public class BlockRefParam implements Serializable { private static final long serialVersionUID = 1L; - private static final List IDENTIFIERS = Arrays.asList("earliest", "latest", "pending"); - private static final List BLOCK_INPUT_KEYS = Arrays.asList("blockHash", "blockNumber"); + private static final List IDENTIFIERS_TO_VALIDATE = Arrays.asList("earliest", "latest", "pending"); + private static final List BLOCK_INPUT_KEYS_TO_VALIDATE = Arrays.asList("blockHash", "blockNumber"); private final String identifier; private final Map inputs; @@ -37,7 +37,7 @@ public BlockRefParam(BlockRef blockRef) { } private void validateString(String identifier) { - if(!IDENTIFIERS.contains(identifier) + if(!IDENTIFIERS_TO_VALIDATE.contains(identifier) && !Utils.isDecimalString(identifier) && !Utils.isHexadecimalString(identifier)) { throw RskJsonRpcRequestException.invalidParamError("Invalid block identifier '" + identifier + "'"); @@ -45,8 +45,7 @@ private void validateString(String identifier) { } private void validateMap(Map inputs) { - if(!inputs.containsKey(BLOCK_INPUT_KEYS.get(0)) - && !inputs.containsKey(BLOCK_INPUT_KEYS.get(1))) { + if(inputs.keySet().stream().noneMatch(BLOCK_INPUT_KEYS_TO_VALIDATE::contains)) { throw RskJsonRpcRequestException.invalidParamError("Invalid block input"); } } From 85c2fe0475b692ada242d523359800c1b9430cf2 Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Thu, 31 Aug 2023 00:49:49 +0200 Subject: [PATCH 12/47] Adding new Parameter classes --- .../rpc/parameters/FilterRequestParam.java | 124 ++++++++++++++++++ .../rpc/parameters/TopicArrayParam.java | 39 ++++++ .../ethereum/rpc/parameters/TopicParam.java | 26 ++++ .../parameters/FilterRequestParamTest.java | 107 +++++++++++++++ 4 files changed, 296 insertions(+) create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicArrayParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicParam.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java new file mode 100644 index 00000000000..8d8c61f623a --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java @@ -0,0 +1,124 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.ethereum.rpc.parameters; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +import java.io.IOException; + +@JsonDeserialize(using = FilterRequestParam.Deserializer.class) +public class FilterRequestParam { + + @JsonProperty + private final BlockIdentifierParam fromBlock; + @JsonProperty + private final BlockIdentifierParam toBlock; + @JsonProperty + private final HexAddressParam address; + @JsonProperty + private final TopicArrayParam[] topics; + @JsonProperty + private final BlockHashParam blockHash; + + public FilterRequestParam(BlockIdentifierParam fromBlock, BlockIdentifierParam toBlock, HexAddressParam address, TopicArrayParam[] topics, BlockHashParam blockHash) { + this.fromBlock = fromBlock; + this.toBlock = toBlock; + this.address = address; + this.topics = topics; + this.blockHash = blockHash; + } + + public BlockIdentifierParam getFromBlock() { + return fromBlock; + } + + public BlockIdentifierParam getToBlock() { + return toBlock; + } + + public HexAddressParam getAddress() { + return address; + } + + public TopicArrayParam[] getTopics() { + return topics; + } + + public BlockHashParam getBlockHash() { + return blockHash; + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = -72304400913233552L; + + public Deserializer() { + this(null); + } + + public Deserializer(Class vc) { + super(vc); + } + + @Override + public FilterRequestParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + JsonNode node = jp.getCodec().readTree(jp); + BlockIdentifierParam fromBlock = node.has("fromBlock") ? new BlockIdentifierParam(node.get("fromBlock").asText()) : null; + BlockIdentifierParam toBlock = node.has("toBlock") ? new BlockIdentifierParam(node.get("toBlock").asText()) : null; + HexAddressParam address = node.has("address") ? new HexAddressParam(node.get("address").asText()) : null; + BlockHashParam blockHash = node.has("blockHash") ? new BlockHashParam(node.get("blockHash").asText()) : null; + TopicArrayParam[] topics = node.has("topics") ? getTopicsArray(node.get("topics")) : null; + + return new FilterRequestParam(fromBlock, toBlock, address, topics, blockHash); + } + + private TopicArrayParam[] getTopicsArray(JsonNode node) { + if (node == null || node.isNull()) { + return new TopicArrayParam[0]; + } + if (node.isArray()) { + TopicArrayParam[] topics = new TopicArrayParam[node.size()]; + for (int i = 0; i < node.size(); i++) { + JsonNode subNode = node.get(i); + if (subNode.isArray()) { + TopicParam[] topicParams = getTopics(subNode); + topics[i] = new TopicArrayParam(topicParams); + } else { + topics[i] = new TopicArrayParam(new TopicParam(subNode.asText())); + } + } + return topics; + } + TopicParam topicParam = new TopicParam(node.asText()); + return new TopicArrayParam[]{new TopicArrayParam(topicParam)}; + } + + private TopicParam[] getTopics(JsonNode jsonNode) { + TopicParam[] topicParams = new TopicParam[jsonNode.size()]; + for (int j = 0; j < jsonNode.size(); j++) { + topicParams[j] = new TopicParam(jsonNode.get(j).asText()); + } + return topicParams; + } + } + +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicArrayParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicArrayParam.java new file mode 100644 index 00000000000..cc16e258db0 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicArrayParam.java @@ -0,0 +1,39 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.ethereum.rpc.parameters; + +public class TopicArrayParam { + private TopicParam[] topics; + + public TopicArrayParam() { + this.topics = new TopicParam[0]; + } + + public TopicArrayParam(TopicParam topic) { + this.topics = new TopicParam[]{topic}; + } + + public TopicArrayParam(TopicParam[] topics) { + this.topics = topics.clone(); + } + + public TopicParam[] getTopics() { + return topics.clone(); + } + +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicParam.java new file mode 100644 index 00000000000..e8213462655 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicParam.java @@ -0,0 +1,26 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.ethereum.rpc.parameters; + +public class TopicParam extends HashParam32 { + private static final String HASH_TYPE = "topic"; + + TopicParam(String hash) { + super(HASH_TYPE, hash); + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java new file mode 100644 index 00000000000..09b5e5f3b6e --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java @@ -0,0 +1,107 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.ethereum.rpc.parameters; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class FilterRequestParamTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + @Test + void validInput() throws JsonProcessingException { + String filterRequestInput = "{\n" + + " \"fromBlock\": \"0x1\"," + + " \"toBlock\" : \"0x2\"," + + " \"address\": \"0x7857288e171c6159c5576d1bd9ac40c0c48a771c\"," + + " \"topics\":[\"0x000000000000000000000000000000006d696e696e675f6665655f746f706963\"]," + + " \"blockHash\": \"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3\"}"; + JsonNode jsonNode = objectMapper.readTree(filterRequestInput); + FilterRequestParam filterRequestParam = objectMapper.convertValue(jsonNode, FilterRequestParam.class); + assertNotNull(filterRequestParam); + assertEquals("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", filterRequestParam.getBlockHash().getHash().toJsonString()); + assertEquals("0x1", filterRequestParam.getFromBlock().getIdentifier()); + assertEquals("0x2", filterRequestParam.getToBlock().getIdentifier()); + assertEquals("0x7857288e171c6159c5576d1bd9ac40c0c48a771c", filterRequestParam.getAddress().getAddress().toJsonString()); +// assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f706963", filterRequestParam.getTopics()[0].getHash().toJsonString()); + } + + @Test + void filterRequestParsesArrayOfTopic() throws JsonProcessingException { + String filterRequestInput = "{\n" + + " \"topics\":[\"0x000000000000000000000000000000006d696e696e675f6665655f746f706963\", " + + " [\"0x0000000000000000000000000000000000000000000000000000000000001111\",\"0x000000000000000000000000000000006d696e696e675f6665655f746f706963\"]]" + + "}"; + JsonNode jsonNode = objectMapper.readTree(filterRequestInput); + FilterRequestParam filterRequestParam = objectMapper.convertValue(jsonNode, FilterRequestParam.class); + assertNotNull(filterRequestParam); + TopicArrayParam[] topics = filterRequestParam.getTopics(); + assertEquals(2, topics.length); + TopicParam[] topicParam = topics[1].getTopics(); + assertEquals(2, topicParam.length); + } + + @Test + void invalidTopicFails() throws JsonProcessingException { + String filterRequestInput = "{\n" + + " \"topics\":[\"0x000000000000000000000000000000006d696e696e675f6665655f746f706963\", " + + " [\"0x0000000000000000000000000000000000000000000000000000000000001111\",\"0x0000w0000000000000000000000000006d696e696e675f6665655f746f706963\"]]" + + "}"; + JsonNode jsonNode = objectMapper.readTree(filterRequestInput); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, FilterRequestParam.class)); + } + + @Test + void filterRequestParsesSingleTopic() throws JsonProcessingException { + String filterRequestInput = "{\n" + + " \"topics\":\"0x000000000000000000000000000000006d696e696e675f6665655f746f706963\"" + + "}"; + JsonNode jsonNode = objectMapper.readTree(filterRequestInput); + FilterRequestParam filterRequestParam = objectMapper.convertValue(jsonNode, FilterRequestParam.class); + assertNotNull(filterRequestParam); + TopicArrayParam[] topics = filterRequestParam.getTopics(); + assertEquals(1, topics.length); + TopicParam[] topicParam = topics[0].getTopics(); + assertEquals(1, topicParam.length); + assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f706963", topicParam[0].getHash().toJsonString()); + } + + @Test + void invalidFromBlockFails() throws JsonProcessingException { + String filterRequestInput = "{\"fromBlock\" : \"0x2w\"}"; + JsonNode jsonNode = objectMapper.readTree(filterRequestInput); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, FilterRequestParam.class)); + } + + @Test + void invalidToBlockFails() throws JsonProcessingException { + String filterRequestInput = "{\"toBlock\" : \"ab\"}"; + JsonNode jsonNode = objectMapper.readTree(filterRequestInput); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, FilterRequestParam.class)); + } + + + +} \ No newline at end of file From acbde9e49d0ec3b1c72aff80c45723859ba7310f Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 31 Aug 2023 10:51:58 -0400 Subject: [PATCH 13/47] Refactor BlockRefParam deserialize to check for the param's type --- .../org/ethereum/rpc/parameters/BlockRefParam.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java index ac970f5080d..df583fc65da 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java @@ -68,7 +68,17 @@ public static class Deserializer extends StdDeserializer { @Override public BlockRefParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - BlockRef blockRef = mapper.readValue(jp, BlockRef.class); + Object objectParam = mapper.readValue(jp, Object.class); + BlockRef blockRef; + + if(objectParam instanceof String) { + blockRef = new BlockRef(objectParam.toString()); + } else if (objectParam instanceof Map) { + blockRef = new BlockRef((Map) objectParam); + } else { + throw RskJsonRpcRequestException.invalidParamError("Invalid input"); + } + return new BlockRefParam(blockRef); } } From 8c5affe537a62e8a402804eec250458b94c032ca Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Thu, 31 Aug 2023 19:17:21 +0200 Subject: [PATCH 14/47] Updating eth_newFilter method with FilterRequestParam --- .../main/java/co/rsk/rpc/Web3EthModule.java | 3 +- .../main/java/org/ethereum/rpc/Web3Impl.java | 10 ++- .../rpc/parameters/FilterRequestParam.java | 63 +++++++++++--- .../rpc/parameters/TopicArrayParam.java | 39 --------- .../ethereum/rpc/parameters/TopicParam.java | 2 +- .../org/ethereum/rpc/Web3ImplLogsTest.java | 84 +++++++++---------- .../parameters/FilterRequestParamTest.java | 44 ++++++++-- 7 files changed, 139 insertions(+), 106 deletions(-) delete mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicArrayParam.java diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index dbe9b123a70..bcdc71042be 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -26,6 +26,7 @@ import org.ethereum.rpc.dto.TransactionReceiptDTO; import org.ethereum.rpc.dto.TransactionResultDTO; import org.ethereum.rpc.parameters.BlockHashParam; +import org.ethereum.rpc.parameters.FilterRequestParam; import org.ethereum.rpc.parameters.HexIndexParam; import org.ethereum.rpc.parameters.TxHashParam; @@ -135,7 +136,7 @@ default String eth_sendTransaction(CallArguments args) { Map eth_compileSolidity(String contract); - String eth_newFilter(FilterRequest fr) throws Exception; + String eth_newFilter(FilterRequestParam fr) throws Exception; String eth_newBlockFilter(); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index 92fc8e519c3..13bfd815c52 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -60,6 +60,7 @@ import org.ethereum.rpc.dto.TransactionReceiptDTO; import org.ethereum.rpc.dto.TransactionResultDTO; import org.ethereum.rpc.parameters.BlockHashParam; +import org.ethereum.rpc.parameters.FilterRequestParam; import org.ethereum.rpc.parameters.HexIndexParam; import org.ethereum.rpc.parameters.TxHashParam; import org.ethereum.util.BuildInfo; @@ -880,7 +881,11 @@ public Map eth_compileSolidity(String contract) { } @Override - public String eth_newFilter(FilterRequest fr) throws Exception { + public String eth_newFilter(FilterRequestParam filterRequestParam) throws Exception { + return newFilter(filterRequestParam.toFilterRequest()); + } + + private String newFilter(FilterRequest fr){ String str = null; try { Filter filter = LogFilter.fromFilterRequest(fr, blockchain, blocksBloomStore, config.getRpcEthGetLogsMaxBlockToQuery(), config.getRpcEthGetLogsMaxLogsToReturn()); @@ -894,7 +899,6 @@ public String eth_newFilter(FilterRequest fr) throws Exception { } } } - @Override public String eth_newBlockFilter() { String s = null; @@ -990,7 +994,7 @@ private Object[] getFilterEvents(String id, boolean newevents) { @Override public Object[] eth_getLogs(FilterRequest fr) throws Exception { logger.debug("eth_getLogs ..."); - String id = eth_newFilter(fr); + String id = newFilter(fr); Object[] ret = eth_getFilterLogs(id); eth_uninstallFilter(id); return ret; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java index 8d8c61f623a..ff6353e6a48 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java @@ -23,8 +23,11 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.FilterRequest; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; @JsonDeserialize(using = FilterRequestParam.Deserializer.class) public class FilterRequestParam { @@ -35,12 +38,13 @@ public class FilterRequestParam { private final BlockIdentifierParam toBlock; @JsonProperty private final HexAddressParam address; - @JsonProperty - private final TopicArrayParam[] topics; +// @JsonProperty +// private final TopicArrayParam[] topics; + private final TopicParam[][] topics; @JsonProperty private final BlockHashParam blockHash; - public FilterRequestParam(BlockIdentifierParam fromBlock, BlockIdentifierParam toBlock, HexAddressParam address, TopicArrayParam[] topics, BlockHashParam blockHash) { + public FilterRequestParam(BlockIdentifierParam fromBlock, BlockIdentifierParam toBlock, HexAddressParam address, TopicParam[][] topics, BlockHashParam blockHash) { this.fromBlock = fromBlock; this.toBlock = toBlock; this.address = address; @@ -60,7 +64,7 @@ public HexAddressParam getAddress() { return address; } - public TopicArrayParam[] getTopics() { + public TopicParam[][] getTopics() { return topics; } @@ -68,6 +72,43 @@ public BlockHashParam getBlockHash() { return blockHash; } + public FilterRequest toFilterRequest() { + String fb = this.fromBlock == null ? null : this.fromBlock.getIdentifier(); + String tb = this.toBlock == null ? null : this.toBlock.getIdentifier(); + String ad = this.address == null ? null : this.address.getAddress().toJsonString(); + String bh = this.blockHash == null ? null : this.blockHash.getHash().toJsonString(); + Object[] tp = this.topics == null ? null : this.parseTopicArrayToObjectArray(); + + FilterRequest filterRequest = new FilterRequest(); + filterRequest.setAddress(ad); + filterRequest.setBlockHash(bh); + filterRequest.setFromBlock(fb); + filterRequest.setToBlock(tb); + filterRequest.setTopics(tp); + + return filterRequest; + } + + public Object[] parseTopicArrayToObjectArray() { + if (this.topics == null) { + return null; + } + Object[] result = new Object[this.topics.length]; + for (int i = 0; i < this.topics.length; i++) { + TopicParam[] topicArray = this.topics[i]; + if (topicArray.length == 1) { + result[i] = topicArray[0].getHash().toJsonString(); + } else { + List arrayList = new ArrayList<>(); + for (int j = 0; j < topicArray.length; j++) { + arrayList.add(topicArray[j].getHash().toJsonString()); + } + result[i] = arrayList; + } + } + return result; + } + public static class Deserializer extends StdDeserializer { private static final long serialVersionUID = -72304400913233552L; @@ -86,30 +127,30 @@ public FilterRequestParam deserialize(JsonParser jp, DeserializationContext ctxt BlockIdentifierParam toBlock = node.has("toBlock") ? new BlockIdentifierParam(node.get("toBlock").asText()) : null; HexAddressParam address = node.has("address") ? new HexAddressParam(node.get("address").asText()) : null; BlockHashParam blockHash = node.has("blockHash") ? new BlockHashParam(node.get("blockHash").asText()) : null; - TopicArrayParam[] topics = node.has("topics") ? getTopicsArray(node.get("topics")) : null; + TopicParam[][] topics = node.has("topics") ? getTopicArray(node.get("topics")) : null; return new FilterRequestParam(fromBlock, toBlock, address, topics, blockHash); } - private TopicArrayParam[] getTopicsArray(JsonNode node) { + private TopicParam[][] getTopicArray(JsonNode node) { if (node == null || node.isNull()) { - return new TopicArrayParam[0]; + return new TopicParam[0][0]; } if (node.isArray()) { - TopicArrayParam[] topics = new TopicArrayParam[node.size()]; + TopicParam[][] topics = new TopicParam[node.size()][]; for (int i = 0; i < node.size(); i++) { JsonNode subNode = node.get(i); if (subNode.isArray()) { TopicParam[] topicParams = getTopics(subNode); - topics[i] = new TopicArrayParam(topicParams); + topics[i] = topicParams; } else { - topics[i] = new TopicArrayParam(new TopicParam(subNode.asText())); + topics[i] = new TopicParam[]{new TopicParam(subNode.asText())}; } } return topics; } TopicParam topicParam = new TopicParam(node.asText()); - return new TopicArrayParam[]{new TopicArrayParam(topicParam)}; + return new TopicParam[][]{new TopicParam[]{topicParam}}; } private TopicParam[] getTopics(JsonNode jsonNode) { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicArrayParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicArrayParam.java deleted file mode 100644 index cc16e258db0..00000000000 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicArrayParam.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of RskJ - * Copyright (C) 2023 RSK Labs Ltd. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ -package org.ethereum.rpc.parameters; - -public class TopicArrayParam { - private TopicParam[] topics; - - public TopicArrayParam() { - this.topics = new TopicParam[0]; - } - - public TopicArrayParam(TopicParam topic) { - this.topics = new TopicParam[]{topic}; - } - - public TopicArrayParam(TopicParam[] topics) { - this.topics = topics.clone(); - } - - public TopicParam[] getTopics() { - return topics.clone(); - } - -} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicParam.java index e8213462655..1c643c97a78 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TopicParam.java @@ -20,7 +20,7 @@ public class TopicParam extends HashParam32 { private static final String HASH_TYPE = "topic"; - TopicParam(String hash) { + public TopicParam(String hash) { super(HASH_TYPE, hash); } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java index ca332119a26..e67546ea771 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java @@ -18,28 +18,6 @@ package org.ethereum.rpc; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; - -import java.math.BigInteger; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; - -import org.ethereum.core.*; -import org.ethereum.datasource.HashMapDB; -import org.ethereum.db.BlockStore; -import org.ethereum.db.ReceiptStore; -import org.ethereum.facade.Ethereum; -import org.ethereum.rpc.Simples.SimpleConfigCapabilities; -import org.ethereum.rpc.dto.TransactionReceiptDTO; -import org.ethereum.rpc.exception.RskJsonRpcRequestException; -import org.ethereum.util.ByteUtil; -import org.ethereum.util.RskTestFactory; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - import co.rsk.config.TestSystemProperties; import co.rsk.core.Coin; import co.rsk.core.Wallet; @@ -65,8 +43,33 @@ import co.rsk.test.builders.TransactionBuilder; import co.rsk.trie.TrieStore; import co.rsk.util.HexUtils; +import org.ethereum.core.*; +import org.ethereum.datasource.HashMapDB; +import org.ethereum.db.BlockStore; +import org.ethereum.db.ReceiptStore; +import org.ethereum.facade.Ethereum; +import org.ethereum.rpc.Simples.SimpleConfigCapabilities; +import org.ethereum.rpc.dto.TransactionReceiptDTO; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.FilterRequestParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.TopicParam; +import org.ethereum.util.ByteUtil; +import org.ethereum.util.RskTestFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import java.math.BigInteger; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; + /** * Created by ajlopez on 30/11/2016. */ @@ -138,8 +141,7 @@ void setUp() { @Test void newFilterInEmptyBlockchain() throws Exception { - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); String id = web3.eth_newFilter(fr); assertNotNull(id); @@ -147,8 +149,7 @@ void newFilterInEmptyBlockchain() throws Exception { @Test void newFilterGetLogsInEmptyBlockchain() throws Exception { - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); String id = web3.eth_newFilter(fr); Object[] logs = web3.eth_getFilterLogs(id); @@ -164,8 +165,7 @@ void newFilterGetLogsAfterBlock() throws Exception { repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("latest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("latest"), null,null,null,null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -207,9 +207,10 @@ void newFilterWithAccountAndTopicsCreatedAfterBlockAndGetLogs() throws Exception ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); - FilterRequest fr = new FilterRequest(); - fr.setAddress( ByteUtil.toHexString(tx.getContractAddress().getBytes())); - fr.setTopics(new Object[] { "06acbfb32bcf8383f3b0a768b70ac9ec234ea0f2d3b9c77fa6a2de69b919aad1" }); + HexAddressParam hexAddressParam = new HexAddressParam((tx.getContractAddress().toJsonString())); + TopicParam[][] topics = new TopicParam[][] { new TopicParam[] { new TopicParam("06acbfb32bcf8383f3b0a768b70ac9ec234ea0f2d3b9c77fa6a2de69b919aad1") } }; + FilterRequestParam fr = new FilterRequestParam(null, null,hexAddressParam,topics,null); + String id = web3.eth_newFilter(fr); Object[] logs = web3.eth_getFilterLogs(id); @@ -229,8 +230,7 @@ void newFilterGetLogsTwiceAfterBlock() throws Exception { web3.personal_newAccountWithSeed("notDefault"); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -256,8 +256,7 @@ void newFilterGetLogsTwiceAfterBlock() throws Exception { @Test void newFilterGetChangesInEmptyBlockchain() throws Exception { - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); String id = web3.eth_newFilter(fr); Object[] logs = web3.eth_getFilterChanges(id); @@ -274,8 +273,7 @@ void newFilterGetChangesAfterBlock() throws Exception { web3.personal_newAccountWithSeed("notDefault"); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -936,8 +934,7 @@ void createMainContractWithoutEvents() throws Exception { repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -965,8 +962,7 @@ void createCallerContractWithEvents() throws Exception { repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -1010,8 +1006,7 @@ void createCallerContractWithEventsOnInvoke() throws Exception { repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -1099,8 +1094,7 @@ void createCallerContractWithEventsOnInvokeUsingGetFilterLogs() throws Exception ).trieStore(trieStore).parent(block2).transactions(txs3).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block3)); - FilterRequest fr = new FilterRequest(); - fr.setAddress( "0x" + mainAddress); + FilterRequestParam fr = new FilterRequestParam(null, null,new HexAddressParam("0x" + mainAddress),null,null); String id = web3.eth_newFilter(fr); Object[] logs = web3.eth_getFilterLogs(id); diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java index 09b5e5f3b6e..cce9c9ed550 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java @@ -20,16 +20,21 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.ethereum.rpc.FilterRequest; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.Collection; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; class FilterRequestParamTest { private final ObjectMapper objectMapper = new ObjectMapper(); + @Test void validInput() throws JsonProcessingException { String filterRequestInput = "{\n" + @@ -45,7 +50,7 @@ void validInput() throws JsonProcessingException { assertEquals("0x1", filterRequestParam.getFromBlock().getIdentifier()); assertEquals("0x2", filterRequestParam.getToBlock().getIdentifier()); assertEquals("0x7857288e171c6159c5576d1bd9ac40c0c48a771c", filterRequestParam.getAddress().getAddress().toJsonString()); -// assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f706963", filterRequestParam.getTopics()[0].getHash().toJsonString()); + assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f706963", filterRequestParam.getTopics()[0][0].getHash().toJsonString()); } @Test @@ -57,10 +62,11 @@ void filterRequestParsesArrayOfTopic() throws JsonProcessingException { JsonNode jsonNode = objectMapper.readTree(filterRequestInput); FilterRequestParam filterRequestParam = objectMapper.convertValue(jsonNode, FilterRequestParam.class); assertNotNull(filterRequestParam); - TopicArrayParam[] topics = filterRequestParam.getTopics(); + TopicParam[][] topics = filterRequestParam.getTopics(); assertEquals(2, topics.length); - TopicParam[] topicParam = topics[1].getTopics(); + TopicParam[] topicParam = topics[1]; assertEquals(2, topicParam.length); + assertEquals("0x0000000000000000000000000000000000000000000000000000000000001111",topicParam[0].getHash().toJsonString()); } @Test @@ -81,9 +87,9 @@ void filterRequestParsesSingleTopic() throws JsonProcessingException { JsonNode jsonNode = objectMapper.readTree(filterRequestInput); FilterRequestParam filterRequestParam = objectMapper.convertValue(jsonNode, FilterRequestParam.class); assertNotNull(filterRequestParam); - TopicArrayParam[] topics = filterRequestParam.getTopics(); + TopicParam[][] topics = filterRequestParam.getTopics(); assertEquals(1, topics.length); - TopicParam[] topicParam = topics[0].getTopics(); + TopicParam[] topicParam = topics[0]; assertEquals(1, topicParam.length); assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f706963", topicParam[0].getHash().toJsonString()); } @@ -102,6 +108,32 @@ void invalidToBlockFails() throws JsonProcessingException { Assertions.assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, FilterRequestParam.class)); } + @Test + void toFilterRequestProducesValidObject() { + FilterRequestParam filterRequestParam = new FilterRequestParam( + new BlockIdentifierParam("0x1"), + new BlockIdentifierParam("0x2"), + new HexAddressParam("0x7857288e171c6159c5576d1bd9ac40c0c48a771c"), + new TopicParam[][]{ + new TopicParam[]{ + new TopicParam("0x000000000000000000000000000000006d696e696e675f6665655f746f706963"), + new TopicParam("0x000000000000000000000000000000006d696e696e675f6665655f746f711111") + }, + new TopicParam[]{ + new TopicParam("0x000000000000000000000000000000006d696e696e675f6665655f746f706963") + } + }, + new BlockHashParam("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")); + FilterRequest filterRequest = filterRequestParam.toFilterRequest(); + assertEquals("0x1", filterRequest.getFromBlock()); + assertEquals("0x2", filterRequest.getToBlock()); + assertEquals("0x7857288e171c6159c5576d1bd9ac40c0c48a771c", filterRequest.getAddress()); + assertEquals(2, filterRequest.getTopics().length); + assertTrue(filterRequest.getTopics()[0] instanceof Collection); + assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f711111", ((List) filterRequest.getTopics()[0]).get(1)); + assertTrue(filterRequest.getTopics()[1] instanceof String); + assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f706963", filterRequest.getTopics()[1]); + } } \ No newline at end of file From 27cc17df344cf25cbc6dc899cbf618420efa204b Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Thu, 31 Aug 2023 21:44:35 +0200 Subject: [PATCH 15/47] Updating eth_getLogs method with FilterRequestParam --- .../main/java/co/rsk/rpc/Web3EthModule.java | 3 +- .../main/java/org/ethereum/rpc/Web3Impl.java | 4 +- .../rpc/parameters/FilterRequestParam.java | 58 ++- .../org/ethereum/rpc/Web3ImplLogsTest.java | 412 ++++++++---------- .../parameters/FilterRequestParamTest.java | 6 +- 5 files changed, 235 insertions(+), 248 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index bcdc71042be..5360c12e5b2 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -20,7 +20,6 @@ import co.rsk.rpc.modules.eth.EthModule; import org.ethereum.rpc.CallArguments; -import org.ethereum.rpc.FilterRequest; import org.ethereum.rpc.dto.BlockResultDTO; import org.ethereum.rpc.dto.CompilationResultDTO; import org.ethereum.rpc.dto.TransactionReceiptDTO; @@ -148,7 +147,7 @@ default String eth_sendTransaction(CallArguments args) { Object[] eth_getFilterLogs(String id); - Object[] eth_getLogs(FilterRequest fr) throws Exception; + Object[] eth_getLogs(FilterRequestParam fr) throws Exception; BigInteger eth_netHashrate(); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index 13bfd815c52..e2c586762c5 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -992,9 +992,9 @@ private Object[] getFilterEvents(String id, boolean newevents) { } @Override - public Object[] eth_getLogs(FilterRequest fr) throws Exception { + public Object[] eth_getLogs(FilterRequestParam fr) throws Exception { logger.debug("eth_getLogs ..."); - String id = newFilter(fr); + String id = newFilter(fr.toFilterRequest()); Object[] ret = eth_getFilterLogs(id); eth_uninstallFilter(id); return ret; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java index ff6353e6a48..0d732021132 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java @@ -17,7 +17,6 @@ */ package org.ethereum.rpc.parameters; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; @@ -32,19 +31,13 @@ @JsonDeserialize(using = FilterRequestParam.Deserializer.class) public class FilterRequestParam { - @JsonProperty private final BlockIdentifierParam fromBlock; - @JsonProperty private final BlockIdentifierParam toBlock; - @JsonProperty - private final HexAddressParam address; -// @JsonProperty -// private final TopicArrayParam[] topics; + private final HexAddressParam[] address; private final TopicParam[][] topics; - @JsonProperty private final BlockHashParam blockHash; - public FilterRequestParam(BlockIdentifierParam fromBlock, BlockIdentifierParam toBlock, HexAddressParam address, TopicParam[][] topics, BlockHashParam blockHash) { + public FilterRequestParam(BlockIdentifierParam fromBlock, BlockIdentifierParam toBlock, HexAddressParam[] address, TopicParam[][] topics, BlockHashParam blockHash) { this.fromBlock = fromBlock; this.toBlock = toBlock; this.address = address; @@ -60,7 +53,7 @@ public BlockIdentifierParam getToBlock() { return toBlock; } - public HexAddressParam getAddress() { + public HexAddressParam[] getAddress() { return address; } @@ -75,7 +68,7 @@ public BlockHashParam getBlockHash() { public FilterRequest toFilterRequest() { String fb = this.fromBlock == null ? null : this.fromBlock.getIdentifier(); String tb = this.toBlock == null ? null : this.toBlock.getIdentifier(); - String ad = this.address == null ? null : this.address.getAddress().toJsonString(); + Object ad = this.address == null ? null : this.parseAddressArray(); String bh = this.blockHash == null ? null : this.blockHash.getHash().toJsonString(); Object[] tp = this.topics == null ? null : this.parseTopicArrayToObjectArray(); @@ -89,7 +82,22 @@ public FilterRequest toFilterRequest() { return filterRequest; } - public Object[] parseTopicArrayToObjectArray() { + private Object parseAddressArray() { + if (this.address == null) { + return null; + } + if (this.address.length == 1) { + return this.address[0].getAddress().toJsonString(); + } else { + List arrayList = new ArrayList<>(); + for (int i = 0; i < this.address.length; i++) { + arrayList.add(this.address[i].getAddress().toJsonString()); + } + return arrayList; + } + } + + private Object[] parseTopicArrayToObjectArray() { if (this.topics == null) { return null; } @@ -97,11 +105,15 @@ public Object[] parseTopicArrayToObjectArray() { for (int i = 0; i < this.topics.length; i++) { TopicParam[] topicArray = this.topics[i]; if (topicArray.length == 1) { - result[i] = topicArray[0].getHash().toJsonString(); + if (topicArray[0] != null) { + result[i] = topicArray[0].getHash().toJsonString(); + } } else { List arrayList = new ArrayList<>(); for (int j = 0; j < topicArray.length; j++) { - arrayList.add(topicArray[j].getHash().toJsonString()); + if (topicArray[j] != null) { + arrayList.add(topicArray[j].getHash().toJsonString()); + } } result[i] = arrayList; } @@ -125,13 +137,29 @@ public FilterRequestParam deserialize(JsonParser jp, DeserializationContext ctxt JsonNode node = jp.getCodec().readTree(jp); BlockIdentifierParam fromBlock = node.has("fromBlock") ? new BlockIdentifierParam(node.get("fromBlock").asText()) : null; BlockIdentifierParam toBlock = node.has("toBlock") ? new BlockIdentifierParam(node.get("toBlock").asText()) : null; - HexAddressParam address = node.has("address") ? new HexAddressParam(node.get("address").asText()) : null; + HexAddressParam[] address = node.has("address") ? getAddressParam(node.get("address")) : null; BlockHashParam blockHash = node.has("blockHash") ? new BlockHashParam(node.get("blockHash").asText()) : null; TopicParam[][] topics = node.has("topics") ? getTopicArray(node.get("topics")) : null; return new FilterRequestParam(fromBlock, toBlock, address, topics, blockHash); } + private HexAddressParam[] getAddressParam(JsonNode node) { + if (node == null || node.isNull()) { + return null; + } + + if (node.isArray()) { + HexAddressParam[] addresses = new HexAddressParam[node.size()]; + for (int i = 0; i < node.size(); i++) { + JsonNode subNode = node.get(i); + addresses[i] = new HexAddressParam(subNode.asText()); + } + return addresses; + } + return new HexAddressParam[]{new HexAddressParam(node.asText())}; + } + private TopicParam[][] getTopicArray(JsonNode node) { if (node == null || node.isNull()) { return new TopicParam[0][0]; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java index e67546ea771..aa59742bd93 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java @@ -51,10 +51,7 @@ import org.ethereum.rpc.Simples.SimpleConfigCapabilities; import org.ethereum.rpc.dto.TransactionReceiptDTO; import org.ethereum.rpc.exception.RskJsonRpcRequestException; -import org.ethereum.rpc.parameters.BlockIdentifierParam; -import org.ethereum.rpc.parameters.FilterRequestParam; -import org.ethereum.rpc.parameters.HexAddressParam; -import org.ethereum.rpc.parameters.TopicParam; +import org.ethereum.rpc.parameters.*; import org.ethereum.util.ByteUtil; import org.ethereum.util.RskTestFactory; import org.junit.jupiter.api.Assertions; @@ -109,7 +106,7 @@ class Web3ImplLogsTest { @TempDir public Path tempDir; private Blockchain blockChain; - private MiningMainchainView mainchainView; + private MiningMainchainView mainchainView; private RepositoryLocator repositoryLocator; private TransactionPool transactionPool; private Ethereum eth; @@ -141,7 +138,7 @@ void setUp() { @Test void newFilterInEmptyBlockchain() throws Exception { - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); assertNotNull(id); @@ -149,7 +146,7 @@ void newFilterInEmptyBlockchain() throws Exception { @Test void newFilterGetLogsInEmptyBlockchain() throws Exception { - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); Object[] logs = web3.eth_getFilterLogs(id); @@ -161,11 +158,11 @@ void newFilterGetLogsInEmptyBlockchain() throws Exception { @Test void newFilterGetLogsAfterBlock() throws Exception { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("latest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("latest"), null, null, null, null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -175,7 +172,7 @@ void newFilterGetLogsAfterBlock() throws Exception { List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); @@ -185,14 +182,14 @@ void newFilterGetLogsAfterBlock() throws Exception { assertNotNull(logs); assertEquals(1, logs.length); - assertEquals("0x" + tx.getContractAddress().toString(),((LogFilterElement)logs[0]).address); + assertEquals("0x" + tx.getContractAddress().toString(), ((LogFilterElement) logs[0]).address); } @Test void newFilterWithAccountAndTopicsCreatedAfterBlockAndGetLogs() throws Exception { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); @@ -203,13 +200,13 @@ void newFilterWithAccountAndTopicsCreatedAfterBlockAndGetLogs() throws Exception List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); - HexAddressParam hexAddressParam = new HexAddressParam((tx.getContractAddress().toJsonString())); - TopicParam[][] topics = new TopicParam[][] { new TopicParam[] { new TopicParam("06acbfb32bcf8383f3b0a768b70ac9ec234ea0f2d3b9c77fa6a2de69b919aad1") } }; - FilterRequestParam fr = new FilterRequestParam(null, null,hexAddressParam,topics,null); + HexAddressParam[] hexAddressParam = new HexAddressParam[]{new HexAddressParam((tx.getContractAddress().toJsonString()))}; + TopicParam[][] topics = initTopicsArray("06acbfb32bcf8383f3b0a768b70ac9ec234ea0f2d3b9c77fa6a2de69b919aad1"); + FilterRequestParam fr = new FilterRequestParam(null, null, hexAddressParam, topics, null); String id = web3.eth_newFilter(fr); @@ -219,18 +216,18 @@ void newFilterWithAccountAndTopicsCreatedAfterBlockAndGetLogs() throws Exception assertNotNull(logs); assertEquals(1, logs.length); - assertEquals("0x" + tx.getContractAddress().toString(),((LogFilterElement)logs[0]).address); + assertEquals("0x" + tx.getContractAddress().toString(), ((LogFilterElement) logs[0]).address); } @Test void newFilterGetLogsTwiceAfterBlock() throws Exception { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -240,7 +237,7 @@ void newFilterGetLogsTwiceAfterBlock() throws Exception { List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); @@ -251,12 +248,12 @@ void newFilterGetLogsTwiceAfterBlock() throws Exception { assertNotNull(logs); assertEquals(1, logs.length); - assertEquals("0x" + tx.getContractAddress().toString(),((LogFilterElement)logs[0]).address); + assertEquals("0x" + tx.getContractAddress().toString(), ((LogFilterElement) logs[0]).address); } @Test void newFilterGetChangesInEmptyBlockchain() throws Exception { - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); Object[] logs = web3.eth_getFilterChanges(id); @@ -268,12 +265,12 @@ void newFilterGetChangesInEmptyBlockchain() throws Exception { @Test void newFilterGetChangesAfterBlock() throws Exception { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -283,7 +280,7 @@ void newFilterGetChangesAfterBlock() throws Exception { List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); @@ -293,13 +290,12 @@ void newFilterGetChangesAfterBlock() throws Exception { assertNotNull(logs); assertEquals(1, logs.length); - assertEquals("0x" + tx.getContractAddress().toString(),((LogFilterElement)logs[0]).address); + assertEquals("0x" + tx.getContractAddress().toString(), ((LogFilterElement) logs[0]).address); } @Test void getLogsFromEmptyBlockchain() throws Exception { - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -310,8 +306,7 @@ void getLogsFromEmptyBlockchain() throws Exception { void getLogsFromBlockchainWithThreeEmptyBlocks() throws Exception { addTwoEmptyBlocks(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -322,8 +317,7 @@ void getLogsFromBlockchainWithThreeEmptyBlocks() throws Exception { void getLogsTwiceFromBlockchainWithThreeEmptyBlocks() throws Exception { addTwoEmptyBlocks(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -335,8 +329,7 @@ void getLogsTwiceFromBlockchainWithThreeEmptyBlocks() throws Exception { void getLogsFromBlockchainWithContractCreation() throws Exception { addContractCreationWithoutEvents(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -347,8 +340,8 @@ void getLogsFromBlockchainWithContractCreation() throws Exception { void getLogsTwiceFromBlockchainWithContractCreation() throws Exception { addContractCreationWithoutEvents(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); + web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -360,62 +353,60 @@ void getLogsTwiceFromBlockchainWithContractCreation() throws Exception { void getLogsFromBlockchainWithEventInContractCreation() throws Exception { addEventInContractCreation(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setToBlock("latest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), new BlockIdentifierParam("latest"), null, null, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); assertEquals(1, logs.length); - String txhash = ((LogFilterElement)logs[0]).transactionHash; + String txhash = ((LogFilterElement) logs[0]).transactionHash; TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); - assertEquals(txdto.getContractAddress(),((LogFilterElement)logs[0]).address); + assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); } @Test void getLogsTwiceFromBlockchainWithEventInContractCreation() throws Exception { addEventInContractCreation(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); + web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); assertEquals(1, logs.length); - String txhash = ((LogFilterElement)logs[0]).transactionHash; + String txhash = ((LogFilterElement) logs[0]).transactionHash; TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); - assertEquals(txdto.getContractAddress(),((LogFilterElement)logs[0]).address); + assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); } @Test void getLogsFromBlockchainWithInvokeContract() throws Exception { addContractInvoke(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); + Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); assertEquals(2, logs.length); - String txhash = ((LogFilterElement)logs[0]).transactionHash; + String txhash = ((LogFilterElement) logs[0]).transactionHash; TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); - assertEquals(txdto.getContractAddress(),((LogFilterElement)logs[0]).address); - assertEquals(txdto.getContractAddress(),((LogFilterElement)logs[1]).address); + assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); + assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[1]).address); } @Test void getLogsKeepsCorrectOrderForReverseSearch() throws Exception { List transactions = addContractInvokeManyTxPerBlock(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); + Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -464,27 +455,26 @@ void getLogsKeepsCorrectOrderForReverseSearch() throws Exception { void getLogsTwiceFromBlockchainWithInvokeContract() throws Exception { addContractInvoke(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); assertEquals(2, logs.length); - String txhash = ((LogFilterElement)logs[0]).transactionHash; + String txhash = ((LogFilterElement) logs[0]).transactionHash; TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); - assertEquals(txdto.getContractAddress(),((LogFilterElement)logs[0]).address); - assertEquals(txdto.getContractAddress(),((LogFilterElement)logs[1]).address); + assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); + assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[1]).address); } @Test void getLogsFromBlockchainWithCallContract() throws Exception { addContractCall(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); + Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -495,8 +485,8 @@ void getLogsFromBlockchainWithCallContract() throws Exception { void getLogsTwiceFromBlockchainWithCallContract() throws Exception { addContractCall(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); + web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -508,9 +498,8 @@ void getLogsTwiceFromBlockchainWithCallContract() throws Exception { void getLogsFromBlockchainWithCallContractAndFilterByContractAddress() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setAddress( ByteUtil.toHexString(block1.getTransactionsList().get(0).getContractAddress().getBytes())); + HexAddressParam[] addressParam = new HexAddressParam[]{new HexAddressParam(block1.getTransactionsList().get(0).getContractAddress().toJsonString())}; + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, addressParam, null, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -518,18 +507,20 @@ void getLogsFromBlockchainWithCallContractAndFilterByContractAddress() throws Ex String address = "0x" + fr.getAddress(); - assertEquals(address,((LogFilterElement)logs[0]).address); - assertEquals(address,((LogFilterElement)logs[1]).address); - assertEquals(address,((LogFilterElement)logs[2]).address); + assertEquals(address, ((LogFilterElement) logs[0]).address); + assertEquals(address, ((LogFilterElement) logs[1]).address); + assertEquals(address, ((LogFilterElement) logs[2]).address); } @Test void getLogsTwoceFromBlockchainWithCallContractAndFilterByContractAddress() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setAddress( ByteUtil.toHexString(block1.getTransactionsList().get(0).getContractAddress().getBytes())); + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + HexAddressParam[] hexAddressParam = new HexAddressParam[]{ + new HexAddressParam(block1.getTransactionsList().get(0).getContractAddress().toJsonString()) + }; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, hexAddressParam, null, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -538,20 +529,20 @@ void getLogsTwoceFromBlockchainWithCallContractAndFilterByContractAddress() thro String address = "0x" + fr.getAddress(); - assertEquals(address,((LogFilterElement)logs[0]).address); - assertEquals(address,((LogFilterElement)logs[1]).address); - assertEquals(address,((LogFilterElement)logs[2]).address); + assertEquals(address, ((LogFilterElement) logs[0]).address); + assertEquals(address, ((LogFilterElement) logs[1]).address); + assertEquals(address, ((LogFilterElement) logs[2]).address); } @Test void getLogsFromBlockchainWithCallContractAndFilterByUnknownContractAddress() throws Exception { addContractCall(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - List addresses = new ArrayList<>(); - addresses.add(ByteUtil.toHexString(new byte[20])); - fr.setAddress(addresses); + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + HexAddressParam[] hexAddressParam = new HexAddressParam[]{ + new HexAddressParam(ByteUtil.toHexString(new byte[20])) + }; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, hexAddressParam, null, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -562,11 +553,11 @@ void getLogsFromBlockchainWithCallContractAndFilterByUnknownContractAddress() th void getLogsTwiceFromBlockchainWithCallContractAndFilterByUnknownContractAddress() throws Exception { addContractCall(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - List addresses = new ArrayList<>(); - addresses.add(ByteUtil.toHexString(new byte[20])); - fr.setAddress(addresses); + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + HexAddressParam[] hexAddressParam = new HexAddressParam[]{ + new HexAddressParam(ByteUtil.toHexString(new byte[20])) + }; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, hexAddressParam, null, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -578,10 +569,9 @@ void getLogsTwiceFromBlockchainWithCallContractAndFilterByUnknownContractAddress void getLogsFromBlockchainWithCallContractAndFilterByUnknownTopic() throws Exception { addContractCall(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - fr.getTopics()[0] = "0102030405060102030405060102030405060102030405060102030405060102"; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = initTopicsArray("0102030405060102030405060102030405060102030405060102030405060102"); + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -592,10 +582,9 @@ void getLogsFromBlockchainWithCallContractAndFilterByUnknownTopic() throws Excep void getLogsTwiceFromBlockchainWithCallContractAndFilterByUnknownTopic() throws Exception { addContractCall(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - fr.getTopics()[0] = "0102030405060102030405060102030405060102030405060102030405060102"; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = initTopicsArray("0102030405060102030405060102030405060102030405060102030405060102"); + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -608,16 +597,15 @@ void getLogsFromBlockchainWithCallContractAndFilterByKnownTopic() throws Excepti addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - fr.getTopics()[0] = GET_VALUED_EVENT_SIGNATURE; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = initTopicsArray(GET_VALUED_EVENT_SIGNATURE); + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); String address = "0x" + ByteUtil.toHexString(block1.getTransactionsList().get(0).getContractAddress().getBytes()); assertEquals(1, logs.length); - assertEquals(address,((LogFilterElement)logs[0]).address); + assertEquals(address, ((LogFilterElement) logs[0]).address); } @Test @@ -625,67 +613,56 @@ void getLogsTwiceFromBlockchainWithCallContractAndFilterByKnownTopic() throws Ex addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - fr.getTopics()[0] = GET_VALUED_EVENT_SIGNATURE; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = initTopicsArray(GET_VALUED_EVENT_SIGNATURE); + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); String address = "0x" + ByteUtil.toHexString(block1.getTransactionsList().get(0).getContractAddress().getBytes()); assertEquals(1, logs.length); - assertEquals(address,((LogFilterElement)logs[0]).address); + assertEquals(address, ((LogFilterElement) logs[0]).address); } @Test void getLogsFromBlockchainWithCallContractAndFilterByKnownTopicInList() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - List topics = new ArrayList<>(); - topics.add(GET_VALUED_EVENT_SIGNATURE); - fr.getTopics()[0] = topics; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = initTopicsArray(GET_VALUED_EVENT_SIGNATURE); + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); String address = "0x" + ByteUtil.toHexString(block1.getTransactionsList().get(0).getContractAddress().getBytes()); assertEquals(1, logs.length); - assertEquals(address,((LogFilterElement)logs[0]).address); + assertEquals(address, ((LogFilterElement) logs[0]).address); } @Test void getLogsTwiceFromBlockchainWithCallContractAndFilterByKnownTopicInList() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - List topics = new ArrayList<>(); - topics.add(GET_VALUED_EVENT_SIGNATURE); - fr.getTopics()[0] = topics; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = initTopicsArray(GET_VALUED_EVENT_SIGNATURE); + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); String address = "0x" + ByteUtil.toHexString(block1.getTransactionsList().get(0).getContractAddress().getBytes()); assertEquals(1, logs.length); - assertEquals(address,((LogFilterElement)logs[0]).address); + assertEquals(address, ((LogFilterElement) logs[0]).address); } @Test void getLogsFromBlockchainWithCallContractAndFilterByKnownsTopicInList() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - List topics = new ArrayList<>(); - topics.add(GET_VALUED_EVENT_SIGNATURE); - topics.add(INC_EVENT_SIGNATURE); - fr.getTopics()[0] = topics; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{new TopicParam(GET_VALUED_EVENT_SIGNATURE),new TopicParam(INC_EVENT_SIGNATURE)}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -701,13 +678,9 @@ void getLogsFromBlockchainWithCallContractAndFilterByKnownsTopicInList() throws void getLogsTwiceFromBlockchainWithCallContractAndFilterByKnownsTopicInList() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - List topics = new ArrayList<>(); - topics.add(GET_VALUED_EVENT_SIGNATURE); - topics.add(INC_EVENT_SIGNATURE); - fr.getTopics()[0] = topics; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{new TopicParam(GET_VALUED_EVENT_SIGNATURE),new TopicParam(INC_EVENT_SIGNATURE)}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -724,45 +697,41 @@ void getLogsTwiceFromBlockchainWithCallContractAndFilterByKnownsTopicInList() th void getLogsFromBlockchainWithCallContractAndFilterByKnownTopicInListWithNull() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[2]); - fr.getTopics()[0] = GET_VALUED_EVENT_SIGNATURE; - fr.getTopics()[1] = null; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{new TopicParam(GET_VALUED_EVENT_SIGNATURE)},{null}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); String address = "0x" + ByteUtil.toHexString(block1.getTransactionsList().get(0).getContractAddress().getBytes()); assertEquals(1, logs.length); - assertEquals(address,((LogFilterElement)logs[0]).address); + assertEquals(address, ((LogFilterElement) logs[0]).address); } @Test void getLogsTwiceFromBlockchainWithCallContractAndFilterByKnownTopicInListWithNull() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[2]); - fr.getTopics()[0] = GET_VALUED_EVENT_SIGNATURE; - fr.getTopics()[1] = null; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{new TopicParam(GET_VALUED_EVENT_SIGNATURE)},{null}}; + + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); String address = "0x" + ByteUtil.toHexString(block1.getTransactionsList().get(0).getContractAddress().getBytes()); assertEquals(1, logs.length); - assertEquals(address,((LogFilterElement)logs[0]).address); + assertEquals(address, ((LogFilterElement) logs[0]).address); } @Test void getLogsFromBlockchainWithCallContractAndFilterWithNullTopic() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - fr.getTopics()[0] = null; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{null}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -778,10 +747,9 @@ void getLogsFromBlockchainWithCallContractAndFilterWithNullTopic() throws Except void getLogsTwiceFromBlockchainWithCallContractAndFilterWithNullTopic() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[1]); - fr.getTopics()[0] = null; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{null}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -798,11 +766,9 @@ void getLogsTwiceFromBlockchainWithCallContractAndFilterWithNullTopic() throws E void getLogsFromBlockchainWithCallContractAndFilterWithTwoTopics() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[2]); - fr.getTopics()[0] = INC_EVENT_SIGNATURE; - fr.getTopics()[1] = ONE_TOPIC; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{new TopicParam(INC_EVENT_SIGNATURE)},{new TopicParam(ONE_TOPIC)}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -818,11 +784,9 @@ void getLogsFromBlockchainWithCallContractAndFilterWithTwoTopics() throws Except void getLogsTwiceFromBlockchainWithCallContractAndFilterWithTwoTopics() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[2]); - fr.getTopics()[0] = INC_EVENT_SIGNATURE; - fr.getTopics()[1] = ONE_TOPIC; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{new TopicParam(INC_EVENT_SIGNATURE)},{new TopicParam(ONE_TOPIC)}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -839,11 +803,9 @@ void getLogsTwiceFromBlockchainWithCallContractAndFilterWithTwoTopics() throws E void getLogsFromBlockchainWithCallContractAndFilterBySecondTopic() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[2]); - fr.getTopics()[0] = null; - fr.getTopics()[1] = ONE_TOPIC; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{null},{new TopicParam(ONE_TOPIC)}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); @@ -859,11 +821,9 @@ void getLogsFromBlockchainWithCallContractAndFilterBySecondTopic() throws Except void getLogsTwiceFromBlockchainWithCallContractAndFilterBySecondTopic() throws Exception { addContractCall(); Block block1 = blockChain.getBlockByNumber(1l); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setTopics(new Object[2]); - fr.getTopics()[0] = null; - fr.getTopics()[1] = ONE_TOPIC; + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("earliest"); + TopicParam[][] topics = new TopicParam[][]{{null},{new TopicParam(ONE_TOPIC)}}; + FilterRequestParam fr = new FilterRequestParam(blockIdentifierParam, null, null, topics, null); web3.eth_getLogs(fr); Object[] logs = web3.eth_getLogs(fr); @@ -879,18 +839,17 @@ void getLogsTwiceFromBlockchainWithCallContractAndFilterBySecondTopic() throws E @Test void getLogsFromBlockchainWithEventInContractCreationReturnsAsExpectedWithBlockHashFilter() throws Exception { addEventInContractCreation(); - FilterRequest fr = new FilterRequest(); final String blockHash = TRACKED_TEST_BLOCK_HASH; - fr.setBlockHash(blockHash); + FilterRequestParam fr = new FilterRequestParam(null, null, null, null, new BlockHashParam(blockHash)); Object[] logs = web3.eth_getLogs(fr); assertNotNull(logs); assertEquals(1, logs.length); assertEquals(blockHash, ((LogFilterElement) logs[0]).blockHash); - String txhash = ((LogFilterElement)logs[0]).transactionHash; + String txhash = ((LogFilterElement) logs[0]).transactionHash; TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); - assertEquals(txdto.getContractAddress(),((LogFilterElement)logs[0]).address); + assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); } @Test @@ -898,8 +857,8 @@ void getLogsWithBlockHashFilterForNonexistentBlockThrowsException() throws Excep final String blockHash = UNTRACKED_TEST_BLOCK_HASH; byte[] blockHashBytes = new Keccak256(HexUtils.stringHexToByteArray(blockHash)).getBytes(); assertFalse(blockChain.hasBlockInSomeBlockchain(blockHashBytes)); - FilterRequest fr = new FilterRequest(); - fr.setBlockHash(blockHash); + FilterRequestParam fr = new FilterRequestParam(null, null, null, null, new BlockHashParam(blockHash)); + Object[] logs = web3.eth_getLogs(fr); @@ -910,19 +869,14 @@ void getLogsWithBlockHashFilterForNonexistentBlockThrowsException() throws Excep @Test void getLogsThrowsExceptionWhenBlockHashIsUsedCombinedWithFromBlock() { addEventInContractCreation(); - FilterRequest fr = new FilterRequest(); - fr.setFromBlock("earliest"); - fr.setBlockHash(TRACKED_TEST_BLOCK_HASH); - + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, new BlockHashParam(TRACKED_TEST_BLOCK_HASH)); Assertions.assertThrows(RskJsonRpcRequestException.class, () -> web3.eth_getLogs(fr)); } @Test void getLogsThrowsExceptionWhenBlockHashIsUsedCombinedWithToBlock() { addEventInContractCreation(); - FilterRequest fr = new FilterRequest(); - fr.setToBlock("latest"); - fr.setBlockHash(TRACKED_TEST_BLOCK_HASH); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("latest"), null, null, null, new BlockHashParam(TRACKED_TEST_BLOCK_HASH)); Assertions.assertThrows(RskJsonRpcRequestException.class, () -> web3.eth_getLogs(fr)); } @@ -930,11 +884,11 @@ void getLogsThrowsExceptionWhenBlockHashIsUsedCombinedWithToBlock() { @Test void createMainContractWithoutEvents() throws Exception { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -944,7 +898,7 @@ void createMainContractWithoutEvents() throws Exception { List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); @@ -958,11 +912,11 @@ void createMainContractWithoutEvents() throws Exception { @Test void createCallerContractWithEvents() throws Exception { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -972,7 +926,7 @@ void createCallerContractWithEvents() throws Exception { List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); @@ -985,7 +939,7 @@ void createCallerContractWithEvents() throws Exception { List txs2 = new ArrayList<>(); txs2.add(tx2); Block block2 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(block1).transactions(txs2).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block2)); @@ -995,18 +949,18 @@ void createCallerContractWithEvents() throws Exception { assertNotNull(logs); assertEquals(2, logs.length); - assertEquals("0x" + mainAddress, ((LogFilterElement)logs[0]).address); - assertEquals("0x" + callerAddress, ((LogFilterElement)logs[1]).address); + assertEquals("0x" + mainAddress, ((LogFilterElement) logs[0]).address); + assertEquals("0x" + callerAddress, ((LogFilterElement) logs[1]).address); } @Test void createCallerContractWithEventsOnInvoke() throws Exception { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); - FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null,null,null,null); + FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); Block genesis = blockChain.getBlockByNumber(0); @@ -1016,7 +970,7 @@ void createCallerContractWithEventsOnInvoke() throws Exception { List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); @@ -1029,7 +983,7 @@ void createCallerContractWithEventsOnInvoke() throws Exception { List txs2 = new ArrayList<>(); txs2.add(tx2); Block block2 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(block1).transactions(txs2).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block2)); @@ -1039,7 +993,7 @@ void createCallerContractWithEventsOnInvoke() throws Exception { List txs3 = new ArrayList<>(); txs3.add(tx3); Block block3 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(block2).transactions(txs3).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block3)); @@ -1049,16 +1003,16 @@ void createCallerContractWithEventsOnInvoke() throws Exception { assertNotNull(logs); assertEquals(3, logs.length); - assertEquals("0x" + mainAddress, ((LogFilterElement)logs[0]).address); - assertEquals("0x" + callerAddress, ((LogFilterElement)logs[1]).address); - assertEquals("0x" + mainAddress, ((LogFilterElement)logs[2]).address); + assertEquals("0x" + mainAddress, ((LogFilterElement) logs[0]).address); + assertEquals("0x" + callerAddress, ((LogFilterElement) logs[1]).address); + assertEquals("0x" + mainAddress, ((LogFilterElement) logs[2]).address); } @Test void createCallerContractWithEventsOnInvokeUsingGetFilterLogs() throws Exception { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); web3.personal_newAccountWithSeed("notDefault"); Block genesis = blockChain.getBlockByNumber(0); @@ -1068,7 +1022,7 @@ void createCallerContractWithEventsOnInvokeUsingGetFilterLogs() throws Exception List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); @@ -1080,7 +1034,7 @@ void createCallerContractWithEventsOnInvokeUsingGetFilterLogs() throws Exception List txs2 = new ArrayList<>(); txs2.add(tx2); Block block2 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(block1).transactions(txs2).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block2)); @@ -1090,11 +1044,12 @@ void createCallerContractWithEventsOnInvokeUsingGetFilterLogs() throws Exception List txs3 = new ArrayList<>(); txs3.add(tx3); Block block3 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(block2).transactions(txs3).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block3)); - FilterRequestParam fr = new FilterRequestParam(null, null,new HexAddressParam("0x" + mainAddress),null,null); + HexAddressParam[] address = new HexAddressParam[]{new HexAddressParam("0x" + mainAddress)}; + FilterRequestParam fr = new FilterRequestParam(null, null, address, null, null); String id = web3.eth_newFilter(fr); Object[] logs = web3.eth_getFilterLogs(id); @@ -1103,7 +1058,7 @@ void createCallerContractWithEventsOnInvokeUsingGetFilterLogs() throws Exception assertNotNull(logs); assertEquals(1, logs.length); - assertEquals("0x" + mainAddress, ((LogFilterElement)logs[0]).address); + assertEquals("0x" + mainAddress, ((LogFilterElement) logs[0]).address); } private Web3Impl createWeb3() { @@ -1153,11 +1108,11 @@ null, new EthModuleWalletEnabled(wallet), null, private void addTwoEmptyBlocks() { Block genesis = blockChain.getBlockByNumber(0); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); Block block2 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(block1).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block2)); assertEquals(3, blockChain.getSize()); @@ -1167,8 +1122,8 @@ private void addTwoEmptyBlocks() { private void addContractCreationWithoutEvents() { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); Block genesis = blockChain.getBlockByNumber(0); @@ -1195,7 +1150,7 @@ function greet(string param) onlyOwner constant returns (string) { List txs = new ArrayList<>(); txs.add(tx); Block block1 = new BlockBuilder(blockChain, null, - blockStore + blockStore ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); @@ -1213,7 +1168,7 @@ public static void addEmptyBlockToBlockchain( BlockStore blockStore, RepositoryLocator repositoryLocator, TrieStore trieStore) { - Account acc1 = new AccountBuilder(blockChain,blockStore,repositoryLocator) + Account acc1 = new AccountBuilder(blockChain, blockStore, repositoryLocator) .name("notDefault").balance(Coin.valueOf(10000000)).build(); Block genesis = blockChain.getBlockByNumber(0); @@ -1229,8 +1184,8 @@ public static void addEmptyBlockToBlockchain( private void addContractInvoke() { Account acc1 = new AccountBuilder(blockChain, - blockStore, - repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); + blockStore, + repositoryLocator).name("notDefault").balance(Coin.valueOf(10000000)).build(); Block genesis = blockChain.getBlockByNumber(0); Transaction tx; @@ -1335,14 +1290,14 @@ private void addContractCall() { } private static Transaction getContractTransaction(Account acc1) { - return getContractTransaction(acc1,false); + return getContractTransaction(acc1, false); } //0.4.11+commit.68ef5810.Emscripten.clang WITH optimizations static final String compiled_0_4_11 = "6060604052341561000c57fe5b5b60466000819055507f06acbfb32bcf8383f3b0a768b70ac9ec234ea0f2d3b9c77fa6a2de69b919aad16000546040518082815260200191505060405180910390a15b5b61014e8061005f6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632096525514610046578063371303c01461006c575bfe5b341561004e57fe5b61005661007e565b6040518082815260200191505060405180910390f35b341561007457fe5b61007c6100c2565b005b60007f1ee041944547858a75ebef916083b6d4f5ae04bea9cd809334469dd07dbf441b6000546040518082815260200191505060405180910390a160005490505b90565b60006000815460010191905081905550600160026000548115156100e257fe5b061415157f6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad6000546040518082815260200191505060405180910390a25b5600a165627a7a7230582092c7b2c0483b85227396e18149993b33243059af0f3bd0364f1dc36b8bbbcdae0029"; static final String compiled_unknown = "60606040526046600081905560609081527f06acbfb32bcf8383f3b0a768b70ac9ec234ea0f2d3b9c77fa6a2de69b919aad190602090a160aa8060426000396000f3606060405260e060020a60003504632096525581146024578063371303c0146060575b005b60a36000805460609081527f1ee041944547858a75ebef916083b6d4f5ae04bea9cd809334469dd07dbf441b90602090a1600060005054905090565b6022600080546001908101918290556060828152600290920614907f6e61ef44ac2747ff8b84d353a908eb8bd5c3fb118334d57698c5cfc7041196ad90602090a2565b5060206060f3"; - private static Transaction getContractTransaction(Account acc1,boolean withEvent) { + private static Transaction getContractTransaction(Account acc1, boolean withEvent) { /* contract compiled in data attribute of tx contract counter { event Incremented(bool indexed odd, uint x); @@ -1396,7 +1351,8 @@ private static Transaction getContractTransactionWithCall(Account acc1, byte[] r .build(); } - String compiledLogExample ="606060405234610000575b60bd806100186000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063195977a614603c575b6000565b34600057605460048080359060200190919050506056565b005b7ffd99bb34477b313b3e3b452b34d012d8315db36a1d63949d9d8f9d2573b05aff816040518082815260200191505060405180910390a15b505600a165627a7a72305820fb2550735b0655fb2fe03738be375a4c29ef1b6ff51004f869be19de0301f30b0029"; + String compiledLogExample = "606060405234610000575b60bd806100186000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063195977a614603c575b6000565b34600057605460048080359060200190919050506056565b005b7ffd99bb34477b313b3e3b452b34d012d8315db36a1d63949d9d8f9d2573b05aff816040518082815260200191505060405180910390a15b505600a165627a7a72305820fb2550735b0655fb2fe03738be375a4c29ef1b6ff51004f869be19de0301f30b0029"; + private Transaction getMainContractTransaction(Account acc1) { /* contract compiled in data attribute of tx contract main { @@ -1442,7 +1398,7 @@ function doSomething(address mainAddr) { .sender(acc1) .gasLimit(BigInteger.valueOf(1000000)) .gasPrice(BigInteger.ONE) - .data( compiledCaller + address) + .data(compiledCaller + address) .nonce(1) .build(); } @@ -1453,7 +1409,7 @@ private static Transaction getCallerContractTransactionWithInvoke(Account acc1, while (address.length() < 64) address = "0" + address; - CallTransaction.Function func = CallTransaction.Function.fromSignature("doSomething", new String[] { "address" }, new String[0]); + CallTransaction.Function func = CallTransaction.Function.fromSignature("doSomething", new String[]{"address"}, new String[0]); return new TransactionBuilder() .sender(acc1) @@ -1464,4 +1420,8 @@ private static Transaction getCallerContractTransactionWithInvoke(Account acc1, .nonce(2) .build(); } + + private TopicParam[][] initTopicsArray(String topic) { + return new TopicParam[][]{{new TopicParam(topic)}}; + } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java index cce9c9ed550..94ed7d5adb7 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java @@ -49,7 +49,7 @@ void validInput() throws JsonProcessingException { assertEquals("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", filterRequestParam.getBlockHash().getHash().toJsonString()); assertEquals("0x1", filterRequestParam.getFromBlock().getIdentifier()); assertEquals("0x2", filterRequestParam.getToBlock().getIdentifier()); - assertEquals("0x7857288e171c6159c5576d1bd9ac40c0c48a771c", filterRequestParam.getAddress().getAddress().toJsonString()); + assertEquals("0x7857288e171c6159c5576d1bd9ac40c0c48a771c", filterRequestParam.getAddress()[0].getAddress().toJsonString()); assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f706963", filterRequestParam.getTopics()[0][0].getHash().toJsonString()); } @@ -66,7 +66,7 @@ void filterRequestParsesArrayOfTopic() throws JsonProcessingException { assertEquals(2, topics.length); TopicParam[] topicParam = topics[1]; assertEquals(2, topicParam.length); - assertEquals("0x0000000000000000000000000000000000000000000000000000000000001111",topicParam[0].getHash().toJsonString()); + assertEquals("0x0000000000000000000000000000000000000000000000000000000000001111", topicParam[0].getHash().toJsonString()); } @Test @@ -113,7 +113,7 @@ void toFilterRequestProducesValidObject() { FilterRequestParam filterRequestParam = new FilterRequestParam( new BlockIdentifierParam("0x1"), new BlockIdentifierParam("0x2"), - new HexAddressParam("0x7857288e171c6159c5576d1bd9ac40c0c48a771c"), + new HexAddressParam[]{new HexAddressParam("0x7857288e171c6159c5576d1bd9ac40c0c48a771c")}, new TopicParam[][]{ new TopicParam[]{ new TopicParam("0x000000000000000000000000000000006d696e696e675f6665655f746f706963"), From 7a9a5d4dfeedfd7194caa1558e7b51784ef21248 Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Fri, 1 Sep 2023 01:43:29 +0200 Subject: [PATCH 16/47] Adding param validation to eth_unistallFilter, eth_getFilterChanges and eth_getFilterLogs. Fixing failing test from previous commit --- .../main/java/co/rsk/rpc/Web3EthModule.java | 6 ++-- .../main/java/org/ethereum/rpc/Web3Impl.java | 25 ++++++++--------- .../org/ethereum/rpc/Web3ImplLogsTest.java | 28 ++++++++++--------- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index 5360c12e5b2..605378b1153 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -141,11 +141,11 @@ default String eth_sendTransaction(CallArguments args) { String eth_newPendingTransactionFilter(); - boolean eth_uninstallFilter(String id); + boolean eth_uninstallFilter(HexIndexParam id); - Object[] eth_getFilterChanges(String id); + Object[] eth_getFilterChanges(HexIndexParam id); - Object[] eth_getFilterLogs(String id); + Object[] eth_getFilterLogs(HexIndexParam id); Object[] eth_getLogs(FilterRequestParam fr) throws Exception; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index e2c586762c5..7d90cc808d6 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -885,7 +885,7 @@ public String eth_newFilter(FilterRequestParam filterRequestParam) throws Except return newFilter(filterRequestParam.toFilterRequest()); } - private String newFilter(FilterRequest fr){ + private String newFilter(FilterRequest fr) { String str = null; try { Filter filter = LogFilter.fromFilterRequest(fr, blockchain, blocksBloomStore, config.getRpcEthGetLogsMaxBlockToQuery(), config.getRpcEthGetLogsMaxLogsToReturn()); @@ -899,6 +899,7 @@ private String newFilter(FilterRequest fr){ } } } + @Override public String eth_newBlockFilter() { String s = null; @@ -930,7 +931,7 @@ public String eth_newPendingTransactionFilter() { } @Override - public boolean eth_uninstallFilter(String id) { + public boolean eth_uninstallFilter(HexIndexParam id) { Boolean s = null; try { @@ -938,7 +939,7 @@ public boolean eth_uninstallFilter(String id) { return false; } - return filterManager.removeFilter(stringHexToBigInteger(id).intValue()); + return filterManager.removeFilter(id.getIndex()); } finally { if (logger.isDebugEnabled()) { logger.debug("eth_uninstallFilter({}): {}", id, s); @@ -947,7 +948,7 @@ public boolean eth_uninstallFilter(String id) { } @Override - public Object[] eth_getFilterChanges(String id) { + public Object[] eth_getFilterChanges(HexIndexParam id) { logger.debug("eth_getFilterChanges ..."); // TODO(mc): this is a quick solution that seems to work with OpenZeppelin tests, but needs to be reviewed @@ -960,7 +961,7 @@ public Object[] eth_getFilterChanges(String id) { Object[] s = null; try { - s = getFilterEvents(id, true); + s = this.filterManager.getFilterEvents(id.getIndex(), true); } finally { if (logger.isDebugEnabled()) { logger.debug("eth_getFilterChanges({}): {}", id, Arrays.toString(s)); @@ -971,13 +972,14 @@ public Object[] eth_getFilterChanges(String id) { } @Override - public Object[] eth_getFilterLogs(String id) { + public Object[] eth_getFilterLogs(HexIndexParam id) { logger.debug("eth_getFilterLogs ..."); Object[] s = null; try { - s = getFilterEvents(id, false); + s = this.filterManager.getFilterEvents(id.getIndex(), false); + } finally { if (logger.isDebugEnabled()) { logger.debug("eth_getFilterLogs({}): {}", id, Arrays.toString(s)); @@ -987,16 +989,13 @@ public Object[] eth_getFilterLogs(String id) { return s; } - private Object[] getFilterEvents(String id, boolean newevents) { - return this.filterManager.getFilterEvents(stringHexToBigInteger(id).intValue(), newevents); - } - @Override public Object[] eth_getLogs(FilterRequestParam fr) throws Exception { logger.debug("eth_getLogs ..."); String id = newFilter(fr.toFilterRequest()); - Object[] ret = eth_getFilterLogs(id); - eth_uninstallFilter(id); + HexIndexParam idParam = new HexIndexParam(id); + Object[] ret = eth_getFilterLogs(idParam); + eth_uninstallFilter(idParam); return ret; } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java index aa59742bd93..6544f79af21 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java @@ -148,7 +148,7 @@ void newFilterInEmptyBlockchain() throws Exception { void newFilterGetLogsInEmptyBlockchain() throws Exception { FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); - Object[] logs = web3.eth_getFilterLogs(id); + Object[] logs = web3.eth_getFilterLogs(new HexIndexParam(id)); assertNotNull(id); assertNotNull(logs); @@ -176,7 +176,7 @@ void newFilterGetLogsAfterBlock() throws Exception { ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); - Object[] logs = web3.eth_getFilterLogs(id); + Object[] logs = web3.eth_getFilterLogs(new HexIndexParam(id)); assertNotNull(id); assertNotNull(logs); @@ -210,7 +210,7 @@ void newFilterWithAccountAndTopicsCreatedAfterBlockAndGetLogs() throws Exception String id = web3.eth_newFilter(fr); - Object[] logs = web3.eth_getFilterLogs(id); + Object[] logs = web3.eth_getFilterLogs(new HexIndexParam(id)); assertNotNull(id); assertNotNull(logs); @@ -241,8 +241,9 @@ void newFilterGetLogsTwiceAfterBlock() throws Exception { ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); - web3.eth_getFilterLogs(id); - Object[] logs = web3.eth_getFilterLogs(id); + HexIndexParam idParam = new HexIndexParam(id); + web3.eth_getFilterLogs(idParam); + Object[] logs = web3.eth_getFilterLogs(idParam); assertNotNull(id); assertNotNull(logs); @@ -255,7 +256,8 @@ void newFilterGetLogsTwiceAfterBlock() throws Exception { void newFilterGetChangesInEmptyBlockchain() throws Exception { FilterRequestParam fr = new FilterRequestParam(new BlockIdentifierParam("earliest"), null, null, null, null); String id = web3.eth_newFilter(fr); - Object[] logs = web3.eth_getFilterChanges(id); + HexIndexParam hexIndexParam = new HexIndexParam(id); + Object[] logs = web3.eth_getFilterChanges(hexIndexParam); assertNotNull(id); assertNotNull(logs); @@ -284,7 +286,7 @@ void newFilterGetChangesAfterBlock() throws Exception { ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); - Object[] logs = web3.eth_getFilterChanges(id); + Object[] logs = web3.eth_getFilterChanges(new HexIndexParam(id)); assertNotNull(id); assertNotNull(logs); @@ -505,7 +507,7 @@ void getLogsFromBlockchainWithCallContractAndFilterByContractAddress() throws Ex assertNotNull(logs); assertEquals(3, logs.length); - String address = "0x" + fr.getAddress(); + String address = fr.getAddress()[0].getAddress().toJsonString(); assertEquals(address, ((LogFilterElement) logs[0]).address); assertEquals(address, ((LogFilterElement) logs[1]).address); @@ -527,7 +529,7 @@ void getLogsTwoceFromBlockchainWithCallContractAndFilterByContractAddress() thro assertNotNull(logs); assertEquals(3, logs.length); - String address = "0x" + fr.getAddress(); + String address = fr.getAddress()[0].getAddress().toJsonString(); assertEquals(address, ((LogFilterElement) logs[0]).address); assertEquals(address, ((LogFilterElement) logs[1]).address); @@ -902,7 +904,7 @@ void createMainContractWithoutEvents() throws Exception { ).trieStore(trieStore).parent(genesis).transactions(txs).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block1)); - Object[] logs = web3.eth_getFilterChanges(id); + Object[] logs = web3.eth_getFilterChanges(new HexIndexParam(id)); assertNotNull(id); assertNotNull(logs); @@ -943,7 +945,7 @@ void createCallerContractWithEvents() throws Exception { ).trieStore(trieStore).parent(block1).transactions(txs2).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block2)); - Object[] logs = web3.eth_getFilterChanges(id); + Object[] logs = web3.eth_getFilterChanges(new HexIndexParam(id)); assertNotNull(id); assertNotNull(logs); @@ -997,7 +999,7 @@ void createCallerContractWithEventsOnInvoke() throws Exception { ).trieStore(trieStore).parent(block2).transactions(txs3).build(); assertEquals(ImportResult.IMPORTED_BEST, blockChain.tryToConnect(block3)); - Object[] logs = web3.eth_getFilterChanges(id); + Object[] logs = web3.eth_getFilterChanges(new HexIndexParam(id)); assertNotNull(id); assertNotNull(logs); @@ -1052,7 +1054,7 @@ void createCallerContractWithEventsOnInvokeUsingGetFilterLogs() throws Exception FilterRequestParam fr = new FilterRequestParam(null, null, address, null, null); String id = web3.eth_newFilter(fr); - Object[] logs = web3.eth_getFilterLogs(id); + Object[] logs = web3.eth_getFilterLogs(new HexIndexParam(id)); assertNotNull(id); assertNotNull(logs); From eda346b8fc56c026169d9cabda62b81ecbef4fd9 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Mon, 4 Sep 2023 13:18:42 -0400 Subject: [PATCH 17/47] Refactor CallArgumentsParam and add HexNumberParam --- .../org/ethereum/core/genesis/BlockTag.java | 48 +++++ .../rpc/parameters/BlockIdentifierParam.java | 3 +- .../rpc/parameters/CallArgumentsParam.java | 138 ++++++++----- .../ethereum/rpc/parameters/HexDataParam.java | 5 + .../rpc/parameters/HexNumberParam.java | 50 +++++ .../parameters/BlockIdentifierParamTest.java | 3 +- .../parameters/CallArgumentsParamTest.java | 188 ++++++++++++------ .../rpc/parameters/HexNumberParamTest.java | 36 ++++ 8 files changed, 357 insertions(+), 114 deletions(-) create mode 100644 rskj-core/src/main/java/org/ethereum/core/genesis/BlockTag.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/HexNumberParamTest.java diff --git a/rskj-core/src/main/java/org/ethereum/core/genesis/BlockTag.java b/rskj-core/src/main/java/org/ethereum/core/genesis/BlockTag.java new file mode 100644 index 00000000000..84c92c5eda9 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/core/genesis/BlockTag.java @@ -0,0 +1,48 @@ +/* + * This file is part of RskJ + * Copyright (C) 2023 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.ethereum.core.genesis; + +import javax.annotation.Nullable; + +public enum BlockTag { + PENDING("pending"), LATEST("latest"), EARLIEST("earliest"), FINALIZED("finalized"), SAFE("safe"); + + private final String tag; + + BlockTag(String tag) { + this.tag = tag; + } + + @Nullable + public static BlockTag fromString(String text) { + for (BlockTag b : BlockTag.values()) { + if (b.tag.equalsIgnoreCase(text)) { + return b; + } + } + return null; + } + + public String getTag() { + return tag; + } + + public boolean tagEquals(String tagName) { + return tag.contentEquals(tagName); + } +} \ No newline at end of file diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java index b214a47df48..41eed228557 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.core.genesis.BlockTag; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.util.Utils; @@ -21,7 +22,7 @@ public class BlockIdentifierParam implements Serializable { private final String identifier; public BlockIdentifierParam(String identifier) { - if(!STRING_IDENTIFIERS.contains(identifier) + if(BlockTag.fromString(identifier) == null && !Utils.isDecimalString(identifier) && !Utils.isHexadecimalString(identifier)) { throw RskJsonRpcRequestException.invalidParamError("Invalid block identifier '" + identifier + "'"); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java index 1dc5f440e3f..cc378d70a43 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java @@ -1,79 +1,101 @@ package org.ethereum.rpc.parameters; -import co.rsk.util.HexUtils; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import org.ethereum.rpc.CallArguments; -import org.ethereum.rpc.exception.RskJsonRpcRequestException; import java.io.IOException; -import java.io.Serializable; -import java.math.BigInteger; @JsonDeserialize(using = CallArgumentsParam.Deserializer.class) -public class CallArgumentsParam implements Serializable { - private static final long serialVersionUID = 1L; - - private transient final CallArguments callArguments; - - public CallArgumentsParam(CallArguments callArguments) { - validateAddressProperty(callArguments.getFrom(), "from"); - validateAddressProperty(callArguments.getTo(), "to"); - validateNumberProperty(callArguments.getGas(), "gas"); - validateNumberProperty(callArguments.getGasPrice(), "gasPrice"); - validateNumberProperty(callArguments.getGasLimit(), "gasLimit"); - validateNumberProperty(callArguments.getNonce(), "nonce"); - validateNumberProperty(callArguments.getChainId(), "chainId"); - validateNumberProperty(callArguments.getValue(), "value"); - validateDataProperty(callArguments.getData()); - - this.callArguments = callArguments; +public class CallArgumentsParam { + + private final HexAddressParam from; + private final HexAddressParam to; + private final HexNumberParam gas; + private final HexNumberParam gasPrice; + private final HexNumberParam gasLimit; + private final HexNumberParam nonce; + private final HexNumberParam chainId; + private final HexNumberParam value; + private final HexDataParam data; + + public CallArgumentsParam(HexAddressParam from, HexAddressParam to, HexNumberParam gas, + HexNumberParam gasPrice, HexNumberParam gasLimit, HexNumberParam nonce, + HexNumberParam chainId, HexNumberParam value, HexDataParam data) { + this.from = from; + this.to = to; + this.gas = gas; + this.gasPrice = gasPrice; + this.gasLimit = gasLimit; + this.nonce = nonce; + this.chainId = chainId; + this.value = value; + this.data = data; } - public CallArguments getCallArguments() { - return callArguments; + public HexAddressParam getFrom() { + return from; } - private boolean isPropertyValidHex(String propertyValue) { - boolean hasPrefix = HexUtils.hasHexPrefix(propertyValue); - return HexUtils.isHex(propertyValue.toLowerCase(), hasPrefix ? 2 : 0); + public HexAddressParam getTo() { + return to; } - private void validateAddressProperty(String propertyValue, String propertyName) { - if (propertyValue == null) { - return; - } + public HexNumberParam getGas() { + return gas; + } - if (!isPropertyValidHex(propertyValue)) { - throw RskJsonRpcRequestException.invalidParamError("Invalid param " + propertyName + ": invalid character in hex input."); - } + public HexNumberParam getGasPrice() { + return gasPrice; } - private void validateNumberProperty(String propertyValue, String propertyName) { - if(propertyValue == null) { - return; - } + public HexNumberParam getGasLimit() { + return gasLimit; + } - if (!isPropertyValidHex(propertyValue)) { - try { - new BigInteger(propertyValue); - } catch(Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid param " + propertyName + ": value must be a valid hex or string number."); - } - } + public HexNumberParam getNonce() { + return nonce; } - private void validateDataProperty(String propertyValue) { - if(propertyValue == null) { - return; - } + public HexNumberParam getChainId() { + return chainId; + } - if(!isPropertyValidHex(propertyValue)) { - throw RskJsonRpcRequestException.invalidParamError("Invalid param data: invalid character in hex input."); - } + public HexNumberParam getValue() { + return value; + } + + public HexDataParam getData() { + return data; + } + + public CallArguments toCallArguments() { + String caFrom = this.from == null ? null : this.from.getAddress().toJsonString(); + String caTo = this.to == null ? null : this.to.getAddress().toJsonString(); + String caGas = this.gas == null ? null : this.gas.getHexNumber(); + String caGasPrice = this.gasPrice == null ? null : this.gasPrice.getHexNumber(); + String caGasLimit = this.gasLimit == null ? null : this.gasLimit.getHexNumber(); + String caNonce = this.nonce == null ? null : this.nonce.getHexNumber(); + String caChainId = this.chainId == null ? null : this.chainId.getHexNumber(); + String caValue = this.value == null ? null : this.value.getHexNumber(); + String caData = this.data == null ? null : this.data.getAsHexString(); + + CallArguments callArguments = new CallArguments(); + callArguments.setFrom(caFrom); + callArguments.setTo(caTo); + callArguments.setGas(caGas); + callArguments.setGasPrice(caGasPrice); + callArguments.setGasLimit(caGasLimit); + callArguments.setNonce(caNonce); + callArguments.setChainId(caChainId); + callArguments.setValue(caValue); + callArguments.setData(caData); + + return callArguments; } public static class Deserializer extends StdDeserializer { @@ -86,8 +108,18 @@ public static class Deserializer extends StdDeserializer { @Override public CallArgumentsParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - CallArguments callArguments = mapper.readValue(jp, CallArguments.class); - return new CallArgumentsParam(callArguments); + JsonNode node = jp.getCodec().readTree(jp); + HexAddressParam from = node.has("from") ? new HexAddressParam(node.get("from").asText()) : null; + HexAddressParam to = node.has("to") ? new HexAddressParam(node.get("to").asText()) : null; + HexNumberParam gas = node.has("gas") ? new HexNumberParam(node.get("gas").asText()) : null; + HexNumberParam gasPrice = node.has("gasPrice") ? new HexNumberParam(node.get("gasPrice").asText()) : null; + HexNumberParam gasLimit = node.has("gasLimit") ? new HexNumberParam(node.get("gasLimit").asText()) : null; + HexNumberParam nonce = node.has("nonce") ? new HexNumberParam(node.get("nonce").asText()) : null; + HexNumberParam chainId = node.has("chainId") ? new HexNumberParam(node.get("chainId").asText()) : null; + HexNumberParam value = node.has("value") ? new HexNumberParam(node.get("value").asText()) : null; + HexDataParam data = node.has("data") ? new HexDataParam(node.get("data").asText()) : null; + + return new CallArgumentsParam(from, to, gas, gasPrice, gasLimit, nonce, chainId, value, data); } } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java index e124e73564d..61696ede095 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.util.ByteUtil; import java.io.IOException; import java.io.Serializable; @@ -28,6 +29,10 @@ public byte[] getRawDataBytes() { return rawDataBytes; } + public String getAsHexString() { + return "0x" + ByteUtil.toHexString(rawDataBytes); + } + public static class Deserializer extends StdDeserializer { private static final long serialVersionUID = 1L; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java new file mode 100644 index 00000000000..d2e333f6ae8 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java @@ -0,0 +1,50 @@ +package org.ethereum.rpc.parameters; + +import co.rsk.util.HexUtils; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; + +import java.io.IOException; +import java.io.Serializable; +import java.math.BigInteger; + +@JsonDeserialize(using = HexNumberParam.Deserializer.class) +public class HexNumberParam implements Serializable { + private static final long serialVersionUID = 1L; + + private final String hexNumber; + + public HexNumberParam(String hexNumber) { + boolean hasPrefix = HexUtils.hasHexPrefix(hexNumber); + if (!HexUtils.isHex(hexNumber.toLowerCase(), hasPrefix ? 2 : 0)) { + try { + new BigInteger(hexNumber); + } catch(Exception e) { + throw RskJsonRpcRequestException.invalidParamError("Invalid param " + hexNumber + ": value must be a valid hex or string number."); + } + } + + this.hexNumber = hexNumber; + } + + public String getHexNumber() { + return this.hexNumber; + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public Deserializer() { this(null); } + + public Deserializer(Class vc) { super(vc); } + + @Override + public HexNumberParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String hexNumber = jp.getText(); + return new HexNumberParam(hexNumber); + } + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java index 31c8ccc1305..95abb2014cd 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java @@ -1,5 +1,6 @@ package org.ethereum.rpc.parameters; +import org.ethereum.core.genesis.BlockTag; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.junit.jupiter.api.Test; @@ -9,7 +10,7 @@ public class BlockIdentifierParamTest { @Test public void testValidStringBlockIdentifier() { - String validBlockIdentifier = "latest"; + String validBlockIdentifier = BlockTag.LATEST.getTag(); BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam(validBlockIdentifier); diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/CallArgumentsParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/CallArgumentsParamTest.java index 19d4027446a..599272d26aa 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/CallArgumentsParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/CallArgumentsParamTest.java @@ -1,105 +1,175 @@ package org.ethereum.rpc.parameters; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; public class CallArgumentsParamTest { - private CallArguments buildCallArguments() { - CallArguments callArguments = new CallArguments(); - - callArguments.setFrom("0x7986b3df570230288501eea3d890bd66948c9b79"); - callArguments.setTo("0xE7B8E91401bF4d1669f54Dc5f98109D7EfBC4EEa"); - callArguments.setGas("0x76c0"); - callArguments.setGasPrice("0x9184e72a000"); - callArguments.setValue("0x9184e72a"); - callArguments.setData("0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"); - callArguments.setNonce("0x1"); - callArguments.setChainId("0x539"); - - return callArguments; - } + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final String FROM = "0x7986b3df570230288501eea3d890bd66948c9b79"; + private final String TO = "0xe7b8e91401bf4d1669f54dc5f98109d7efbc4eea"; + private final String GAS = "0x76c0"; + private final String GAS_PRICE = "0x9184e72a000"; + private final String VALUE = "0x9184e72a"; + private final String DATA = "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"; + private final String NONCE = "0x1"; + private final String CHAIN_ID = "0x539"; @Test - public void testValidCallArgumentsParam() { - CallArguments validCallArguments = buildCallArguments(); - - CallArgumentsParam callArgumentsParam = new CallArgumentsParam(validCallArguments); - - assertEquals(validCallArguments.getFrom(), callArgumentsParam.getCallArguments().getFrom()); - assertEquals(validCallArguments.getTo(), callArgumentsParam.getCallArguments().getTo()); - assertEquals(validCallArguments.getGas(), callArgumentsParam.getCallArguments().getGas()); - assertEquals(validCallArguments.getGasPrice(), callArgumentsParam.getCallArguments().getGasPrice()); - assertEquals(validCallArguments.getValue(), callArgumentsParam.getCallArguments().getValue()); - assertEquals(validCallArguments.getData(), callArgumentsParam.getCallArguments().getData()); - assertEquals(validCallArguments.getNonce(), callArgumentsParam.getCallArguments().getNonce()); - assertEquals(validCallArguments.getChainId(), callArgumentsParam.getCallArguments().getChainId()); + public void testValidCallArgumentsParam() throws JsonProcessingException { + String callArgumentsInput = "{\n" + + " \"from\": \"" + FROM + "\"," + + " \"to\" : \"" + TO + "\"," + + " \"gas\": \"" + GAS + "\"," + + " \"gasPrice\":\"" + GAS_PRICE + "\"," + + " \"value\":\"" + VALUE + "\"," + + " \"data\": \"" + DATA + "\", " + + " \"nonce\": \"" + NONCE + "\", " + + " \"chainId\": \"" + CHAIN_ID + "\"}"; + + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); + CallArgumentsParam callArgumentsParam = objectMapper.convertValue(jsonNode, CallArgumentsParam.class); + + assertNotNull(callArgumentsParam); + + assertEquals(FROM, callArgumentsParam.getFrom().getAddress().toJsonString()); + assertEquals(TO, callArgumentsParam.getTo().getAddress().toJsonString()); + assertEquals(GAS, callArgumentsParam.getGas().getHexNumber()); + assertEquals(GAS_PRICE, callArgumentsParam.getGasPrice().getHexNumber()); + assertEquals(VALUE, callArgumentsParam.getValue().getHexNumber()); + assertEquals(DATA, callArgumentsParam.getData().getAsHexString()); + assertEquals(NONCE, callArgumentsParam.getNonce().getHexNumber()); + assertEquals(CHAIN_ID, callArgumentsParam.getChainId().getHexNumber()); } @Test - public void testInvalidFromInCallArgumentsParam() { - CallArguments invalidCallArguments = buildCallArguments(); - invalidCallArguments.setFrom("0x7986b3df570230288501eea3d890bd66948c9bzx"); + public void testInvalidFromInCallArgumentsParam() throws JsonProcessingException { + String from = "0x7986b3df570230288501eea3d890bd66948c9b7s"; - assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + String callArgumentsInput = "{\n" + + " \"from\": \"" + from + "\"}"; + + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); + + assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, CallArgumentsParam.class)); } @Test - public void testInvalidToInCallArgumentsParam() { - CallArguments invalidCallArguments = buildCallArguments(); - invalidCallArguments.setTo("0xE7B8E91401bF4d1669f54Dc5f98109D7EfBC4Eqw"); + public void testInvalidToInCallArgumentsParam() throws JsonProcessingException { + String to = "0xe7b8e91401bf4d1669f54dc5f98109d7efbc4esw"; + + String callArgumentsInput = "{\n" + + " \"to\": \"" + to + "\"}"; - assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); + + assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, CallArgumentsParam.class)); } @Test - public void testInvalidGasInCallArgumentsParam() { - CallArguments invalidCallArguments = buildCallArguments(); - invalidCallArguments.setGas("0x76cZ"); + public void testInvalidGasInCallArgumentsParam() throws JsonProcessingException { + String gas = "0x76cz"; + + String callArgumentsInput = "{\n" + + " \"gas\": \"" + gas + "\"}"; + + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); - assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, CallArgumentsParam.class)); } @Test - public void testInvalidGasPriceInCallArgumentsParam() { - CallArguments invalidCallArguments = buildCallArguments(); - invalidCallArguments.setGasPrice("12tb45"); + public void testInvalidGasPriceInCallArgumentsParam() throws JsonProcessingException { + String gasPrice = "0x9184e72a0zq"; + + String callArgumentsInput = "{\n" + + " \"gasPrice\": \"" + gasPrice + "\"}"; + + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); - assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, CallArgumentsParam.class)); } @Test - public void testInvalidValueInCallArgumentsParam() { - CallArguments invalidCallArguments = buildCallArguments(); - invalidCallArguments.setValue("0x9184e7gt"); + public void testInvalidValueInCallArgumentsParam() throws JsonProcessingException { + String value = "0x9184e7tq"; - assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + String callArgumentsInput = "{\n" + + " \"value\": \"" + value + "\"}"; + + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); + + assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, CallArgumentsParam.class)); } @Test - public void testInvalidDataInCallArgumentsParam() { - CallArguments invalidCallArguments = buildCallArguments(); - invalidCallArguments.setData("0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445phm"); + public void testInvalidDataInCallArgumentsParam() throws JsonProcessingException { + String data = "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f0724456pl"; + + String callArgumentsInput = "{\n" + + " \"data\": \"" + data + "\"}"; - assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); + + assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, CallArgumentsParam.class)); } @Test - public void testInvalidNonceInCallArgumentsParam() { - CallArguments invalidCallArguments = buildCallArguments(); - invalidCallArguments.setNonce("0xJ"); + public void testInvalidNonceInCallArgumentsParam() throws JsonProcessingException { + String nonce = "0xj"; + + String callArgumentsInput = "{\n" + + " \"nonce\": \"" + nonce + "\"}"; + + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); - assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, CallArgumentsParam.class)); } @Test - public void testInvalidChainIdInCallArgumentsParam() { - CallArguments invalidCallArguments = buildCallArguments(); - invalidCallArguments.setChainId("0xB2R"); + public void testInvalidChainIdInCallArgumentsParam() throws JsonProcessingException { + String chainId = "0xb2r"; - assertThrows(RskJsonRpcRequestException.class, () -> new CallArgumentsParam(invalidCallArguments)); + String callArgumentsInput = "{\n" + + " \"chainId\": \"" + chainId + "\"}"; + + JsonNode jsonNode = objectMapper.readTree(callArgumentsInput); + + assertThrows(RskJsonRpcRequestException.class, () -> objectMapper.convertValue(jsonNode, CallArgumentsParam.class)); + } + + @Test + public void testToCallArguments() { + CallArgumentsParam callArgumentsParam = new CallArgumentsParam( + new HexAddressParam(FROM), + new HexAddressParam(TO), + new HexNumberParam(GAS), + new HexNumberParam(GAS_PRICE), + null, + new HexNumberParam(NONCE), + new HexNumberParam(CHAIN_ID), + new HexNumberParam(VALUE), + new HexDataParam(DATA) + ); + + CallArguments callArguments = callArgumentsParam.toCallArguments(); + + assertEquals(FROM, callArguments.getFrom()); + assertEquals(TO, callArguments.getTo()); + assertEquals(GAS, callArguments.getGas()); + assertEquals(GAS_PRICE, callArguments.getGasPrice()); + assertEquals(NONCE, callArguments.getNonce()); + assertEquals(CHAIN_ID, callArguments.getChainId()); + assertEquals(VALUE, callArguments.getValue()); + assertEquals(DATA, callArguments.getData()); } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexNumberParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexNumberParamTest.java new file mode 100644 index 00000000000..f12bc6b4ad1 --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexNumberParamTest.java @@ -0,0 +1,36 @@ +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class HexNumberParamTest { + + @Test + public void testValidHexNumberParam() { + String validHexNumber = "0x76c0"; + HexNumberParam hexNumberParam = new HexNumberParam(validHexNumber); + + assertNotNull(hexNumberParam); + assertEquals(validHexNumber, hexNumberParam.getHexNumber()); + } + + @Test + public void testValidHexNumberParamAsStringNumber() { + String validStringNumber = "1500"; + HexNumberParam hexNumberParam = new HexNumberParam(validStringNumber); + + assertNotNull(hexNumberParam); + assertEquals(validStringNumber, hexNumberParam.getHexNumber()); + } + + @Test + public void testInvalidHexNumberParam() { + String invalidHexNumber = "0x76ty"; + + assertThrows(RskJsonRpcRequestException.class, () -> new HexNumberParam(invalidHexNumber)); + } +} From 5c00e1eec2c2677dd8ee0f7041379b09d05bd171 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Mon, 4 Sep 2023 15:12:10 -0400 Subject: [PATCH 18/47] Fix SonarCloud issues --- .../org/ethereum/core/genesis/BlockTag.java | 2 +- .../rpc/parameters/BlockIdentifierParam.java | 4 -- .../rpc/parameters/CallArgumentsParam.java | 67 +++++++++++++------ 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/core/genesis/BlockTag.java b/rskj-core/src/main/java/org/ethereum/core/genesis/BlockTag.java index 84c92c5eda9..eeda113bcf9 100644 --- a/rskj-core/src/main/java/org/ethereum/core/genesis/BlockTag.java +++ b/rskj-core/src/main/java/org/ethereum/core/genesis/BlockTag.java @@ -45,4 +45,4 @@ public String getTag() { public boolean tagEquals(String tagName) { return tag.contentEquals(tagName); } -} \ No newline at end of file +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java index 41eed228557..03fddeb0f7a 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java @@ -10,15 +10,11 @@ import java.io.IOException; import java.io.Serializable; -import java.util.Arrays; -import java.util.List; @JsonDeserialize(using = BlockIdentifierParam.Deserializer.class) public class BlockIdentifierParam implements Serializable { private static final long serialVersionUID = 1L; - private static final List STRING_IDENTIFIERS = Arrays.asList("earliest", "latest", "pending"); - private final String identifier; public BlockIdentifierParam(String identifier) { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java index cc378d70a43..d2b2d48a3ae 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java @@ -3,12 +3,12 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import org.ethereum.rpc.CallArguments; import java.io.IOException; +import java.util.Optional; @JsonDeserialize(using = CallArgumentsParam.Deserializer.class) public class CallArgumentsParam { @@ -74,15 +74,15 @@ public HexDataParam getData() { } public CallArguments toCallArguments() { - String caFrom = this.from == null ? null : this.from.getAddress().toJsonString(); - String caTo = this.to == null ? null : this.to.getAddress().toJsonString(); - String caGas = this.gas == null ? null : this.gas.getHexNumber(); - String caGasPrice = this.gasPrice == null ? null : this.gasPrice.getHexNumber(); - String caGasLimit = this.gasLimit == null ? null : this.gasLimit.getHexNumber(); - String caNonce = this.nonce == null ? null : this.nonce.getHexNumber(); - String caChainId = this.chainId == null ? null : this.chainId.getHexNumber(); - String caValue = this.value == null ? null : this.value.getHexNumber(); - String caData = this.data == null ? null : this.data.getAsHexString(); + String caFrom = Optional.ofNullable(this.from).map(prop -> prop.getAddress().toJsonString()).orElse(null); + String caTo = Optional.ofNullable(this.to).map(prop -> prop.getAddress().toJsonString()).orElse(null); + String caGas = Optional.ofNullable(this.gas).map(HexNumberParam::getHexNumber).orElse(null); + String caGasPrice = Optional.ofNullable(this.gasPrice).map(HexNumberParam::getHexNumber).orElse(null); + String caGasLimit = Optional.ofNullable(this.gasLimit).map(HexNumberParam::getHexNumber).orElse(null); + String caNonce = Optional.ofNullable(this.nonce).map(HexNumberParam::getHexNumber).orElse(null); + String caChainId = Optional.ofNullable(this.chainId).map(HexNumberParam::getHexNumber).orElse(null); + String caValue = Optional.ofNullable(this.value).map(HexNumberParam::getHexNumber).orElse(null); + String caData = Optional.ofNullable(this.data).map(HexDataParam::getAsHexString).orElse(null); CallArguments callArguments = new CallArguments(); callArguments.setFrom(caFrom); @@ -100,7 +100,6 @@ public CallArguments toCallArguments() { public static class Deserializer extends StdDeserializer { private static final long serialVersionUID = 1L; - private final ObjectMapper mapper = new ObjectMapper(); public Deserializer() { this(null); } @@ -109,15 +108,43 @@ public static class Deserializer extends StdDeserializer { @Override public CallArgumentsParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonNode node = jp.getCodec().readTree(jp); - HexAddressParam from = node.has("from") ? new HexAddressParam(node.get("from").asText()) : null; - HexAddressParam to = node.has("to") ? new HexAddressParam(node.get("to").asText()) : null; - HexNumberParam gas = node.has("gas") ? new HexNumberParam(node.get("gas").asText()) : null; - HexNumberParam gasPrice = node.has("gasPrice") ? new HexNumberParam(node.get("gasPrice").asText()) : null; - HexNumberParam gasLimit = node.has("gasLimit") ? new HexNumberParam(node.get("gasLimit").asText()) : null; - HexNumberParam nonce = node.has("nonce") ? new HexNumberParam(node.get("nonce").asText()) : null; - HexNumberParam chainId = node.has("chainId") ? new HexNumberParam(node.get("chainId").asText()) : null; - HexNumberParam value = node.has("value") ? new HexNumberParam(node.get("value").asText()) : null; - HexDataParam data = node.has("data") ? new HexDataParam(node.get("data").asText()) : null; + + HexAddressParam from = Optional.ofNullable(node).map(n -> n.get("from")) + .map(JsonNode::asText) + .map(HexAddressParam::new) + .orElse(null); + HexAddressParam to = Optional.ofNullable(node).map(n -> n.get("to")) + .map(JsonNode::asText) + .map(HexAddressParam::new) + .orElse(null); + HexNumberParam gas = Optional.ofNullable(node).map(n -> n.get("gas")) + .map(JsonNode::asText) + .map(HexNumberParam::new) + .orElse(null); + HexNumberParam gasPrice = Optional.ofNullable(node).map(n -> n.get("gasPrice")) + .map(JsonNode::asText) + .map(HexNumberParam::new) + .orElse(null); + HexNumberParam gasLimit = Optional.ofNullable(node).map(n -> n.get("gasLimit")) + .map(JsonNode::asText) + .map(HexNumberParam::new) + .orElse(null); + HexNumberParam nonce = Optional.ofNullable(node).map(n -> n.get("nonce")) + .map(JsonNode::asText) + .map(HexNumberParam::new) + .orElse(null); + HexNumberParam chainId = Optional.ofNullable(node).map(n -> n.get("chainId")) + .map(JsonNode::asText) + .map(HexNumberParam::new) + .orElse(null); + HexNumberParam value = Optional.ofNullable(node).map(n -> n.get("value")) + .map(JsonNode::asText) + .map(HexNumberParam::new) + .orElse(null); + HexDataParam data = Optional.ofNullable(node).map(n -> n.get("data")) + .map(JsonNode::asText) + .map(HexDataParam::new) + .orElse(null); return new CallArgumentsParam(from, to, gas, gasPrice, gasLimit, nonce, chainId, value, data); } From a0f9f5a598242b5e95373c84abebac5db7dfe532 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Tue, 5 Sep 2023 08:08:49 -0400 Subject: [PATCH 19/47] Code cleaning --- .../rpc/parameters/CallArgumentsParam.java | 66 ++++++++++++++----- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java index d2b2d48a3ae..14d9448cbc9 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java @@ -1,5 +1,6 @@ package org.ethereum.rpc.parameters; +import co.rsk.core.RskAddress; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; @@ -74,15 +75,35 @@ public HexDataParam getData() { } public CallArguments toCallArguments() { - String caFrom = Optional.ofNullable(this.from).map(prop -> prop.getAddress().toJsonString()).orElse(null); - String caTo = Optional.ofNullable(this.to).map(prop -> prop.getAddress().toJsonString()).orElse(null); - String caGas = Optional.ofNullable(this.gas).map(HexNumberParam::getHexNumber).orElse(null); - String caGasPrice = Optional.ofNullable(this.gasPrice).map(HexNumberParam::getHexNumber).orElse(null); - String caGasLimit = Optional.ofNullable(this.gasLimit).map(HexNumberParam::getHexNumber).orElse(null); - String caNonce = Optional.ofNullable(this.nonce).map(HexNumberParam::getHexNumber).orElse(null); - String caChainId = Optional.ofNullable(this.chainId).map(HexNumberParam::getHexNumber).orElse(null); - String caValue = Optional.ofNullable(this.value).map(HexNumberParam::getHexNumber).orElse(null); - String caData = Optional.ofNullable(this.data).map(HexDataParam::getAsHexString).orElse(null); + String caFrom = Optional.ofNullable(this.from) + .map(HexAddressParam::getAddress) + .map(RskAddress::toJsonString) + .orElse(null); + String caTo = Optional.ofNullable(this.to) + .map(HexAddressParam::getAddress) + .map(RskAddress::toJsonString) + .orElse(null); + String caGas = Optional.ofNullable(this.gas) + .map(HexNumberParam::getHexNumber) + .orElse(null); + String caGasPrice = Optional.ofNullable(this.gasPrice) + .map(HexNumberParam::getHexNumber) + .orElse(null); + String caGasLimit = Optional.ofNullable(this.gasLimit) + .map(HexNumberParam::getHexNumber) + .orElse(null); + String caNonce = Optional.ofNullable(this.nonce) + .map(HexNumberParam::getHexNumber) + .orElse(null); + String caChainId = Optional.ofNullable(this.chainId) + .map(HexNumberParam::getHexNumber) + .orElse(null); + String caValue = Optional.ofNullable(this.value) + .map(HexNumberParam::getHexNumber) + .orElse(null); + String caData = Optional.ofNullable(this.data) + .map(HexDataParam::getAsHexString) + .orElse(null); CallArguments callArguments = new CallArguments(); callArguments.setFrom(caFrom); @@ -109,39 +130,48 @@ public static class Deserializer extends StdDeserializer { public CallArgumentsParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonNode node = jp.getCodec().readTree(jp); - HexAddressParam from = Optional.ofNullable(node).map(n -> n.get("from")) + HexAddressParam from = Optional.ofNullable(node) + .map(n -> n.get("from")) .map(JsonNode::asText) .map(HexAddressParam::new) .orElse(null); - HexAddressParam to = Optional.ofNullable(node).map(n -> n.get("to")) + HexAddressParam to = Optional.ofNullable(node) + .map(n -> n.get("to")) .map(JsonNode::asText) .map(HexAddressParam::new) .orElse(null); - HexNumberParam gas = Optional.ofNullable(node).map(n -> n.get("gas")) + HexNumberParam gas = Optional.ofNullable(node) + .map(n -> n.get("gas")) .map(JsonNode::asText) .map(HexNumberParam::new) .orElse(null); - HexNumberParam gasPrice = Optional.ofNullable(node).map(n -> n.get("gasPrice")) + HexNumberParam gasPrice = Optional.ofNullable(node) + .map(n -> n.get("gasPrice")) .map(JsonNode::asText) .map(HexNumberParam::new) .orElse(null); - HexNumberParam gasLimit = Optional.ofNullable(node).map(n -> n.get("gasLimit")) + HexNumberParam gasLimit = Optional.ofNullable(node) + .map(n -> n.get("gasLimit")) .map(JsonNode::asText) .map(HexNumberParam::new) .orElse(null); - HexNumberParam nonce = Optional.ofNullable(node).map(n -> n.get("nonce")) + HexNumberParam nonce = Optional.ofNullable(node) + .map(n -> n.get("nonce")) .map(JsonNode::asText) .map(HexNumberParam::new) .orElse(null); - HexNumberParam chainId = Optional.ofNullable(node).map(n -> n.get("chainId")) + HexNumberParam chainId = Optional.ofNullable(node) + .map(n -> n.get("chainId")) .map(JsonNode::asText) .map(HexNumberParam::new) .orElse(null); - HexNumberParam value = Optional.ofNullable(node).map(n -> n.get("value")) + HexNumberParam value = Optional.ofNullable(node) + .map(n -> n.get("value")) .map(JsonNode::asText) .map(HexNumberParam::new) .orElse(null); - HexDataParam data = Optional.ofNullable(node).map(n -> n.get("data")) + HexDataParam data = Optional.ofNullable(node) + .map(n -> n.get("data")) .map(JsonNode::asText) .map(HexDataParam::new) .orElse(null); From 7bfa8ee6151f7727da267f4c7501a6bfe70ba8d3 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 7 Sep 2023 13:12:27 -0400 Subject: [PATCH 20/47] Add HexKeyParam and HexDurationParam classes --- .../rpc/parameters/HexDurationParam.java | 40 +++++++++++++++++ .../rpc/parameters/HexIndexParam.java | 8 ++-- .../ethereum/rpc/parameters/HexKeyParam.java | 45 +++++++++++++++++++ .../rpc/parameters/HexStringParam.java | 12 +++++ .../rpc/parameters/HexDurationParamTest.java | 28 ++++++++++++ .../rpc/parameters/HexKeyParamTest.java | 26 +++++++++++ 6 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java create mode 100644 rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java create mode 100644 rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java new file mode 100644 index 00000000000..350c02e5f24 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java @@ -0,0 +1,40 @@ +package org.ethereum.rpc.parameters; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +import java.io.IOException; +import java.io.Serializable; + +@JsonDeserialize(using = HexDurationParam.Deserializer.class) +public class HexDurationParam extends HexStringParam implements Serializable { + private static final long serialVersionUID = 1L; + + private final Long duration; + + public HexDurationParam(String hexDurationStr) { + validateHexString(hexDurationStr); + + this.duration = Long.parseLong(hexDurationStr.substring(2), 16); + } + + public Long getDuration() { + return duration; + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public Deserializer() { this(null); } + + public Deserializer(Class vc) { super(vc); } + + @Override + public HexDurationParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String hexDurationStr = jp.getText(); + return new HexDurationParam(hexDurationStr); + } + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java index 7f9bfdef205..f939aa0e95a 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -23,21 +23,19 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import org.ethereum.rpc.exception.RskJsonRpcRequestException; import java.io.IOException; import java.io.Serializable; @JsonDeserialize(using = HexIndexParam.Deserializer.class) -public class HexIndexParam implements Serializable { +public class HexIndexParam extends HexStringParam implements Serializable { private static final long serialVersionUID = 1L; private final Integer index; public HexIndexParam(String indexString) { - if (!HexUtils.hasHexPrefix(indexString) || !HexUtils.isHex(indexString,2)) { - throw RskJsonRpcRequestException.invalidParamError("Invalid argument \"" + indexString + "\": param should be a hex value string."); - } + validateHexString(indexString); + String preResult = HexUtils.removeHexPrefix(indexString); this.index = Integer.parseInt(preResult, 16); } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java new file mode 100644 index 00000000000..3a5e796a4cb --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java @@ -0,0 +1,45 @@ +package org.ethereum.rpc.parameters; + +import co.rsk.util.HexUtils; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; + +import java.io.IOException; +import java.io.Serializable; + +@JsonDeserialize(using = HexKeyParam.Deserializer.class) +public class HexKeyParam implements Serializable { + private static final long serialVersionUID = 1L; + + private final String hexKey; + + public HexKeyParam(String hexKey) { + boolean hasPrefix = HexUtils.hasHexPrefix(hexKey); + if (!HexUtils.isHex(hexKey.toLowerCase(), hasPrefix ? 2 : 0)) { + throw RskJsonRpcRequestException.invalidParamError("Invalid param " + hexKey + ": value must be a valid hex."); + } + + this.hexKey = hexKey; + } + + public String getHexKey() { + return hexKey; + } + + public static class Deserializer extends StdDeserializer { + private static final long serialVersionUID = 1L; + + public Deserializer() { this(null); } + + public Deserializer(Class vc) { super(vc); } + + @Override + public HexKeyParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String hexKey = jp.getText(); + return new HexKeyParam(hexKey); + } + } +} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java new file mode 100644 index 00000000000..5a97ffce711 --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java @@ -0,0 +1,12 @@ +package org.ethereum.rpc.parameters; + +import co.rsk.util.HexUtils; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; + +public class HexStringParam { + public void validateHexString(String hexString) { + if (!HexUtils.hasHexPrefix(hexString) || !HexUtils.isHex(hexString,2)) { + throw RskJsonRpcRequestException.invalidParamError("Invalid argument \"" + hexString + "\": param should be a hex value string."); + } + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java new file mode 100644 index 00000000000..a8dd9c66300 --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java @@ -0,0 +1,28 @@ +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class HexDurationParamTest { + @Test + void testValidHexDurationParam() { + String validHexValue = "0x1e"; + HexDurationParam hexDurationParam = new HexDurationParam(validHexValue); + + assertNotNull(hexDurationParam); + assertEquals(30, hexDurationParam.getDuration()); + } + + @Test + void testInvalidHexDurationParam() { + String invalidHexValue = "1e"; // Missing hex prefix + String nonNumericHexValue = "0x1t"; // Non-valid hex value + + assertThrows(RskJsonRpcRequestException.class, () -> new HexDurationParam(invalidHexValue)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexDurationParam(nonNumericHexValue)); + } +} diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java new file mode 100644 index 00000000000..c49a6f2dd8c --- /dev/null +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java @@ -0,0 +1,26 @@ +package org.ethereum.rpc.parameters; + +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class HexKeyParamTest { + @Test + void testValidHexKeyParam() { + String validHexValue = "0xcd3376bb711cb332ee3fb2ca04c6a8b9f70c316fcdf7a1f44ef4c7999483295e"; + HexKeyParam hexKeyParam = new HexKeyParam(validHexValue); + + assertNotNull(hexKeyParam); + assertEquals(validHexValue, hexKeyParam.getHexKey()); + } + + @Test + void testInvalidHexKeyParam() { + String invalidHexValue = "0xcd3376bb711cb332ee3fb2ca04c6a8b9f70c316fcdf7a1f44ef4c79994832zxt"; + + assertThrows(RskJsonRpcRequestException.class, () -> new HexKeyParam(invalidHexValue)); + } +} From e970d380effa2d60e9f1da5e0b33d0449094f79a Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 7 Sep 2023 15:30:27 -0400 Subject: [PATCH 21/47] Fix sonar issues --- .../java/org/ethereum/rpc/parameters/HexDurationParam.java | 2 +- .../main/java/org/ethereum/rpc/parameters/HexIndexParam.java | 2 +- .../main/java/org/ethereum/rpc/parameters/HexStringParam.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java index 350c02e5f24..1738dde55ad 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java @@ -15,7 +15,7 @@ public class HexDurationParam extends HexStringParam implements Serializable { private final Long duration; public HexDurationParam(String hexDurationStr) { - validateHexString(hexDurationStr); + super(hexDurationStr); this.duration = Long.parseLong(hexDurationStr.substring(2), 16); } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java index f939aa0e95a..e63ce64659e 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -34,7 +34,7 @@ public class HexIndexParam extends HexStringParam implements Serializable { private final Integer index; public HexIndexParam(String indexString) { - validateHexString(indexString); + super(indexString); String preResult = HexUtils.removeHexPrefix(indexString); this.index = Integer.parseInt(preResult, 16); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java index 5a97ffce711..ef3dcc4874a 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java @@ -3,8 +3,8 @@ import co.rsk.util.HexUtils; import org.ethereum.rpc.exception.RskJsonRpcRequestException; -public class HexStringParam { - public void validateHexString(String hexString) { +public abstract class HexStringParam { + HexStringParam(String hexString) { if (!HexUtils.hasHexPrefix(hexString) || !HexUtils.isHex(hexString,2)) { throw RskJsonRpcRequestException.invalidParamError("Invalid argument \"" + hexString + "\": param should be a hex value string."); } From 207d69a9be418e149a9d80c7ac5fc449f6f38067 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 7 Sep 2023 16:45:14 -0400 Subject: [PATCH 22/47] Remove Serializable implementation from HexStringParam child classes --- .../java/org/ethereum/rpc/parameters/HexDurationParam.java | 5 +---- .../main/java/org/ethereum/rpc/parameters/HexIndexParam.java | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java index 1738dde55ad..5f036b65b2d 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java @@ -6,12 +6,9 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; -import java.io.Serializable; @JsonDeserialize(using = HexDurationParam.Deserializer.class) -public class HexDurationParam extends HexStringParam implements Serializable { - private static final long serialVersionUID = 1L; - +public class HexDurationParam extends HexStringParam { private final Long duration; public HexDurationParam(String hexDurationStr) { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java index e63ce64659e..1f1aec99b7e 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -25,12 +25,9 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; -import java.io.Serializable; @JsonDeserialize(using = HexIndexParam.Deserializer.class) -public class HexIndexParam extends HexStringParam implements Serializable { - private static final long serialVersionUID = 1L; - +public class HexIndexParam extends HexStringParam { private final Integer index; public HexIndexParam(String indexString) { From 9104c173e725d9d18e53482be09b25f96fd561f6 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Fri, 8 Sep 2023 08:41:19 -0400 Subject: [PATCH 23/47] Fix failing tests --- .../test/java/org/ethereum/rpc/Web3ImplTest.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) 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 a436fe2352b..8b1ce0f081a 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -26,8 +26,6 @@ import co.rsk.core.bc.TransactionPoolImpl; import co.rsk.crypto.Keccak256; import co.rsk.db.RepositoryLocator; -import co.rsk.logfilter.BlocksBloomStore; -import co.rsk.metrics.HashRateCalculator; import co.rsk.mine.MinerClient; import co.rsk.mine.MinerServer; import co.rsk.net.BlockProcessor; @@ -44,17 +42,13 @@ import co.rsk.rpc.modules.eth.EthModule; import co.rsk.rpc.modules.eth.EthModuleTransactionBase; import co.rsk.rpc.modules.eth.EthModuleWalletEnabled; -import co.rsk.rpc.modules.evm.EvmModule; -import co.rsk.rpc.modules.mnr.MnrModule; import co.rsk.rpc.modules.personal.PersonalModule; import co.rsk.rpc.modules.personal.PersonalModuleWalletDisabled; import co.rsk.rpc.modules.personal.PersonalModuleWalletEnabled; import co.rsk.rpc.modules.rsk.RskModule; import co.rsk.rpc.modules.rsk.RskModuleImpl; -import co.rsk.rpc.modules.trace.TraceModule; import co.rsk.rpc.modules.txpool.TxPoolModule; import co.rsk.rpc.modules.txpool.TxPoolModuleImpl; -import co.rsk.scoring.PeerScoringManager; import co.rsk.test.World; import co.rsk.test.builders.AccountBuilder; import co.rsk.test.builders.BlockBuilder; @@ -2425,9 +2419,11 @@ void whenEthGetFilterChanges_throwFilterNotFoundException() { Web3RskImpl web3 = (Web3RskImpl) createWeb3(); + HexIndexParam hexIndexParam = new HexIndexParam("0x01"); + RskJsonRpcRequestException exception = Assertions.assertThrowsExactly( expectedException.getClass(), - () -> web3.eth_getFilterChanges("0x01"), + () -> web3.eth_getFilterChanges(hexIndexParam), "filter not found" ); @@ -2445,9 +2441,11 @@ void whenEthGetFilterLogs_throwFilterNotFoundException() { Web3RskImpl web3 = (Web3RskImpl) createWeb3(); + HexIndexParam hexIndexParam = new HexIndexParam("0x01"); + RskJsonRpcRequestException exception = Assertions.assertThrowsExactly( expectedException.getClass(), - () -> web3.eth_getFilterLogs("0x01"), + () -> web3.eth_getFilterLogs(hexIndexParam), "filter not found" ); From e6f9cc77b2c28aafc0adec5a3945b2f68e68ffa5 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 31 Aug 2023 10:57:34 -0400 Subject: [PATCH 24/47] Implement deserializers --- .../main/java/co/rsk/rpc/Web3EthModule.java | 27 ++++--- .../co/rsk/rpc/modules/eth/EthModule.java | 19 +++-- .../rpc/modules/eth/EthModuleTransaction.java | 7 +- .../modules/eth/EthModuleTransactionBase.java | 14 +++- .../eth/EthModuleTransactionDisabled.java | 3 +- .../eth/EthModuleTransactionInstant.java | 7 +- .../rsk/rpc/modules/eth/EthModuleWallet.java | 5 +- .../modules/eth/EthModuleWalletDisabled.java | 4 +- .../modules/eth/EthModuleWalletEnabled.java | 12 +-- .../main/java/org/ethereum/rpc/Web3Impl.java | 43 +++++++--- .../co/rsk/mine/TransactionModuleTest.java | 10 ++- .../rsk/rpc/modules/eth/EthModuleDSLTest.java | 6 +- .../eth/EthModuleGasEstimationDSLTest.java | 5 +- .../co/rsk/rpc/modules/eth/EthModuleTest.java | 19 +++-- .../org/ethereum/rpc/Web3ImplLogsTest.java | 39 +++++++-- .../java/org/ethereum/rpc/Web3ImplTest.java | 81 ++++++++++--------- .../org/ethereum/rpc/Web3ImplUnitTest.java | 12 +-- .../vm/program/NestedContractsTest.java | 10 ++- 18 files changed, 202 insertions(+), 121 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index 05374f348a4..f6e3fff7f16 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -26,6 +26,11 @@ import org.ethereum.rpc.dto.TransactionResultDTO; import org.ethereum.rpc.parameters.BlockHashParam; import org.ethereum.rpc.parameters.FilterRequestParam; +import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.BlockRefParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.rpc.parameters.HexIndexParam; import org.ethereum.rpc.parameters.TxHashParam; @@ -37,15 +42,15 @@ default String[] eth_accounts() { return getEthModule().accounts(); } - default String eth_sign(String addr, String data) { + default String eth_sign(HexAddressParam addr, HexDataParam data) { return getEthModule().sign(addr, data); } - default String eth_call(CallArguments args, String bnOrId) { + default String eth_call(CallArgumentsParam args, BlockIdentifierParam bnOrId) { return getEthModule().call(args, bnOrId); } - default String eth_estimateGas(CallArguments args) { + default String eth_estimateGas(CallArgumentsParam args) { return getEthModule().estimateGas(args); } @@ -75,19 +80,15 @@ default String eth_chainId() { String eth_call(CallArguments args, Map blockRef) throws Exception; // NOSONAR - String eth_getBalance(String address, String block) throws Exception; + String eth_getBalance(HexAddressParam address, BlockRefParam blockRefParam) throws Exception; - String eth_getBalance(String address) throws Exception; - - String eth_getBalance(String address, Map blockRef) throws Exception; // NOSONAR + String eth_getBalance(HexAddressParam address) throws Exception; String eth_getStorageAt(String address, String storageIdx, Map blockRef) throws Exception; // NOSONAR String eth_getStorageAt(String address, String storageIdx, String blockId) throws Exception; - String eth_getTransactionCount(String address, Map blockRef) throws Exception; // NOSONAR - - String eth_getTransactionCount(String address, String blockId) throws Exception ; + String eth_getTransactionCount(HexAddressParam address, BlockRefParam blockRefParam) throws Exception; String eth_getBlockTransactionCountByHash(BlockHashParam blockHash)throws Exception; @@ -103,11 +104,11 @@ default String eth_getCode(String address, String blockId) { String eth_getCode(String address, Map blockRef) throws Exception; // NOSONAR - default String eth_sendRawTransaction(String rawData) { + default String eth_sendRawTransaction(HexDataParam rawData) { return getEthModule().sendRawTransaction(rawData); } - default String eth_sendTransaction(CallArguments args) { + default String eth_sendTransaction(CallArgumentsParam args) { return getEthModule().sendTransaction(args); } @@ -121,7 +122,7 @@ default String eth_sendTransaction(CallArguments args) { TransactionResultDTO eth_getTransactionByBlockNumberAndIndex(String bnOrId, String index) throws Exception; - TransactionReceiptDTO eth_getTransactionReceipt(String transactionHash) throws Exception; + TransactionReceiptDTO eth_getTransactionReceipt(TxHashParam transactionHash) throws Exception; BlockResultDTO eth_getUncleByBlockHashAndIndex(BlockHashParam blockHash, HexIndexParam uncleIdx) throws Exception; diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java index 4b58b1540a6..e3fee59111a 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java @@ -38,6 +38,10 @@ import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.converters.CallArgumentsToByteArray; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.vm.GasCost; import org.ethereum.vm.PrecompiledContracts; import org.ethereum.vm.program.ProgramResult; @@ -120,10 +124,11 @@ public Map bridgeState() throws IOException, BlockStoreException return state.stateToMap(); } - public String call(CallArguments args, String bnOrId) { + public String call(CallArgumentsParam argsParam, BlockIdentifierParam bnOrId) { String hReturn = null; + CallArguments args = argsParam.getCallArguments(); try { - ExecutionBlockRetriever.Result result = executionBlockRetriever.retrieveExecutionBlock(bnOrId); + ExecutionBlockRetriever.Result result = executionBlockRetriever.retrieveExecutionBlock(bnOrId.getIdentifier()); Block block = result.getBlock(); Trie finalState = result.getFinalState(); ProgramResult res; @@ -150,11 +155,11 @@ public String call(CallArguments args, String bnOrId) { } } - public String estimateGas(CallArguments args) { + public String estimateGas(CallArgumentsParam args) { String estimation = null; Block bestBlock = blockchain.getBestBlock(); try { - CallArgumentsToByteArray hexArgs = new CallArgumentsToByteArray(args); + CallArgumentsToByteArray hexArgs = new CallArgumentsToByteArray(args.getCallArguments()); TransactionExecutor executor = reversibleTransactionExecutor.estimateGas( bestBlock, @@ -194,17 +199,17 @@ protected String internalEstimateGas(ProgramResult reversibleExecutionResult) { } @Override - public String sendTransaction(CallArguments args) { + public String sendTransaction(CallArgumentsParam args) { return ethModuleTransaction.sendTransaction(args); } @Override - public String sendRawTransaction(String rawData) { + public String sendRawTransaction(HexDataParam rawData) { return ethModuleTransaction.sendRawTransaction(rawData); } @Override - public String sign(String addr, String data) { + public String sign(HexAddressParam addr, HexDataParam data) { return ethModuleWallet.sign(addr, data); } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransaction.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransaction.java index f3c1ea1300b..d9357b05c19 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransaction.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransaction.java @@ -18,10 +18,11 @@ package co.rsk.rpc.modules.eth; -import org.ethereum.rpc.CallArguments; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexDataParam; public interface EthModuleTransaction { - String sendTransaction(CallArguments args); + String sendTransaction(CallArgumentsParam args); - String sendRawTransaction(String rawData); + String sendRawTransaction(HexDataParam rawData); } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionBase.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionBase.java index 6cc64af4c22..0bec326c0c8 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionBase.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionBase.java @@ -30,6 +30,8 @@ import org.ethereum.core.TransactionPoolAddResult; import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.util.TransactionArgumentsUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +39,6 @@ import co.rsk.core.RskAddress; import co.rsk.core.Wallet; import co.rsk.net.TransactionGateway; -import co.rsk.util.HexUtils; public class EthModuleTransactionBase implements EthModuleTransaction { @@ -56,7 +57,12 @@ public EthModuleTransactionBase(Constants constants, Wallet wallet, TransactionP } @Override - public synchronized String sendTransaction(CallArguments args) { + public synchronized String sendTransaction(CallArgumentsParam argsParam) { + CallArguments args = argsParam.getCallArguments(); + + if(args.getFrom() == null) { + throw invalidParamError("from is null"); + } Account senderAccount = this.wallet.getAccount(new RskAddress(args.getFrom())); @@ -97,10 +103,10 @@ public synchronized String sendTransaction(CallArguments args) { } @Override - public String sendRawTransaction(String rawData) { + public String sendRawTransaction(HexDataParam rawData) { String s = null; try { - Transaction tx = new ImmutableTransaction(HexUtils.stringHexToByteArray(rawData)); + Transaction tx = new ImmutableTransaction(rawData.getRawDataBytes()); if (null == tx.getGasLimit() || null == tx.getGasPrice() || null == tx.getValue()) { throw invalidParamError("Missing parameter, gasPrice, gas or value"); diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java index 0f1bee0cad6..180fa46ff0f 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java @@ -22,6 +22,7 @@ import org.ethereum.config.Constants; import org.ethereum.core.TransactionPool; import org.ethereum.rpc.CallArguments; +import org.ethereum.rpc.parameters.CallArgumentsParam; import static org.ethereum.rpc.exception.RskJsonRpcRequestException.invalidParamError; @@ -36,7 +37,7 @@ public EthModuleTransactionDisabled(Constants constants, TransactionPool transac } @Override - public String sendTransaction(CallArguments args) { // lgtm [java/non-sync-override] + public String sendTransaction(CallArgumentsParam args) { // lgtm [java/non-sync-override] LOGGER.debug("eth_sendTransaction({}): {}", args, null); throw invalidParamError("Local wallet is disabled in this node"); } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionInstant.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionInstant.java index ee879308874..f5b08ae5dfa 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionInstant.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionInstant.java @@ -27,8 +27,9 @@ import org.ethereum.core.Blockchain; import org.ethereum.core.TransactionPool; import org.ethereum.db.TransactionInfo; -import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.vm.program.ProgramResult; import co.rsk.core.Wallet; @@ -64,7 +65,7 @@ public EthModuleTransactionInstant( } @Override - public synchronized String sendTransaction(CallArguments args) { + public synchronized String sendTransaction(CallArgumentsParam args) { try { this.blockExecutor.setRegisterProgramResults(true); @@ -80,7 +81,7 @@ public synchronized String sendTransaction(CallArguments args) { } @Override - public String sendRawTransaction(String rawData) { + public String sendRawTransaction(HexDataParam rawData) { try { this.blockExecutor.setRegisterProgramResults(true); diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWallet.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWallet.java index aaf90d7ff35..eca121e7341 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWallet.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWallet.java @@ -18,9 +18,12 @@ package co.rsk.rpc.modules.eth; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDataParam; + public interface EthModuleWallet { String[] accounts(); - String sign(String addr, String data); + String sign(HexAddressParam addr, HexDataParam data); } \ No newline at end of file diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java index 4cf03242cd2..1d29f3899be 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java @@ -18,6 +18,8 @@ package co.rsk.rpc.modules.eth; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +39,7 @@ public String[] accounts() { } @Override - public String sign(String addr, String data) { + public String sign(HexAddressParam addr, HexDataParam data) { LOGGER.debug("eth_sign({}, {}): {}", addr, data, null); throw invalidParamError("Local wallet is disabled in this node"); } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java index 2341857377c..86e24e6511c 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java @@ -28,11 +28,12 @@ import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.crypto.signature.ECDSASignature; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.util.ByteUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import co.rsk.core.RskAddress; import co.rsk.core.Wallet; import co.rsk.util.HexUtils; @@ -47,15 +48,15 @@ public EthModuleWalletEnabled(Wallet wallet) { } @Override - public String sign(String addr, String data) { + public String sign(HexAddressParam addr, HexDataParam data) { String s = null; try { - Account account = this.wallet.getAccount(new RskAddress(addr)); + Account account = this.wallet.getAccount(addr.getAddress()); if (account == null) { throw invalidParamError("Account not found"); } - return s = this.sign(data, account.getEcKey()); + return s = this.sign(data.getRawDataBytes(), account.getEcKey()); } finally { LOGGER.debug("eth_sign({}, {}): {}", addr, data, s); } @@ -71,8 +72,7 @@ public String[] accounts() { } } - private String sign(String data, ECKey ecKey) { - byte[] dataHash = HexUtils.stringHexToByteArray(data); + private String sign(byte[] dataHash, ECKey ecKey) { // 0x19 = 25, length should be an ascii decimals, message - original String prefix = (char) 25 + "Ethereum Signed Message:\n" + dataHash.length; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index bd5fbd4a9e1..e84bd0f3033 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -61,6 +61,10 @@ import org.ethereum.rpc.dto.TransactionResultDTO; import org.ethereum.rpc.parameters.BlockHashParam; import org.ethereum.rpc.parameters.FilterRequestParam; +import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.BlockRefParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; import org.ethereum.rpc.parameters.HexIndexParam; import org.ethereum.rpc.parameters.TxHashParam; import org.ethereum.util.BuildInfo; @@ -401,7 +405,7 @@ public String eth_blockNumber() { @Override public String eth_call(CallArguments args, Map inputs) { - return invokeByBlockRef(inputs, blockNumber -> this.eth_call(args, blockNumber)); + return invokeByBlockRef(inputs, blockNumber -> this.eth_call(new CallArgumentsParam(args), new BlockIdentifierParam(blockNumber))); } @Override @@ -410,7 +414,15 @@ public String eth_getCode(String address, Map inputs) { } @Override - public String eth_getBalance(String address, String block) { + public String eth_getBalance(HexAddressParam address, BlockRefParam blockRefParam) { + if(blockRefParam.getIdentifier() != null) { + return this.eth_getBalance(address, blockRefParam.getIdentifier()); + } else { + return this.eth_getBalance(address, blockRefParam.getInputs()); + } + } + + private String eth_getBalance(HexAddressParam address, String block) { /* HEX String - an integer block number * String "earliest" for the earliest/genesis block * String "latest" - for the latest mined block @@ -419,14 +431,14 @@ public String eth_getBalance(String address, String block) { AccountInformationProvider accountInformationProvider = web3InformationRetriever.getInformationProvider(block); - RskAddress addr = new RskAddress(address); + RskAddress addr = address.getAddress(); Coin balance = accountInformationProvider.getBalance(addr); return toQuantityJsonHex(balance.asBigInteger()); } - @Override - public String eth_getBalance(String address, Map inputs) { + + private String eth_getBalance(HexAddressParam address, Map inputs) { return invokeByBlockRef(inputs, blockNumber -> this.eth_getBalance(address, blockNumber)); } @@ -440,7 +452,7 @@ private boolean isInMainChain(Block block) { } @Override - public String eth_getBalance(String address) { + public String eth_getBalance(HexAddressParam address) { return eth_getBalance(address, "latest"); } @@ -477,7 +489,15 @@ public String eth_getStorageAt(String address, String storageIdx, String blockId } @Override - public String eth_getTransactionCount(String address, Map inputs) { + public String eth_getTransactionCount(HexAddressParam address, BlockRefParam blockRefParam) { + if(blockRefParam.getIdentifier() != null) { + return this.eth_getTransactionCount(address, blockRefParam.getIdentifier()); + } else { + return this.eth_getTransactionCount(address, blockRefParam.getInputs()); + } + } + + private String eth_getTransactionCount(HexAddressParam address, Map inputs) { return invokeByBlockRef(inputs, blockNumber -> this.eth_getTransactionCount(address, blockNumber)); } @@ -511,11 +531,10 @@ private String toInvokeByBlockHash(String blockHash, boolean requireCanonical, F return toInvokeByBlockNumber.apply(toQuantityJsonHex(block.getNumber())); } - @Override - public String eth_getTransactionCount(String address, String blockId) { + private String eth_getTransactionCount(HexAddressParam address, String blockId) { String s = null; try { - RskAddress addr = new RskAddress(address); + RskAddress addr = address.getAddress(); AccountInformationProvider accountInformationProvider = web3InformationRetriever .getInformationProvider(blockId); BigInteger nonce = accountInformationProvider.getNonce(addr); @@ -777,10 +796,10 @@ public TransactionResultDTO eth_getTransactionByBlockNumberAndIndex(String bnOrI } @Override - public TransactionReceiptDTO eth_getTransactionReceipt(String transactionHash) { + public TransactionReceiptDTO eth_getTransactionReceipt(TxHashParam transactionHash) { logger.trace("eth_getTransactionReceipt({})", transactionHash); - byte[] hash = stringHexToByteArray(transactionHash); + byte[] hash = stringHexToByteArray(transactionHash.getHash().toHexString()); TransactionInfo txInfo = receiptStore.getInMainChain(hash, blockStore).orElse(null); if (txInfo == null) { diff --git a/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java b/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java index a162c59184d..4d7d30aebce 100644 --- a/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java @@ -67,6 +67,8 @@ import org.ethereum.rpc.Simples.SimpleConfigCapabilities; import org.ethereum.rpc.Web3Impl; import org.ethereum.rpc.Web3Mocks; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.sync.SyncPool; import org.ethereum.util.BuildInfo; import org.ethereum.util.ByteUtil; @@ -306,7 +308,7 @@ public int checkEstimateGas(int method, long expectedValue, long gasLimit, Assertions.assertNotEquals(expectedValue, gasLimit); CallArguments args = getContractCallTransactionParameters(method, gasLimit, srcAddr, contractAddress, repository); - String gas = web3.eth_estimateGas(args); + String gas = web3.eth_estimateGas(new CallArgumentsParam(args)); byte[] gasReturnedBytes = Hex.decode(gas.substring("0x".length())); BigInteger gasReturned = BigIntegers.fromUnsignedByteArray(gasReturnedBytes); int gasReturnedInt = gasReturned.intValueExact(); @@ -332,7 +334,7 @@ private String sendRawTransaction(Web3Impl web3) { String rawData = ByteUtil.toHexString(tx.getEncoded()); - return web3.eth_sendRawTransaction(rawData); + return web3.eth_sendRawTransaction(new HexDataParam(rawData)); } private Transaction getTransactionFromBlockWhichWasSend(BlockChainImpl blockchain, String tx) { @@ -350,13 +352,13 @@ private Transaction getTransactionFromBlockWhichWasSend(BlockChainImpl blockchai private String sendContractCreationTransaction(RskAddress srcaddr, Web3Impl web3, RepositorySnapshot repository) { CallArguments args = getContractCreationTransactionParameters(srcaddr, web3, repository); - return web3.eth_sendTransaction(args); + return web3.eth_sendTransaction(new CallArgumentsParam(args)); } private String sendTransaction(Web3Impl web3, RepositorySnapshot repository) { CallArguments args = getTransactionParameters(web3, repository); - return web3.eth_sendTransaction(args); + return web3.eth_sendTransaction(new CallArgumentsParam(args)); } //////////////////////////////////////////////// diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java index 79fea1f08bb..531ab2ba0c1 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java @@ -26,6 +26,8 @@ import org.ethereum.core.TransactionReceipt; import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.util.EthModuleTestUtils; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; @@ -63,14 +65,14 @@ void testCall_getRevertReason() throws FileNotFoundException, DslProcessorExcept args.setNonce("1"); args.setGas("10000000"); try { - eth.call(args, "0x2"); + eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("0x2")); fail(); } catch (RskJsonRpcRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Negative value.")); } args.setData("0xd96a094a0000000000000000000000000000000000000000000000000000000000000001"); // call to contract with param value = 1 - final String call = eth.call(args, "0x2"); + final String call = eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("0x2")); assertEquals("0x", call); } } diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleGasEstimationDSLTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleGasEstimationDSLTest.java index 123f50d943b..c3ddc9940ed 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleGasEstimationDSLTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleGasEstimationDSLTest.java @@ -30,6 +30,7 @@ import org.ethereum.core.TransactionReceipt; import org.ethereum.crypto.HashUtil; import org.ethereum.rpc.CallArguments; +import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.util.ByteUtil; import org.ethereum.util.EthModuleTestUtils; import org.ethereum.vm.GasCost; @@ -288,7 +289,7 @@ void estimateGas_gasCap() throws FileNotFoundException, DslProcessorException { callArguments.setGas(HexUtils.toQuantityJsonHex(gasEstimationCap + 1_000_000_000)); // exceeding the gas cap callArguments.setData("0x31fe52e8"); // call outOfGas() - String estimatedGas = eth.estimateGas(callArguments); + String estimatedGas = eth.estimateGas(new CallArgumentsParam(callArguments)); assertEquals("0x67c280", estimatedGas); assertEquals(gasEstimationCap, Long.decode(estimatedGas).longValue()); @@ -785,7 +786,7 @@ public boolean runWithArgumentsAndBlock(EthModuleTestUtils.EthModuleGasEstimatio } private long estimateGas(EthModuleTestUtils.EthModuleGasEstimation eth, CallArguments args) { - return Long.parseLong(eth.estimateGas(args).substring("0x".length()), 16); + return Long.parseLong(eth.estimateGas(new CallArgumentsParam(args)).substring("0x".length()), 16); } // todo this is duplicated code, should be extracted into a test util diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java index 534eb97a425..3abfa48709f 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java @@ -36,6 +36,9 @@ import org.ethereum.datasource.HashMapDB; import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.util.ByteUtil; import org.ethereum.util.TransactionFactoryHelper; import org.ethereum.vm.program.ProgramResult; @@ -106,7 +109,7 @@ void callSmokeTest() { config.getCallGasCap()); String expectedResult = HexUtils.toUnformattedJsonHex(hReturn); - String actualResult = eth.call(args, "latest"); + String actualResult = eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); assertEquals(expectedResult, actualResult); } @@ -146,7 +149,7 @@ void callWithoutReturn() { config.getCallGasCap()); String expectedResult = HexUtils.toUnformattedJsonHex(hReturn); - String actualResult = eth.call(args, "latest"); + String actualResult = eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); assertEquals(expectedResult, actualResult); } @@ -191,7 +194,7 @@ void test_revertedTransaction() { config.getCallGasCap()); try { - eth.call(args, "latest"); + eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); } catch (RskJsonRpcRequestException e) { assertThat(e.getMessage(), Matchers.containsString("deposit too big")); } @@ -222,7 +225,7 @@ void sendTransactionWithGasLimitTest() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); // Hash of the actual transaction builded inside the sendTransaction - String txResult = ethModuleTransaction.sendTransaction(args); + String txResult = ethModuleTransaction.sendTransaction(new CallArgumentsParam(args)); assertEquals(txExpectedResult, txResult); } @@ -250,7 +253,7 @@ void sendTransactionThrowsErrorOnChainIdValidationTest() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); - Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendTransaction(args)); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendTransaction(new CallArgumentsParam(args))); } @Test @@ -279,7 +282,7 @@ void sendRawTransactionThrowsErrorOnChainIdValidationTest() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); String rawData = ByteUtil.toHexString(tx.getEncoded()); - Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendRawTransaction(rawData)); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendRawTransaction(new HexDataParam(rawData))); } @Test @@ -298,10 +301,10 @@ void sendTransaction_invalidSenderAccount_throwsRskJsonRpcRequestException() { // Then try { - ethModuleTransaction.sendTransaction(argsMock); + ethModuleTransaction.sendTransaction(new CallArgumentsParam(argsMock)); fail("RskJsonRpcRequestException should be thrown"); } catch (RskJsonRpcRequestException ex) { - verify(argsMock, times(2)).getFrom(); + verify(argsMock, times(4)).getFrom(); assertEquals("Could not find account for address: " + addressFrom.toJsonString(), ex.getMessage()); } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java index 6544f79af21..adb865d4e77 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplLogsTest.java @@ -18,6 +18,29 @@ package org.ethereum.rpc; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; + +import java.math.BigInteger; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.ethereum.core.*; +import org.ethereum.datasource.HashMapDB; +import org.ethereum.db.BlockStore; +import org.ethereum.db.ReceiptStore; +import org.ethereum.facade.Ethereum; +import org.ethereum.rpc.Simples.SimpleConfigCapabilities; +import org.ethereum.rpc.dto.TransactionReceiptDTO; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.TxHashParam; +import org.ethereum.util.ByteUtil; +import org.ethereum.util.RskTestFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + import co.rsk.config.TestSystemProperties; import co.rsk.core.Coin; import co.rsk.core.Wallet; @@ -362,7 +385,7 @@ void getLogsFromBlockchainWithEventInContractCreation() throws Exception { assertEquals(1, logs.length); String txhash = ((LogFilterElement) logs[0]).transactionHash; - TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); + TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(new TxHashParam(txhash)); assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); } @@ -380,7 +403,7 @@ void getLogsTwiceFromBlockchainWithEventInContractCreation() throws Exception { assertEquals(1, logs.length); String txhash = ((LogFilterElement) logs[0]).transactionHash; - TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); + TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(new TxHashParam(txhash)); assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); } @@ -397,7 +420,7 @@ void getLogsFromBlockchainWithInvokeContract() throws Exception { assertEquals(2, logs.length); String txhash = ((LogFilterElement) logs[0]).transactionHash; - TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); + TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(new TxHashParam(txhash)); assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[1]).address); @@ -415,7 +438,7 @@ void getLogsKeepsCorrectOrderForReverseSearch() throws Exception { assertEquals(3, logs.length); String txHash1 = "0x" + transactions.get(0).getHash().toHexString(); - TransactionReceiptDTO txReceipt1 = web3.eth_getTransactionReceipt(txHash1); + TransactionReceiptDTO txReceipt1 = web3.eth_getTransactionReceipt(new TxHashParam(txHash1)); String contractAddress = txReceipt1.getContractAddress(); LogFilterElement logs1 = (LogFilterElement) logs[0]; assertEquals(contractAddress, logs1.address); @@ -426,7 +449,7 @@ void getLogsKeepsCorrectOrderForReverseSearch() throws Exception { assertArrayEquals(receipt1Logs.topics, logs1.topics); String txHash2 = "0x" + transactions.get(1).getHash().toHexString(); - TransactionReceiptDTO txReceipt2 = web3.eth_getTransactionReceipt(txHash2); + TransactionReceiptDTO txReceipt2 = web3.eth_getTransactionReceipt(new TxHashParam(txHash2)); LogFilterElement logs2 = (LogFilterElement) logs[1]; assertEquals(contractAddress, logs2.address); assertEquals(txHash2, logs2.transactionHash); @@ -436,7 +459,7 @@ void getLogsKeepsCorrectOrderForReverseSearch() throws Exception { assertArrayEquals(receipt2Logs.topics, logs2.topics); String txHash3 = "0x" + transactions.get(2).getHash().toHexString(); - TransactionReceiptDTO txReceipt3 = web3.eth_getTransactionReceipt(txHash3); + TransactionReceiptDTO txReceipt3 = web3.eth_getTransactionReceipt(new TxHashParam(txHash3)); LogFilterElement logs3 = (LogFilterElement) logs[2]; assertEquals(contractAddress, logs3.address); assertEquals(txHash3, logs3.transactionHash); @@ -465,7 +488,7 @@ void getLogsTwiceFromBlockchainWithInvokeContract() throws Exception { assertEquals(2, logs.length); String txhash = ((LogFilterElement) logs[0]).transactionHash; - TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); + TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(new TxHashParam(txhash)); assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[1]).address); @@ -850,7 +873,7 @@ void getLogsFromBlockchainWithEventInContractCreationReturnsAsExpectedWithBlockH assertEquals(1, logs.length); assertEquals(blockHash, ((LogFilterElement) logs[0]).blockHash); String txhash = ((LogFilterElement) logs[0]).transactionHash; - TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(txhash); + TransactionReceiptDTO txdto = web3.eth_getTransactionReceipt(new TxHashParam(txhash)); assertEquals(txdto.getContractAddress(), ((LogFilterElement) logs[0]).address); } 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 8b1ce0f081a..fb35555668f 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -78,6 +78,11 @@ import org.ethereum.rpc.dto.TransactionResultDTO; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockHashParam; +import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.BlockRefParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.rpc.parameters.HexIndexParam; import org.ethereum.rpc.parameters.TxHashParam; import org.ethereum.util.BuildInfo; @@ -217,7 +222,7 @@ void getBalanceWithAccount() { Web3Impl web3 = createWeb3(world); - assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(ByteUtil.toHexString(acc1.getAddress().getBytes()))); + assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(new HexAddressParam(ByteUtil.toHexString(acc1.getAddress().getBytes())))); } @Test @@ -227,7 +232,9 @@ void getBalanceWithAccountAndLatestBlock() { Web3Impl web3 = createWeb3(world); - assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(ByteUtil.toHexString(acc1.getAddress().getBytes()), "latest")); + assertEquals(BALANCE_10K_HEX, web3.eth_getBalance( + new HexAddressParam(ByteUtil.toHexString(acc1.getAddress().getBytes())), + new BlockRefParam(new BlockRef("latest")))); } @Test @@ -239,7 +246,7 @@ void getBalanceWithAccountAndGenesisBlock() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(accountAddress, "0x0")); + assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x0")))); } @Test @@ -252,42 +259,42 @@ void getBalanceWithAccountAndBlock() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(accountAddress, "0x1")); + assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1")))); } @Test //[ "0x
", { "blockNumber": "0x0" } -> return balance at given address in genesis block void getBalanceWithAccountAndBlockNumber() { final ChainParams chain = chainWithAccount10kBalance(false); - assertByBlockNumber(BALANCE_10K_HEX, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertByBlockNumber(BALANCE_10K_HEX, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException void getBalanceWithAccountAndInvalidInputThrowsException() { final ChainParams chain = chainWithAccount10kBalance(false); - assertInvalidInput(blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertInvalidInput(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return balance at given address in genesis block void getBalanceWithAccountAndBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); - assertByBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertByBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonExistentBlockHash(blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertNonExistentBlockHash(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @@ -295,14 +302,14 @@ void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @@ -310,28 +317,28 @@ void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return balance at given address in genesis block void getBalanceWithAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertCanonicalBlockHashWhenCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertCanonicalBlockHashWhenCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return balance at given address in genesis block void getBalanceWithAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return balance at given address in specified block void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertNonCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x" } -> return balance at given address in specified bloc void getBalanceWithAccountAndNonCanonicalBlockHash() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(chain.accountAddress, blockRef)); + assertNonCanonicalBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test @@ -355,9 +362,9 @@ void getBalanceWithAccountAndBlockWithTransaction() { String accountAddress = ByteUtil.toHexString(acc2.getAddress().getBytes()); String balanceString = BALANCE_10K_HEX; - assertEquals("0x0", web3.eth_getBalance(accountAddress, "0x0")); - assertEquals(balanceString, web3.eth_getBalance(accountAddress, "0x1")); - assertEquals(balanceString, web3.eth_getBalance(accountAddress, "pending")); + assertEquals("0x0", web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x0")))); + assertEquals(balanceString, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1")))); + assertEquals(balanceString, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("pending")))); } @Test @@ -719,7 +726,7 @@ void getUnknownTransactionReceipt() { String hashString = tx.getHash().toHexString(); - Assertions.assertNull(web3.eth_getTransactionReceipt(hashString)); + Assertions.assertNull(web3.eth_getTransactionReceipt(new TxHashParam(hashString))); Assertions.assertNull(web3.rsk_getRawTransactionReceiptByHash(hashString)); } @@ -738,7 +745,7 @@ void getTransactionReceipt() { String hashString = tx.getHash().toHexString(); - TransactionReceiptDTO tr = web3.eth_getTransactionReceipt(hashString); + TransactionReceiptDTO tr = web3.eth_getTransactionReceipt(new TxHashParam(hashString)); assertNotNull(tr); assertEquals("0x" + hashString, tr.getTransactionHash()); @@ -789,7 +796,7 @@ void getTransactionReceiptNotInMainBlockchain() { String hashString = tx.getHash().toHexString(); - TransactionReceiptDTO tr = web3.eth_getTransactionReceipt(hashString); + TransactionReceiptDTO tr = web3.eth_getTransactionReceipt(new TxHashParam(hashString)); Assertions.assertNull(tr); } @@ -989,12 +996,12 @@ void getTransactionCount() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - String count = web3.eth_getTransactionCount(accountAddress, "0x1"); + String count = web3.eth_getTransactionCount(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1"))); assertNotNull(count); assertEquals("0x1", count); - count = web3.eth_getTransactionCount(accountAddress, "0x0"); + count = web3.eth_getTransactionCount(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x0"))); assertNotNull(count); assertEquals("0x0", count); @@ -1004,42 +1011,42 @@ void getTransactionCount() { //[ "0x
", { "blockNumber": "0x0" } -> return tx count at given address in genesis block void getTransactionCountByBlockNumber() { final ChainParams chain = createChainWithATransaction(false); - assertByBlockNumber("0x1", blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); + assertByBlockNumber("0x1", blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException void getTransactionCountAndInvalidInputThrowsException() { final ChainParams chain = createChainWithATransaction(false); - assertInvalidInput(blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); + assertInvalidInput(blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return tx count at given address in genesis block void getTransactionCountByBlockHash() { final ChainParams chain = createChainWithATransaction(false); - assertByBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); + assertByBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getTransactionCountByNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonExistentBlockHash(blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); + assertNonExistentBlockHash(blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getTransactionCountByNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithATransaction(true); - assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); + assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x" } -> return tx count at given address in specified bloc void getTransactionCountByNonCanonicalBlockHash() { final ChainParams chain = createChainWithATransaction(true); - assertNonCanonicalBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(chain.accountAddress, blockRef)); + assertNonCanonicalBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test @@ -1780,7 +1787,7 @@ function greet(string memory param) public pure returns (string memory) { argsForCall.setTo(HexUtils.toJsonHex(tx.getContractAddress().getBytes())); argsForCall.setData("0xead710c40000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"); - String result = web3.eth_call(argsForCall, "latest"); + String result = web3.eth_call(new CallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); assertEquals("0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000", result); } @@ -1827,7 +1834,7 @@ function greet(string memory param) public pure returns (string memory) { argsForCall.setTo(HexUtils.toJsonHex(tx.getContractAddress().getBytes())); argsForCall.setData("0xead710c40000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"); - String result = web3.eth_call(argsForCall, "latest"); + String result = web3.eth_call(new CallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); assertEquals("0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000", result); } @@ -1860,7 +1867,7 @@ void callNoneContractReturn() { argsForCall.setTo(HexUtils.toUnformattedJsonHex(tx.getContractAddress().getBytes())); argsForCall.setData(HexUtils.toUnformattedJsonHex(func.encode())); - String result = web3.eth_call(argsForCall, "latest"); + String result = web3.eth_call(new CallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); assertEquals("0x", result); } @@ -1964,7 +1971,7 @@ void eth_sign() { byte[] hash = Keccak256Helper.keccak256("this is the data to hash".getBytes()); - String signature = web3.eth_sign(addr1, "0x" + ByteUtil.toHexString(hash)); + String signature = web3.eth_sign(new HexAddressParam(addr1), new HexDataParam("0x" + ByteUtil.toHexString(hash))); MatcherAssert.assertThat( signature, @@ -1990,7 +1997,7 @@ void eth_sign_testSignatureGenerationToBeAlways32BytesLength() { byte[] hash = Keccak256Helper.keccak256("this is the data to hash".getBytes()); - String signature = web3.eth_sign(addr1, "0x" + ByteUtil.toHexString(hash)); + String signature = web3.eth_sign(new HexAddressParam(addr1), new HexDataParam("0x" + ByteUtil.toHexString(hash))); MatcherAssert.assertThat( signature, @@ -2334,7 +2341,7 @@ private void checkSendTransaction(Byte chainId) { args.setChainId(HexUtils.toJsonHex(new byte[]{chainId})); } - String txHash = web3.eth_sendTransaction(args); + String txHash = web3.eth_sendTransaction(new CallArgumentsParam(args)); // ***** Verifies tx hash String to = toAddress.substring(2); @@ -2403,7 +2410,7 @@ void callWithoutReturn() { argsForCall.setTo(HexUtils.toJsonHex(tx.getContractAddress().getBytes())); argsForCall.setData(HexUtils.toJsonHex(noreturn.functions.get("noreturn").encodeSignature())); - String result = web3.eth_call(argsForCall, "latest"); + String result = web3.eth_call(new CallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); Assertions.assertEquals("0x", result); } @@ -3040,7 +3047,7 @@ void transactionReceiptAndResultHasTypeField() { String hashString = tx.getHash().toHexString(); TxHashParam txHashParam = new TxHashParam(hashString); - TransactionReceiptDTO txReceipt = web3.eth_getTransactionReceipt(hashString); + TransactionReceiptDTO txReceipt = web3.eth_getTransactionReceipt(new TxHashParam(hashString)); TransactionResultDTO txResult = web3.eth_getTransactionByHash(txHashParam); assertEquals("0x0", txReceipt.getType()); diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java index 752d0d05d5f..9f33754cbc8 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java @@ -25,6 +25,8 @@ import org.ethereum.net.server.ChannelManager; import org.ethereum.net.server.PeerServer; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.BlockRefParam; +import org.ethereum.rpc.parameters.HexAddressParam; import org.ethereum.util.BuildInfo; import org.ethereum.vm.DataWord; import org.junit.jupiter.api.BeforeEach; @@ -101,12 +103,12 @@ void eth_getBalance_stateCannotBeRetrieved() { when(retriever.getInformationProvider(id)) .thenThrow(RskJsonRpcRequestException.blockNotFound("Block not found")); TestUtils.assertThrows(RskJsonRpcRequestException.class, - () -> target.eth_getBalance(addr, id)); + () -> target.eth_getBalance(new HexAddressParam(addr), new BlockRefParam(new BlockRef(id)))); } @Test void eth_getBalance() { - String id = "id"; + String id = "0x00"; String addr = "0x0011223344556677880011223344556677889900"; RskAddress expectedAddress = new RskAddress(addr); @@ -115,7 +117,7 @@ void eth_getBalance() { when(aip.getBalance(expectedAddress)) .thenReturn(new Coin(BigInteger.ONE)); - String result = target.eth_getBalance(addr, id); + String result = target.eth_getBalance(new HexAddressParam(addr),new BlockRefParam(new BlockRef(id))); assertEquals("0x1", result); } @@ -130,7 +132,7 @@ void eth_getBalanceByBlockRef() { }; final Web3Impl spyTarget = spy(target); doReturn("0x1").when(spyTarget).invokeByBlockRef(eq(blockRef),any()); - String result = spyTarget.eth_getBalance(addr, blockRef); + String result = spyTarget.eth_getBalance(new HexAddressParam(addr), new BlockRefParam(new BlockRef(blockRef))); assertEquals("0x1", result); verify(spyTarget).invokeByBlockRef(eq(blockRef),any()); } @@ -276,7 +278,7 @@ void eth_getBlockTransactionCountByBlockRef() { }; final Web3Impl spyTarget = spy(target); doReturn("0x1").when(spyTarget).invokeByBlockRef(eq(blockRef),any()); - String result = spyTarget.eth_getTransactionCount(addr, blockRef); + String result = spyTarget.eth_getTransactionCount(new HexAddressParam(addr), new BlockRefParam(new BlockRef(blockRef))); assertEquals("0x1", result); verify(spyTarget).invokeByBlockRef(eq(blockRef),any()); } diff --git a/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java b/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java index acff8d03dfd..76cc4bbcac8 100644 --- a/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java +++ b/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java @@ -34,6 +34,8 @@ import org.ethereum.core.ReceivedTxSignatureCache; import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.vm.DataWord; import org.ethereum.vm.PrecompiledContracts; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; @@ -111,7 +113,7 @@ void testNested_interfaceCall_require() throws FileNotFoundException, DslProcess final String contractA = getContractAddressString(TX_CONTRACTA); CallArguments args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(0))); try { - ethModule.call(args, "latest"); + ethModule.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); fail(); } catch (RskJsonRpcRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Negative value")); @@ -119,7 +121,7 @@ void testNested_interfaceCall_require() throws FileNotFoundException, DslProcess //Success Call -> 2 > 0 args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(2))); - final String call = ethModule.call(args, "latest"); + final String call = ethModule.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); //assertEquals("0x" + DataWord.valueOf(2).toString(), call); } @@ -151,12 +153,12 @@ void testNested_ABICall_require() throws FileNotFoundException, DslProcessorExce //Failed Call ContractA.buy(0) -> 0 > 0 final String contractA = getContractAddressString("tx03"); CallArguments args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(0))); - String call = ethModule.call(args, "latest"); + String call = ethModule.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); assertEquals("0x" + DataWord.valueOf(0).toString(), call); //Success Call -> 2 > 0 args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(2))); - call = ethModule.call(args, "latest"); + call = ethModule.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); assertEquals("0x" + DataWord.valueOf(2).toString(), call); } From 59637703f1aaa10e9ae2626a5dcc3778b0d6a413 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Tue, 5 Sep 2023 10:50:20 -0400 Subject: [PATCH 25/47] Refactor CallArgumentsParam implementation --- .../main/java/co/rsk/rpc/Web3EthModule.java | 3 +- .../co/rsk/rpc/modules/eth/EthModule.java | 4 +-- .../modules/eth/EthModuleTransactionBase.java | 2 +- .../main/java/org/ethereum/rpc/Web3Impl.java | 4 +-- .../co/rsk/mine/TransactionModuleTest.java | 8 ++--- .../rsk/rpc/modules/eth/EthModuleDSLTest.java | 6 ++-- .../eth/EthModuleGasEstimationDSLTest.java | 6 ++-- .../co/rsk/rpc/modules/eth/EthModuleTest.java | 20 ++++------- .../java/org/ethereum/rpc/Web3ImplTest.java | 34 ++++++++++--------- .../org/ethereum/rpc/Web3ImplUnitTest.java | 3 +- .../util/TransactionFactoryHelper.java | 19 +++++++++++ .../vm/program/NestedContractsTest.java | 10 +++--- 12 files changed, 66 insertions(+), 53 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index f6e3fff7f16..af4040da38d 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -19,7 +19,6 @@ package co.rsk.rpc; import co.rsk.rpc.modules.eth.EthModule; -import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.dto.BlockResultDTO; import org.ethereum.rpc.dto.CompilationResultDTO; import org.ethereum.rpc.dto.TransactionReceiptDTO; @@ -78,7 +77,7 @@ default String eth_chainId() { String eth_blockNumber(); - String eth_call(CallArguments args, Map blockRef) throws Exception; // NOSONAR + String eth_call(CallArgumentsParam args, Map blockRef) throws Exception; // NOSONAR String eth_getBalance(HexAddressParam address, BlockRefParam blockRefParam) throws Exception; diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java index e3fee59111a..92ff0febc7a 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java @@ -126,7 +126,7 @@ public Map bridgeState() throws IOException, BlockStoreException public String call(CallArgumentsParam argsParam, BlockIdentifierParam bnOrId) { String hReturn = null; - CallArguments args = argsParam.getCallArguments(); + CallArguments args = argsParam.toCallArguments(); try { ExecutionBlockRetriever.Result result = executionBlockRetriever.retrieveExecutionBlock(bnOrId.getIdentifier()); Block block = result.getBlock(); @@ -159,7 +159,7 @@ public String estimateGas(CallArgumentsParam args) { String estimation = null; Block bestBlock = blockchain.getBestBlock(); try { - CallArgumentsToByteArray hexArgs = new CallArgumentsToByteArray(args.getCallArguments()); + CallArgumentsToByteArray hexArgs = new CallArgumentsToByteArray(args.toCallArguments()); TransactionExecutor executor = reversibleTransactionExecutor.estimateGas( bestBlock, diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionBase.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionBase.java index 0bec326c0c8..f2b7a125a86 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionBase.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionBase.java @@ -58,7 +58,7 @@ public EthModuleTransactionBase(Constants constants, Wallet wallet, TransactionP @Override public synchronized String sendTransaction(CallArgumentsParam argsParam) { - CallArguments args = argsParam.getCallArguments(); + CallArguments args = argsParam.toCallArguments(); if(args.getFrom() == null) { throw invalidParamError("from is null"); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index e84bd0f3033..634f4944b4c 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -404,8 +404,8 @@ public String eth_blockNumber() { } @Override - public String eth_call(CallArguments args, Map inputs) { - return invokeByBlockRef(inputs, blockNumber -> this.eth_call(new CallArgumentsParam(args), new BlockIdentifierParam(blockNumber))); + public String eth_call(CallArgumentsParam args, Map inputs) { + return invokeByBlockRef(inputs, blockNumber -> this.eth_call(args, new BlockIdentifierParam(blockNumber))); } @Override diff --git a/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java b/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java index 4d7d30aebce..94cc516fdb3 100644 --- a/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/mine/TransactionModuleTest.java @@ -67,11 +67,11 @@ import org.ethereum.rpc.Simples.SimpleConfigCapabilities; import org.ethereum.rpc.Web3Impl; import org.ethereum.rpc.Web3Mocks; -import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.sync.SyncPool; import org.ethereum.util.BuildInfo; import org.ethereum.util.ByteUtil; +import org.ethereum.util.TransactionFactoryHelper; import org.ethereum.vm.GasCost; import org.ethereum.vm.PrecompiledContracts; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; @@ -308,7 +308,7 @@ public int checkEstimateGas(int method, long expectedValue, long gasLimit, Assertions.assertNotEquals(expectedValue, gasLimit); CallArguments args = getContractCallTransactionParameters(method, gasLimit, srcAddr, contractAddress, repository); - String gas = web3.eth_estimateGas(new CallArgumentsParam(args)); + String gas = web3.eth_estimateGas(TransactionFactoryHelper.toCallArgumentsParam(args)); byte[] gasReturnedBytes = Hex.decode(gas.substring("0x".length())); BigInteger gasReturned = BigIntegers.fromUnsignedByteArray(gasReturnedBytes); int gasReturnedInt = gasReturned.intValueExact(); @@ -352,13 +352,13 @@ private Transaction getTransactionFromBlockWhichWasSend(BlockChainImpl blockchai private String sendContractCreationTransaction(RskAddress srcaddr, Web3Impl web3, RepositorySnapshot repository) { CallArguments args = getContractCreationTransactionParameters(srcaddr, web3, repository); - return web3.eth_sendTransaction(new CallArgumentsParam(args)); + return web3.eth_sendTransaction(TransactionFactoryHelper.toCallArgumentsParam(args)); } private String sendTransaction(Web3Impl web3, RepositorySnapshot repository) { CallArguments args = getTransactionParameters(web3, repository); - return web3.eth_sendTransaction(new CallArgumentsParam(args)); + return web3.eth_sendTransaction(TransactionFactoryHelper.toCallArgumentsParam(args)); } //////////////////////////////////////////////// diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java index 531ab2ba0c1..de5df86e265 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java @@ -27,8 +27,8 @@ import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockIdentifierParam; -import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.util.EthModuleTestUtils; +import org.ethereum.util.TransactionFactoryHelper; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; @@ -65,14 +65,14 @@ void testCall_getRevertReason() throws FileNotFoundException, DslProcessorExcept args.setNonce("1"); args.setGas("10000000"); try { - eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("0x2")); + eth.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("0x2")); fail(); } catch (RskJsonRpcRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Negative value.")); } args.setData("0xd96a094a0000000000000000000000000000000000000000000000000000000000000001"); // call to contract with param value = 1 - final String call = eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("0x2")); + final String call = eth.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("0x2")); assertEquals("0x", call); } } diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleGasEstimationDSLTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleGasEstimationDSLTest.java index c3ddc9940ed..dd98efff455 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleGasEstimationDSLTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleGasEstimationDSLTest.java @@ -30,9 +30,9 @@ import org.ethereum.core.TransactionReceipt; import org.ethereum.crypto.HashUtil; import org.ethereum.rpc.CallArguments; -import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.util.ByteUtil; import org.ethereum.util.EthModuleTestUtils; +import org.ethereum.util.TransactionFactoryHelper; import org.ethereum.vm.GasCost; import org.ethereum.vm.LogInfo; import org.ethereum.vm.program.InternalTransaction; @@ -289,7 +289,7 @@ void estimateGas_gasCap() throws FileNotFoundException, DslProcessorException { callArguments.setGas(HexUtils.toQuantityJsonHex(gasEstimationCap + 1_000_000_000)); // exceeding the gas cap callArguments.setData("0x31fe52e8"); // call outOfGas() - String estimatedGas = eth.estimateGas(new CallArgumentsParam(callArguments)); + String estimatedGas = eth.estimateGas(TransactionFactoryHelper.toCallArgumentsParam(callArguments)); assertEquals("0x67c280", estimatedGas); assertEquals(gasEstimationCap, Long.decode(estimatedGas).longValue()); @@ -786,7 +786,7 @@ public boolean runWithArgumentsAndBlock(EthModuleTestUtils.EthModuleGasEstimatio } private long estimateGas(EthModuleTestUtils.EthModuleGasEstimation eth, CallArguments args) { - return Long.parseLong(eth.estimateGas(new CallArgumentsParam(args)).substring("0x".length()), 16); + return Long.parseLong(eth.estimateGas(TransactionFactoryHelper.toCallArgumentsParam(args)).substring("0x".length()), 16); } // todo this is duplicated code, should be extracted into a test util diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java index 3abfa48709f..2fe7ec49993 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java @@ -37,7 +37,6 @@ import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockIdentifierParam; -import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.util.ByteUtil; import org.ethereum.util.TransactionFactoryHelper; @@ -59,13 +58,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; class EthModuleTest { @@ -109,7 +102,7 @@ void callSmokeTest() { config.getCallGasCap()); String expectedResult = HexUtils.toUnformattedJsonHex(hReturn); - String actualResult = eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); + String actualResult = eth.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("latest")); assertEquals(expectedResult, actualResult); } @@ -149,7 +142,7 @@ void callWithoutReturn() { config.getCallGasCap()); String expectedResult = HexUtils.toUnformattedJsonHex(hReturn); - String actualResult = eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); + String actualResult = eth.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("latest")); assertEquals(expectedResult, actualResult); } @@ -194,7 +187,7 @@ void test_revertedTransaction() { config.getCallGasCap()); try { - eth.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); + eth.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("latest")); } catch (RskJsonRpcRequestException e) { assertThat(e.getMessage(), Matchers.containsString("deposit too big")); } @@ -225,7 +218,7 @@ void sendTransactionWithGasLimitTest() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); // Hash of the actual transaction builded inside the sendTransaction - String txResult = ethModuleTransaction.sendTransaction(new CallArgumentsParam(args)); + String txResult = ethModuleTransaction.sendTransaction(TransactionFactoryHelper.toCallArgumentsParam(args)); assertEquals(txExpectedResult, txResult); } @@ -253,7 +246,7 @@ void sendTransactionThrowsErrorOnChainIdValidationTest() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); - Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendTransaction(new CallArgumentsParam(args))); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendTransaction(TransactionFactoryHelper.toCallArgumentsParam(args))); } @Test @@ -301,10 +294,9 @@ void sendTransaction_invalidSenderAccount_throwsRskJsonRpcRequestException() { // Then try { - ethModuleTransaction.sendTransaction(new CallArgumentsParam(argsMock)); + ethModuleTransaction.sendTransaction(TransactionFactoryHelper.toCallArgumentsParam(argsMock)); fail("RskJsonRpcRequestException should be thrown"); } catch (RskJsonRpcRequestException ex) { - verify(argsMock, times(4)).getFrom(); assertEquals("Could not find account for address: " + addressFrom.toJsonString(), ex.getMessage()); } } 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 fb35555668f..edcddac18d4 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -87,6 +87,7 @@ import org.ethereum.rpc.parameters.TxHashParam; import org.ethereum.util.BuildInfo; import org.ethereum.util.ByteUtil; +import org.ethereum.util.TransactionFactoryHelper; import org.ethereum.vm.PrecompiledContracts; import org.ethereum.vm.program.ProgramResult; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; @@ -513,70 +514,70 @@ void getCodeAtAccountAndNonCanonicalBlockHash() { //[ {argsForCall}, { "blockNumber": "0x0" } -> return contract call respond at given args for call in genesis block void callByBlockNumber() { final ChainParams chain = createChainWithACall(false); - assertByBlockNumber(CALL_RESPOND, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertByBlockNumber(CALL_RESPOND, blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return contract call respond at given address in genesis block void callByBlockHash() { final ChainParams chain = createChainWithACall(false); - assertByBlockHash(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertByBlockHash(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test //[ {argsForCall}, { "blockHash": "0x" } -> raise block-not-found error void callByNonExistentBlockHash() { final ChainParams chain = createChainWithACall(false); - assertNonExistentBlockHash(blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertNonExistentBlockHash(blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test //[ {argsForCall}, { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void callByNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithACall(false); - assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test //[ {argsForCall}, { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void callByNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithACall(false); - assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test // [ {argsForCall} { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void callByNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithACall(true); - assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return contract call respond at given address in genesis block void callByCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithACall(false); - assertCanonicalBlockHashWhenCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertCanonicalBlockHashWhenCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test //[ {argsForCall}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return contract call respond at given address in genesis block void callByCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithACall(false); - assertCanonicalBlockHashWhenNotCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertCanonicalBlockHashWhenNotCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test // [ {argsForCall}, { "blockHash": "0x", "requireCanonical": false } -> return contract call respond at given address in specified block void callByNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithACall(true); - assertNonCanonicalBlockHashWhenNotCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertNonCanonicalBlockHashWhenNotCanonical(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test // [ {argsForCall}, { "blockHash": "0x" } -> return contract call respond at given address in specified bloc void callByNonCanonicalBlockHash() { final ChainParams chain = createChainWithACall(true); - assertNonCanonicalBlockHash(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(chain.argsForCall, blockRef)); + assertNonCanonicalBlockHash(CALL_RESPOND, chain.block, blockRef -> chain.web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(chain.argsForCall), blockRef)); } @Test @@ -1787,7 +1788,7 @@ function greet(string memory param) public pure returns (string memory) { argsForCall.setTo(HexUtils.toJsonHex(tx.getContractAddress().getBytes())); argsForCall.setData("0xead710c40000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"); - String result = web3.eth_call(new CallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); + String result = web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); assertEquals("0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000", result); } @@ -1834,7 +1835,7 @@ function greet(string memory param) public pure returns (string memory) { argsForCall.setTo(HexUtils.toJsonHex(tx.getContractAddress().getBytes())); argsForCall.setData("0xead710c40000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"); - String result = web3.eth_call(new CallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); + String result = web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); assertEquals("0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000", result); } @@ -1867,7 +1868,7 @@ void callNoneContractReturn() { argsForCall.setTo(HexUtils.toUnformattedJsonHex(tx.getContractAddress().getBytes())); argsForCall.setData(HexUtils.toUnformattedJsonHex(func.encode())); - String result = web3.eth_call(new CallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); + String result = web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); assertEquals("0x", result); } @@ -2340,8 +2341,9 @@ private void checkSendTransaction(Byte chainId) { if (chainId != null) { args.setChainId(HexUtils.toJsonHex(new byte[]{chainId})); } + CallArgumentsParam argsParam = TransactionFactoryHelper.toCallArgumentsParam(args); - String txHash = web3.eth_sendTransaction(new CallArgumentsParam(args)); + String txHash = web3.eth_sendTransaction(argsParam); // ***** Verifies tx hash String to = toAddress.substring(2); @@ -2351,7 +2353,7 @@ private void checkSendTransaction(Byte chainId) { .gasPrice(gasPrice) .gasLimit(gasLimit) .destination(Hex.decode(to)) - .data(args.getData() == null ? null : Hex.decode(args.getData())) + .data(args.getData() == null ? null : Hex.decode(args.getData().substring(2))) .chainId(config.getNetworkConstants().getChainId()) .value(value) .build(); @@ -2410,7 +2412,7 @@ void callWithoutReturn() { argsForCall.setTo(HexUtils.toJsonHex(tx.getContractAddress().getBytes())); argsForCall.setData(HexUtils.toJsonHex(noreturn.functions.get("noreturn").encodeSignature())); - String result = web3.eth_call(new CallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); + String result = web3.eth_call(TransactionFactoryHelper.toCallArgumentsParam(argsForCall), new BlockIdentifierParam("latest")); Assertions.assertEquals("0x", result); } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java index 9f33754cbc8..8b7f3b3f8b5 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java @@ -28,6 +28,7 @@ import org.ethereum.rpc.parameters.BlockRefParam; import org.ethereum.rpc.parameters.HexAddressParam; import org.ethereum.util.BuildInfo; +import org.ethereum.util.TransactionFactoryHelper; import org.ethereum.vm.DataWord; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -262,7 +263,7 @@ void eth_callAtByBlockRef() { final String expectedData = "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"; doReturn(expectedData).when(spyTarget).invokeByBlockRef(eq(blockRef),any()); - String result = spyTarget.eth_call(argsForCall,blockRef); + String result = spyTarget.eth_call(TransactionFactoryHelper.toCallArgumentsParam(argsForCall),blockRef); assertEquals(expectedData, result); verify(spyTarget).invokeByBlockRef(eq(blockRef),any()); } diff --git a/rskj-core/src/test/java/org/ethereum/util/TransactionFactoryHelper.java b/rskj-core/src/test/java/org/ethereum/util/TransactionFactoryHelper.java index a92f7cd8176..bea56c4e635 100644 --- a/rskj-core/src/test/java/org/ethereum/util/TransactionFactoryHelper.java +++ b/rskj-core/src/test/java/org/ethereum/util/TransactionFactoryHelper.java @@ -1,6 +1,7 @@ package org.ethereum.util; import java.math.BigInteger; +import java.util.Optional; import org.ethereum.core.Account; import org.ethereum.core.Transaction; @@ -10,6 +11,10 @@ import co.rsk.test.builders.AccountBuilder; import co.rsk.test.builders.TransactionBuilder; import co.rsk.util.HexUtils; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDataParam; +import org.ethereum.rpc.parameters.HexNumberParam; /** * Created by ajlopez on 28/02/2018. @@ -116,4 +121,18 @@ public static Transaction createTransaction(CallArguments args, byte chainId, Ac return tx; } + public static CallArgumentsParam toCallArgumentsParam(CallArguments args) { + return new CallArgumentsParam( + Optional.ofNullable(args.getFrom()).filter(p -> !p.isEmpty()).map(HexAddressParam::new).orElse(null), + Optional.ofNullable(args.getTo()).filter(p -> !p.isEmpty()).map(HexAddressParam::new).orElse(null), + Optional.ofNullable(args.getGas()).filter(p -> !p.isEmpty()).map(HexNumberParam::new).orElse(null), + Optional.ofNullable(args.getGasPrice()).filter(p -> !p.isEmpty()).map(HexNumberParam::new).orElse(null), + Optional.ofNullable(args.getGasLimit()).filter(p -> !p.isEmpty()).map(HexNumberParam::new).orElse(null), + Optional.ofNullable(args.getNonce()).filter(p -> !p.isEmpty()).map(HexNumberParam::new).orElse(null), + Optional.ofNullable(args.getChainId()).filter(p -> !p.isEmpty()).map(HexNumberParam::new).orElse(null), + Optional.ofNullable(args.getValue()).filter(p -> !p.isEmpty()).map(HexNumberParam::new).orElse(null), + Optional.ofNullable(args.getData()).filter(p -> !p.isEmpty()).map(HexDataParam::new).orElse(null) + ); + } + } diff --git a/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java b/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java index 76cc4bbcac8..ae71d844e0a 100644 --- a/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java +++ b/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java @@ -35,7 +35,7 @@ import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockIdentifierParam; -import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.util.TransactionFactoryHelper; import org.ethereum.vm.DataWord; import org.ethereum.vm.PrecompiledContracts; import org.ethereum.vm.program.invoke.ProgramInvokeFactoryImpl; @@ -113,7 +113,7 @@ void testNested_interfaceCall_require() throws FileNotFoundException, DslProcess final String contractA = getContractAddressString(TX_CONTRACTA); CallArguments args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(0))); try { - ethModule.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); + ethModule.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("latest")); fail(); } catch (RskJsonRpcRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Negative value")); @@ -121,7 +121,7 @@ void testNested_interfaceCall_require() throws FileNotFoundException, DslProcess //Success Call -> 2 > 0 args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(2))); - final String call = ethModule.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); + final String call = ethModule.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("latest")); //assertEquals("0x" + DataWord.valueOf(2).toString(), call); } @@ -153,12 +153,12 @@ void testNested_ABICall_require() throws FileNotFoundException, DslProcessorExce //Failed Call ContractA.buy(0) -> 0 > 0 final String contractA = getContractAddressString("tx03"); CallArguments args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(0))); - String call = ethModule.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); + String call = ethModule.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("latest")); assertEquals("0x" + DataWord.valueOf(0).toString(), call); //Success Call -> 2 > 0 args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(2))); - call = ethModule.call(new CallArgumentsParam(args), new BlockIdentifierParam("latest")); + call = ethModule.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("latest")); assertEquals("0x" + DataWord.valueOf(2).toString(), call); } From d1f32b50439cf85267fd5cdaf638cda7622eadea Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Wed, 6 Sep 2023 08:07:31 -0400 Subject: [PATCH 26/47] Make sendTransaction method synchronized --- .../co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java index 180fa46ff0f..6b0313f6033 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleTransactionDisabled.java @@ -21,7 +21,6 @@ import co.rsk.net.TransactionGateway; import org.ethereum.config.Constants; import org.ethereum.core.TransactionPool; -import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.parameters.CallArgumentsParam; import static org.ethereum.rpc.exception.RskJsonRpcRequestException.invalidParamError; @@ -37,7 +36,7 @@ public EthModuleTransactionDisabled(Constants constants, TransactionPool transac } @Override - public String sendTransaction(CallArgumentsParam args) { // lgtm [java/non-sync-override] + public synchronized String sendTransaction(CallArgumentsParam args) { // lgtm [java/non-sync-override] LOGGER.debug("eth_sendTransaction({}): {}", args, null); throw invalidParamError("Local wallet is disabled in this node"); } From fddec391c3716e22285d94819b66d81bdc079633 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Wed, 6 Sep 2023 09:16:03 -0400 Subject: [PATCH 27/47] Fix code smells --- .../co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java | 4 +++- .../java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java | 5 ++++- .../java/co/rsk/rpc/modules/eth/EthModuleTest.java | 10 +++++++--- .../org/ethereum/vm/program/NestedContractsTest.java | 5 ++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java index 86e24e6511c..3d254713132 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java @@ -56,7 +56,9 @@ public String sign(HexAddressParam addr, HexDataParam data) { throw invalidParamError("Account not found"); } - return s = this.sign(data.getRawDataBytes(), account.getEcKey()); + s = this.sign(data.getRawDataBytes(), account.getEcKey()); + + return s; } finally { LOGGER.debug("eth_sign({}, {}): {}", addr, data, s); } diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java index de5df86e265..cad63aba4f2 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleDSLTest.java @@ -27,6 +27,7 @@ import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.util.EthModuleTestUtils; import org.ethereum.util.TransactionFactoryHelper; import org.hamcrest.MatcherAssert; @@ -64,8 +65,10 @@ void testCall_getRevertReason() throws FileNotFoundException, DslProcessorExcept args.setValue("0"); args.setNonce("1"); args.setGas("10000000"); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("0x2"); try { - eth.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("0x2")); + eth.call(callArgumentsParam, blockIdentifierParam); fail(); } catch (RskJsonRpcRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Negative value.")); diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java index 2fe7ec49993..c4703a9a568 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java @@ -37,6 +37,7 @@ import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.util.ByteUtil; import org.ethereum.util.TransactionFactoryHelper; @@ -246,7 +247,8 @@ void sendTransactionThrowsErrorOnChainIdValidationTest() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); - Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendTransaction(TransactionFactoryHelper.toCallArgumentsParam(args))); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendTransaction(callArgumentsParam)); } @Test @@ -275,7 +277,8 @@ void sendRawTransactionThrowsErrorOnChainIdValidationTest() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); String rawData = ByteUtil.toHexString(tx.getEncoded()); - Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendRawTransaction(new HexDataParam(rawData))); + HexDataParam hexDataParam = new HexDataParam(rawData); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> ethModuleTransaction.sendRawTransaction(hexDataParam)); } @Test @@ -292,9 +295,10 @@ void sendTransaction_invalidSenderAccount_throwsRskJsonRpcRequestException() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPoolMock, transactionGatewayMock); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(argsMock); // Then try { - ethModuleTransaction.sendTransaction(TransactionFactoryHelper.toCallArgumentsParam(argsMock)); + ethModuleTransaction.sendTransaction(callArgumentsParam); fail("RskJsonRpcRequestException should be thrown"); } catch (RskJsonRpcRequestException ex) { assertEquals("Could not find account for address: " + addressFrom.toJsonString(), ex.getMessage()); diff --git a/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java b/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java index ae71d844e0a..dada3866b25 100644 --- a/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java +++ b/rskj-core/src/test/java/org/ethereum/vm/program/NestedContractsTest.java @@ -35,6 +35,7 @@ import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockIdentifierParam; +import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.util.TransactionFactoryHelper; import org.ethereum.vm.DataWord; import org.ethereum.vm.PrecompiledContracts; @@ -112,8 +113,10 @@ void testNested_interfaceCall_require() throws FileNotFoundException, DslProcess //Failed Call ContractA.buy(0) -> 0 > 0 final String contractA = getContractAddressString(TX_CONTRACTA); CallArguments args = buildArgs(contractA, Hex.toHexString(BUY_FUNCTION.encode(0))); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("latest"); try { - ethModule.call(TransactionFactoryHelper.toCallArgumentsParam(args), new BlockIdentifierParam("latest")); + ethModule.call(callArgumentsParam, blockIdentifierParam); fail(); } catch (RskJsonRpcRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Negative value")); From d0fe9483f10e18ad16d54d2398212d7a9d812e01 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Wed, 6 Sep 2023 10:53:19 -0400 Subject: [PATCH 28/47] Suppress Sonar warnings --- rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java | 1 + rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java | 1 + 2 files changed, 2 insertions(+) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index af4040da38d..12599b36203 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -36,6 +36,7 @@ import java.math.BigInteger; import java.util.Map; +@SuppressWarnings({"java:S100", "java:S112"}) public interface Web3EthModule { default String[] eth_accounts() { return getEthModule().accounts(); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index 634f4944b4c..f6a5e6f8e79 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -85,6 +85,7 @@ import static java.lang.Math.max; import static org.ethereum.rpc.exception.RskJsonRpcRequestException.*; +@SuppressWarnings("java:S100") public class Web3Impl implements Web3 { private static final Logger logger = LoggerFactory.getLogger("web3"); From b3ed70095346f5cba420a34f6b9411113cdb54a7 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Fri, 8 Sep 2023 09:08:33 -0400 Subject: [PATCH 29/47] Fix failing tests on EthModuleTest --- .../co/rsk/rpc/modules/eth/EthModuleTest.java | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java index c4703a9a568..12a4c9a16d3 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java @@ -47,7 +47,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -59,6 +58,8 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class EthModuleTest { @@ -393,7 +394,10 @@ void whenExecuteCallWithDataParameter_callExecutorWithData() { config.getGasEstimationCap(), config.getCallGasCap()); - eth.call(args, "latest"); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("latest"); + + eth.call(callArgumentsParam, blockIdentifierParam); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(executor, times(1)) @@ -436,7 +440,10 @@ void whenExecuteCallWithInputParameter_callExecutorWithInput() { config.getGasEstimationCap(), config.getCallGasCap()); - eth.call(args, "latest"); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("latest"); + + eth.call(callArgumentsParam, blockIdentifierParam); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(executor, times(1)) @@ -481,7 +488,10 @@ void whenExecuteCallWithInputAndDataParameters_callExecutorWithInput() { config.getCallGasCap()); - eth.call(args, "latest"); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + BlockIdentifierParam blockIdentifierParam = new BlockIdentifierParam("latest"); + + eth.call(callArgumentsParam, blockIdentifierParam); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(executor, times(1)) @@ -523,7 +533,9 @@ void whenExecuteEstimateGasWithDataParameter_callExecutorWithData() { config.getGasEstimationCap(), config.getCallGasCap()); - eth.estimateGas(args); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + + eth.estimateGas(callArgumentsParam); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(reversibleTransactionExecutor, times(1)) @@ -565,7 +577,9 @@ void whenExecuteEstimateGasWithInputParameter_callExecutorWithInput() { config.getGasEstimationCap(), config.getCallGasCap()); - eth.estimateGas(args); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + + eth.estimateGas(callArgumentsParam); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(reversibleTransactionExecutor, times(1)) @@ -608,7 +622,9 @@ void whenExecuteEstimateGasWithInputAndDataParameters_callExecutorWithInput() { config.getGasEstimationCap(), config.getCallGasCap()); - eth.estimateGas(args); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + + eth.estimateGas(callArgumentsParam); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(reversibleTransactionExecutor, times(1)) @@ -640,7 +656,9 @@ void whenExecuteSendTransactionWithDataParameter_callExecutorWithData() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); - ethModuleTransaction.sendTransaction(args); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + + ethModuleTransaction.sendTransaction(callArgumentsParam); ArgumentCaptor transactionCaptor = ArgumentCaptor.forClass(Transaction.class); verify(transactionGateway, times(1)) @@ -672,7 +690,9 @@ void whenExecuteSendTransactionWithInputParameter_callExecutorWithInput() { EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); - ethModuleTransaction.sendTransaction(args); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + + ethModuleTransaction.sendTransaction(callArgumentsParam); ArgumentCaptor transactionCaptor = ArgumentCaptor.forClass(Transaction.class); verify(transactionGateway, times(1)) @@ -705,7 +725,9 @@ void whenExecuteSendTransactionWithInputAndDataParameters_callExecutorWithInput( EthModuleTransactionBase ethModuleTransaction = new EthModuleTransactionBase(constants, wallet, transactionPool, transactionGateway); - ethModuleTransaction.sendTransaction(args); + CallArgumentsParam callArgumentsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + + ethModuleTransaction.sendTransaction(callArgumentsParam); ArgumentCaptor transactionCaptor = ArgumentCaptor.forClass(Transaction.class); verify(transactionGateway, times(1)) From 5131f49cf2405379293b9bdb1d5c0e65743e897b Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Mon, 11 Sep 2023 19:05:57 -0400 Subject: [PATCH 30/47] Update methods argument classes --- .../main/java/co/rsk/rpc/Web3EthModule.java | 5 +- .../rpc/modules/personal/PersonalModule.java | 15 ++- .../PersonalModuleWalletDisabled.java | 15 ++- .../personal/PersonalModuleWalletEnabled.java | 29 +++-- .../src/main/java/org/ethereum/rpc/Web3.java | 14 ++- .../main/java/org/ethereum/rpc/Web3Impl.java | 30 +++-- .../rpc/parameters/HexDurationParam.java | 6 +- .../rpc/parameters/HexStringParam.java | 4 + .../modules/personal/PersonalModuleTest.java | 11 +- .../PersonalModuleWalletEnabledTest.java | 7 +- .../java/org/ethereum/rpc/Web3ImplTest.java | 105 +++++++++++++----- .../org/ethereum/rpc/Web3ImplUnitTest.java | 32 ++++-- 12 files changed, 191 insertions(+), 82 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index 12599b36203..db5e2b1778d 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -31,6 +31,7 @@ import org.ethereum.rpc.parameters.HexAddressParam; import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.rpc.parameters.HexIndexParam; +import org.ethereum.rpc.parameters.HexNumberParam; import org.ethereum.rpc.parameters.TxHashParam; import java.math.BigInteger; @@ -84,9 +85,7 @@ default String eth_chainId() { String eth_getBalance(HexAddressParam address) throws Exception; - String eth_getStorageAt(String address, String storageIdx, Map blockRef) throws Exception; // NOSONAR - - String eth_getStorageAt(String address, String storageIdx, String blockId) throws Exception; + String eth_getStorageAt(HexAddressParam address, HexNumberParam storageIdx, BlockRefParam blockRefParam) throws Exception; String eth_getTransactionCount(HexAddressParam address, BlockRefParam blockRefParam) throws Exception; diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModule.java b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModule.java index 62b5cbd8f4d..af1102c80f7 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModule.java @@ -18,24 +18,27 @@ package co.rsk.rpc.modules.personal; -import org.ethereum.rpc.CallArguments; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDurationParam; +import org.ethereum.rpc.parameters.HexKeyParam; public interface PersonalModule { - String dumpRawKey(String address) throws Exception; + String dumpRawKey(HexAddressParam address) throws Exception; - String importRawKey(String key, String passphrase); + String importRawKey(HexKeyParam key, String passphrase); void init(); String[] listAccounts(); - boolean lockAccount(String address); + boolean lockAccount(HexAddressParam address); String newAccountWithSeed(String seed); String newAccount(String passphrase); - String sendTransaction(CallArguments args, String passphrase) throws Exception; + String sendTransaction(CallArgumentsParam args, String passphrase) throws Exception; - boolean unlockAccount(String address, String passphrase, String duration); + boolean unlockAccount(HexAddressParam address, String passphrase, HexDurationParam duration); } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletDisabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletDisabled.java index 0379c0fe5c1..616b912b2d4 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletDisabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletDisabled.java @@ -18,8 +18,11 @@ package co.rsk.rpc.modules.personal; -import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.DisabledWalletException; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDurationParam; +import org.ethereum.rpc.parameters.HexKeyParam; public class PersonalModuleWalletDisabled implements PersonalModule { @Override @@ -45,27 +48,27 @@ public String[] listAccounts() { } @Override - public String importRawKey(String key, String passphrase) { + public String importRawKey(HexKeyParam key, String passphrase) { throw new DisabledWalletException(); } @Override - public String sendTransaction(CallArguments args, String passphrase) { + public String sendTransaction(CallArgumentsParam args, String passphrase) { throw new DisabledWalletException(); } @Override - public boolean unlockAccount(String address, String passphrase, String duration) { + public boolean unlockAccount(HexAddressParam address, String passphrase, HexDurationParam duration) { throw new DisabledWalletException(); } @Override - public boolean lockAccount(String address) { + public boolean lockAccount(HexAddressParam address) { throw new DisabledWalletException(); } @Override - public String dumpRawKey(String address) { + public String dumpRawKey(HexAddressParam address) { throw new DisabledWalletException(); } } \ No newline at end of file diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java index 141319d7c6c..115a7a15005 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java @@ -29,12 +29,17 @@ import org.ethereum.facade.Ethereum; import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDurationParam; +import org.ethereum.rpc.parameters.HexKeyParam; import org.ethereum.util.ByteUtil; import org.ethereum.util.TransactionArgumentsUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; +import java.util.Optional; import static org.ethereum.rpc.exception.RskJsonRpcRequestException.invalidParamError; @@ -121,8 +126,9 @@ public String[] listAccounts() { } @Override - public String importRawKey(String key, String passphrase) { + public String importRawKey(HexKeyParam keyParam, String passphrase) { String s = null; + String key = Optional.ofNullable(keyParam).map(HexKeyParam::getHexKey).orElse(null); try { if (key != null && key.startsWith("0x")) { key = key.substring(2); @@ -136,8 +142,9 @@ public String importRawKey(String key, String passphrase) { } @Override - public String sendTransaction(CallArguments args, String passphrase) throws Exception { + public String sendTransaction(CallArgumentsParam argsParam, String passphrase) throws Exception { String s = null; + CallArguments args = argsParam.toCallArguments(); try { return s = sendTransaction(args, getAccount(args.getFrom(), passphrase)); } finally { @@ -146,15 +153,15 @@ public String sendTransaction(CallArguments args, String passphrase) throws Exce } @Override - public boolean unlockAccount(String address, String passphrase, String duration) { - return unlockAccount(new RskAddress(address), passphrase, duration); + public boolean unlockAccount(HexAddressParam address, String passphrase, HexDurationParam duration) { + return unlockAccount(address.getAddress(), passphrase, duration); } - private boolean unlockAccount(RskAddress addr, String passphrase, String duration) { + private boolean unlockAccount(RskAddress addr, String passphrase, HexDurationParam duration) { long dur = (long) 1000 * 60 * 30; - if (duration != null && duration.length() > 0) { + if (duration != null && duration.getDuration() != null) { try { - dur = convertFromJsonHexToLong(duration); + dur = duration.getDuration(); } catch (Exception e) { throw invalidParamError("Can't parse duration param", e); } @@ -164,15 +171,15 @@ private boolean unlockAccount(RskAddress addr, String passphrase, String duratio } @Override - public boolean lockAccount(String address) { - return this.wallet.lockAccount(new RskAddress(address)); + public boolean lockAccount(HexAddressParam address) { + return this.wallet.lockAccount(address.getAddress()); } @Override - public String dumpRawKey(String address) throws Exception { + public String dumpRawKey(HexAddressParam address) throws Exception { String s = null; try { - Account account = wallet.getAccount(new RskAddress(convertFromJsonHexToHex(address))); + Account account = wallet.getAccount(address.getAddress()); if (account == null) { throw new Exception("Address private key is locked or could not be found in this node"); } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3.java index a27803107e9..8b16c98019b 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3.java @@ -30,6 +30,10 @@ import co.rsk.rpc.Web3TxPoolModule; import co.rsk.scoring.PeerScoringInformation; import co.rsk.scoring.PeerScoringReputationSummary; +import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDurationParam; +import org.ethereum.rpc.parameters.HexKeyParam; @java.lang.SuppressWarnings("squid:S100") public interface Web3 extends InternalService, Web3TxPoolModule, Web3EthModule, Web3EvmModule, Web3MnrModule, Web3DebugModule, Web3TraceModule, Web3RskModule { @@ -54,11 +58,11 @@ public interface Web3 extends InternalService, Web3TxPoolModule, Web3EthModule, String personal_newAccountWithSeed(String seed); String personal_newAccount(String passphrase); String[] personal_listAccounts(); - String personal_importRawKey(String key, String passphrase); - String personal_sendTransaction(CallArguments transactionArgs, String passphrase) throws Exception; - boolean personal_unlockAccount(String key, String passphrase, String duration); - boolean personal_lockAccount(String key); - String personal_dumpRawKey(String address) throws Exception; + String personal_importRawKey(HexKeyParam key, String passphrase); + String personal_sendTransaction(CallArgumentsParam transactionArgs, String passphrase) throws Exception; + boolean personal_unlockAccount(HexAddressParam key, String passphrase, HexDurationParam duration); + boolean personal_lockAccount(HexAddressParam key); + String personal_dumpRawKey(HexAddressParam address) throws Exception; void sco_banAddress(String address); void sco_unbanAddress(String address); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index f6a5e6f8e79..e52cd91e58d 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -65,7 +65,10 @@ import org.ethereum.rpc.parameters.BlockRefParam; import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexDurationParam; import org.ethereum.rpc.parameters.HexIndexParam; +import org.ethereum.rpc.parameters.HexKeyParam; +import org.ethereum.rpc.parameters.HexNumberParam; import org.ethereum.rpc.parameters.TxHashParam; import org.ethereum.util.BuildInfo; import org.ethereum.vm.DataWord; @@ -458,22 +461,29 @@ public String eth_getBalance(HexAddressParam address) { } @Override - public String eth_getStorageAt(String address, String storageIdx, Map blockRef) { + public String eth_getStorageAt(HexAddressParam address, HexNumberParam storageIdx, BlockRefParam blockRefParam) { + if(blockRefParam.getIdentifier() != null) { + return this.eth_getStorageAt(address, storageIdx, blockRefParam.getIdentifier()); + } else { + return this.eth_getStorageAt(address, storageIdx, blockRefParam.getInputs()); + } + } + + private String eth_getStorageAt(HexAddressParam address, HexNumberParam storageIdx, Map blockRef) { return invokeByBlockRef(blockRef, blockNumber -> this.eth_getStorageAt(address, storageIdx, blockNumber)); } - @Override - public String eth_getStorageAt(String address, String storageIdx, String blockId) { + private String eth_getStorageAt(HexAddressParam address, HexNumberParam storageIdx, String blockId) { String s = null; try { - RskAddress addr = new RskAddress(address); + RskAddress addr = address.getAddress(); AccountInformationProvider accountInformationProvider = web3InformationRetriever.getInformationProvider(blockId); DataWord sv = accountInformationProvider - .getStorageValue(addr, DataWord.valueOf(HexUtils.strHexOrStrNumberToByteArray(storageIdx))); + .getStorageValue(addr, DataWord.valueOf(HexUtils.strHexOrStrNumberToByteArray(storageIdx.getHexNumber()))); if (sv == null) { s = "0x0"; @@ -1071,12 +1081,12 @@ public String personal_newAccount(String passphrase) { } @Override - public String personal_importRawKey(String key, String passphrase) { + public String personal_importRawKey(HexKeyParam key, String passphrase) { return personalModule.importRawKey(key, passphrase); } @Override - public String personal_dumpRawKey(String address) throws Exception { + public String personal_dumpRawKey(HexAddressParam address) throws Exception { return personalModule.dumpRawKey(address); } @@ -1086,17 +1096,17 @@ public String[] personal_listAccounts() { } @Override - public String personal_sendTransaction(CallArguments args, String passphrase) throws Exception { + public String personal_sendTransaction(CallArgumentsParam args, String passphrase) throws Exception { return personalModule.sendTransaction(args, passphrase); } @Override - public boolean personal_unlockAccount(String address, String passphrase, String duration) { + public boolean personal_unlockAccount(HexAddressParam address, String passphrase, HexDurationParam duration) { return personalModule.unlockAccount(address, passphrase, duration); } @Override - public boolean personal_lockAccount(String address) { + public boolean personal_lockAccount(HexAddressParam address) { return personalModule.lockAccount(address); } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java index 5f036b65b2d..aea668b9cff 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java @@ -14,7 +14,11 @@ public class HexDurationParam extends HexStringParam { public HexDurationParam(String hexDurationStr) { super(hexDurationStr); - this.duration = Long.parseLong(hexDurationStr.substring(2), 16); + if(hexDurationStr.isEmpty()) { + this.duration = null; + } else { + this.duration = Long.parseLong(hexDurationStr.substring(2), 16); + } } public Long getDuration() { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java index ef3dcc4874a..fe6f5572ea3 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java @@ -5,6 +5,10 @@ public abstract class HexStringParam { HexStringParam(String hexString) { + if(hexString.isEmpty()) { + return; + } + if (!HexUtils.hasHexPrefix(hexString) || !HexUtils.isHex(hexString,2)) { throw RskJsonRpcRequestException.invalidParamError("Invalid argument \"" + hexString + "\": param should be a hex value string."); } diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleTest.java index 365dcdf6dc7..efcb16201a3 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleTest.java @@ -31,14 +31,11 @@ import org.ethereum.facade.Ethereum; import org.ethereum.rpc.CallArguments; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.util.TransactionFactoryHelper; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - class PersonalModuleTest { private static final String PASS_FRASE = "passfrase"; @@ -54,6 +51,7 @@ void sendTransactionWithGasLimitTest() throws Exception { // Hash of the expected transaction CallArguments args = TransactionFactoryHelper.createArguments(sender, receiver); + CallArgumentsParam argsParam = TransactionFactoryHelper.toCallArgumentsParam(args); Transaction tx = TransactionFactoryHelper.createTransaction(args, props.getNetworkConstants().getChainId(), wallet.getAccount(sender, PASS_FRASE)); String txExpectedResult = tx.getHash().toJsonString(); @@ -66,7 +64,7 @@ void sendTransactionWithGasLimitTest() throws Exception { PersonalModuleWalletEnabled personalModuleWalletEnabled = new PersonalModuleWalletEnabled(props, ethereum, wallet, null); // Hash of the actual transaction builded inside the sendTransaction - String txResult = personalModuleWalletEnabled.sendTransaction(args, PASS_FRASE); + String txResult = personalModuleWalletEnabled.sendTransaction(argsParam, PASS_FRASE); assertEquals(txExpectedResult, txResult); } @@ -83,6 +81,7 @@ void sendTransactionThrowsErrorOnChainIdValidationTest() { // Hash of the expected transaction CallArguments args = TransactionFactoryHelper.createArguments(sender, receiver); args.setChainId("" + ((int) props.getNetworkConstants().getChainId() - 2)); + CallArgumentsParam argsParam = TransactionFactoryHelper.toCallArgumentsParam(args); TransactionPoolAddResult transactionPoolAddResult = mock(TransactionPoolAddResult.class); when(transactionPoolAddResult.transactionsWereAdded()).thenReturn(true); @@ -91,7 +90,7 @@ void sendTransactionThrowsErrorOnChainIdValidationTest() { PersonalModuleWalletEnabled personalModuleWalletEnabled = new PersonalModuleWalletEnabled(props, ethereum, wallet, null); - Assertions.assertThrows(RskJsonRpcRequestException.class, () -> personalModuleWalletEnabled.sendTransaction(args, PASS_FRASE)); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> personalModuleWalletEnabled.sendTransaction(argsParam, PASS_FRASE)); } } diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabledTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabledTest.java index 6a76c6a34d5..fff87a50406 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabledTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabledTest.java @@ -6,6 +6,7 @@ import org.bouncycastle.util.encoders.DecoderException; import org.bouncycastle.util.encoders.Hex; import org.ethereum.crypto.ECKey; +import org.ethereum.rpc.parameters.HexKeyParam; import org.ethereum.util.ByteUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -43,7 +44,8 @@ void importRawKey_KeyContains0xPrefix_OK() { doReturn(true).when(walletMock).unlockAccount(eq(addressMock), eq(passphrase), any(Long.class)); PersonalModuleWalletEnabled personalModuleWalletEnabled = createPersonalModuleWalletEnabled(walletMock); - String result = personalModuleWalletEnabled.importRawKey(String.format("0x%s", rawKey), passphrase); + HexKeyParam hexKeyParam = new HexKeyParam(String.format("0x%s", rawKey)); + String result = personalModuleWalletEnabled.importRawKey(hexKeyParam, passphrase); verify(walletMock, times(1)).addAccountWithPrivateKey(hexDecodedKey, passphrase); verify(walletMock, times(1)).unlockAccount(addressMock, passphrase, 1800000L); @@ -67,7 +69,8 @@ void importRawKey_KeyDoesNotContains0xPrefix_OK() { doReturn(true).when(walletMock).unlockAccount(eq(addressMock), eq(passphrase), any(Long.class)); PersonalModuleWalletEnabled personalModuleWalletEnabled = createPersonalModuleWalletEnabled(walletMock); - String result = personalModuleWalletEnabled.importRawKey(rawKey, passphrase); + HexKeyParam hexKeyParam = new HexKeyParam(rawKey); + String result = personalModuleWalletEnabled.importRawKey(hexKeyParam, passphrase); verify(walletMock, times(1)).addAccountWithPrivateKey(hexDecodedKey, passphrase); verify(walletMock, times(1)).unlockAccount(addressMock, passphrase, 1800000L); 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 edcddac18d4..ff8c5c5737a 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -83,7 +83,10 @@ import org.ethereum.rpc.parameters.CallArgumentsParam; import org.ethereum.rpc.parameters.HexAddressParam; import org.ethereum.rpc.parameters.HexDataParam; +import org.ethereum.rpc.parameters.HexDurationParam; import org.ethereum.rpc.parameters.HexIndexParam; +import org.ethereum.rpc.parameters.HexKeyParam; +import org.ethereum.rpc.parameters.HexNumberParam; import org.ethereum.rpc.parameters.TxHashParam; import org.ethereum.util.BuildInfo; import org.ethereum.util.ByteUtil; @@ -372,21 +375,30 @@ void getBalanceWithAccountAndBlockWithTransaction() { //[ "0x
", { "blockNumber": "0x0" } -> return storage at given address in genesis block void getStorageAtAccountAndBlockNumber() { final ChainParams chain = chainWithAccount10kBalance(false); - assertByBlockNumber("0x0", blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertByBlockNumber("0x0", blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return storage at given address in genesis block void getStorageAtAccountAndBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); - assertByBlockHash("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertByBlockHash("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getStorageAtAccountAndNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonExistentBlockHash(blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertNonExistentBlockHash(blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @@ -394,49 +406,70 @@ void getStorageAtAccountAndNonExistentBlockHash() { //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void getStorageAtAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void getStorageAtAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getStorageAtAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return storage at given address in genesis block void getStorageAtAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertCanonicalBlockHashWhenCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertCanonicalBlockHashWhenCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return storage at given address in genesis block void getStorageAtAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertCanonicalBlockHashWhenNotCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertCanonicalBlockHashWhenNotCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return storage at given address in specified block void getStorageAtAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHashWhenNotCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertNonCanonicalBlockHashWhenNotCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x" } -> return storage at given address in specified bloc void getStorageAtAccountAndNonCanonicalBlockHash() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHash("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt(chain.accountAddress, "0x0", blockRef)); + assertNonCanonicalBlockHash("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( + new HexAddressParam(chain.accountAddress), + new HexNumberParam("0x0"), + new BlockRefParam(new BlockRef(blockRef)))); } @@ -2058,7 +2091,9 @@ void importAccountUsingRawKey() { assertNull(account); - String address = web3.personal_importRawKey(ByteUtil.toHexString(privKeyBytes), "passphrase1"); + HexKeyParam hexKeyParam = new HexKeyParam(ByteUtil.toHexString(privKeyBytes)); + + String address = web3.personal_importRawKey(hexKeyParam, "passphrase1"); assertNotNull(address); @@ -2085,7 +2120,9 @@ void importAccountUsingRawKeyContaining0xPrefix() { assertNull(account); - String address = web3.personal_importRawKey(String.format("0x%s", ByteUtil.toHexString(privKeyBytes)), "passphrase1"); + HexKeyParam hexKeyParam = new HexKeyParam(String.format("0x%s", ByteUtil.toHexString(privKeyBytes))); + + String address = web3.personal_importRawKey(hexKeyParam, "passphrase1"); assertNotNull(address); @@ -2102,10 +2139,14 @@ void dumpRawKey() throws Exception { ECKey eckey = new ECKey(); - String address = web3.personal_importRawKey(ByteUtil.toHexString(eckey.getPrivKeyBytes()), "passphrase1"); - assertTrue(web3.personal_unlockAccount(address, "passphrase1", "")); + HexKeyParam hexKeyParam = new HexKeyParam(ByteUtil.toHexString(eckey.getPrivKeyBytes())); + + String address = web3.personal_importRawKey(hexKeyParam, "passphrase1"); + HexAddressParam hexAddressParam = new HexAddressParam(address); + + assertTrue(web3.personal_unlockAccount(hexAddressParam, "passphrase1", new HexDurationParam(""))); - String rawKey = web3.personal_dumpRawKey(address).substring(2); + String rawKey = web3.personal_dumpRawKey(hexAddressParam).substring(2); assertArrayEquals(eckey.getPrivKeyBytes(), Hex.decode(rawKey)); } @@ -2116,10 +2157,14 @@ void dumpRawKeyContaining0xPrefix() throws Exception { ECKey eckey = new ECKey(); - String address = web3.personal_importRawKey(String.format("0x%s", ByteUtil.toHexString(eckey.getPrivKeyBytes())), "passphrase1"); - assertTrue(web3.personal_unlockAccount(address, "passphrase1", "")); + HexKeyParam hexKeyParam = new HexKeyParam(String.format("0x%s", ByteUtil.toHexString(eckey.getPrivKeyBytes()))); - String rawKey = web3.personal_dumpRawKey(address).substring(2); + String address = web3.personal_importRawKey(hexKeyParam, "passphrase1"); + HexAddressParam hexAddressParam = new HexAddressParam(address); + + assertTrue(web3.personal_unlockAccount(hexAddressParam, "passphrase1", new HexDurationParam(""))); + + String rawKey = web3.personal_dumpRawKey(hexAddressParam).substring(2); assertArrayEquals(eckey.getPrivKeyBytes(), Hex.decode(rawKey)); } @@ -2151,6 +2196,8 @@ void sendPersonalTransaction() throws Exception { args.setNonce(nonce.toString()); args.setChainId(HexUtils.toJsonHex(new byte[]{chainId})); + CallArgumentsParam argsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + // ***** Verifies tx hash Transaction expectedTx = Transaction .builder() @@ -2170,7 +2217,7 @@ void sendPersonalTransaction() throws Exception { when(ethereumMock.submitTransaction(expectedTx)).thenReturn(pendingTransactionResult); // ***** Executes the transaction ******************* - String txHash = web3.personal_sendTransaction(args, "passphrase1"); + String txHash = web3.personal_sendTransaction(argsParam, "passphrase1"); // ***** Checking expected result ******************* @@ -2201,6 +2248,8 @@ void sendPersonalTransactionFailsIfTransactionIsNotQueued() { args.setValue(value.toString()); args.setNonce(nonce.toString()); + CallArgumentsParam argsParam = TransactionFactoryHelper.toCallArgumentsParam(args); + Transaction expectedTx = Transaction .builder() .destination(toAddress.substring(2)) @@ -2219,7 +2268,7 @@ void sendPersonalTransactionFailsIfTransactionIsNotQueued() { // ***** Executes the transaction ******************* RskJsonRpcRequestException thrownEx = Assertions.assertThrows(RskJsonRpcRequestException.class, () -> { - web3.personal_sendTransaction(args, "passphrase1"); + web3.personal_sendTransaction(argsParam, "passphrase1"); }); assertEquals(-32010, thrownEx.getCode(), "Unexpected exception code"); @@ -2233,9 +2282,11 @@ void unlockAccount() { String addr = web3.personal_newAccount("passphrase1"); - web3.personal_lockAccount(addr); + HexAddressParam hexAddressParam = new HexAddressParam(addr); - assertTrue(web3.personal_unlockAccount(addr, "passphrase1", "")); + web3.personal_lockAccount(hexAddressParam); + + assertTrue(web3.personal_unlockAccount(hexAddressParam, "passphrase1", new HexDurationParam(""))); Account account = wallet.getAccount(new RskAddress(addr)); @@ -2248,10 +2299,12 @@ void unlockAccountInvalidDuration() { String addr = web3.personal_newAccount("passphrase1"); - web3.personal_lockAccount(addr); + HexAddressParam hexAddressParam = new HexAddressParam(addr); + + web3.personal_lockAccount(hexAddressParam); RskJsonRpcRequestException e = TestUtils.assertThrows(RskJsonRpcRequestException.class, - () -> web3.personal_unlockAccount(addr, "passphrase1", "K")); + () -> web3.personal_unlockAccount(hexAddressParam, "passphrase1", new HexDurationParam("K"))); assertEquals(-32602, (int) e.getCode()); } @@ -2265,7 +2318,9 @@ void lockAccount() { assertNotNull(account); - assertTrue(web3.personal_lockAccount(addr)); + HexAddressParam hexAddressParam = new HexAddressParam(addr); + + assertTrue(web3.personal_lockAccount(hexAddressParam)); Account account1 = wallet.getAccount(new RskAddress(addr)); diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java index 8b7f3b3f8b5..a687120b11c 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java @@ -27,6 +27,7 @@ import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockRefParam; import org.ethereum.rpc.parameters.HexAddressParam; +import org.ethereum.rpc.parameters.HexNumberParam; import org.ethereum.util.BuildInfo; import org.ethereum.util.TransactionFactoryHelper; import org.ethereum.vm.DataWord; @@ -140,31 +141,39 @@ void eth_getBalanceByBlockRef() { @Test void eth_getStorageAt_stateCannotBeRetrieved() { - String id = "id"; + String id = "0x00"; String addr = "0x0011223344556677880011223344556677889900"; String storageIdx = "0x01"; + HexAddressParam hexAddressParam = new HexAddressParam(addr); + HexNumberParam hexNumberParam = new HexNumberParam(storageIdx); + BlockRefParam blockRefParam = new BlockRefParam(new BlockRef(id)); + when(retriever.getInformationProvider(id)) .thenThrow(RskJsonRpcRequestException.blockNotFound("Block not found")); TestUtils.assertThrows(RskJsonRpcRequestException.class, - () -> target.eth_getStorageAt(addr, storageIdx, id)); + () -> target.eth_getStorageAt(hexAddressParam, hexNumberParam, blockRefParam)); } @Test void eth_getStorageAt() { - String id = "id"; + String id = "0x00"; String addr = "0x0011223344556677880011223344556677889900"; RskAddress expectedAddress = new RskAddress(addr); String storageIdx = "0x01"; DataWord expectedIdx = DataWord.valueOf(HexUtils.stringHexToByteArray(storageIdx)); + HexAddressParam hexAddressParam = new HexAddressParam(addr); + HexNumberParam hexNumberParam = new HexNumberParam(storageIdx); + BlockRefParam blockRefParam = new BlockRefParam(new BlockRef(id)); + AccountInformationProvider aip = mock(AccountInformationProvider.class); when(retriever.getInformationProvider(id)).thenReturn(aip); when(aip.getStorageValue(expectedAddress, expectedIdx)) .thenReturn(DataWord.ONE); - String result = target.eth_getStorageAt(addr, storageIdx, id); + String result = target.eth_getStorageAt(hexAddressParam, hexNumberParam, blockRefParam); assertEquals("0x0000000000000000000000000000000000000000000000000000000000000001", result); } @@ -181,8 +190,13 @@ void eth_getStorageAtByBlockRef() { }; final Web3Impl spyTarget = spy(target); final String expectedData = "0x0000000000000000000000000000000000000000000000000000000000000001"; + + HexAddressParam hexAddressParam = new HexAddressParam(addr); + HexNumberParam hexNumberParam = new HexNumberParam(storageIdx); + BlockRefParam blockRefParam = new BlockRefParam(new BlockRef(blockRef)); + doReturn(expectedData).when(spyTarget).invokeByBlockRef(eq(blockRef),any()); - String result = spyTarget.eth_getStorageAt(addr, storageIdx, blockRef); + String result = spyTarget.eth_getStorageAt(hexAddressParam, hexNumberParam, blockRefParam); assertEquals(expectedData, result); verify(spyTarget).invokeByBlockRef(eq(blockRef),any()); } @@ -190,18 +204,22 @@ void eth_getStorageAtByBlockRef() { @Test void eth_getStorageAtEmptyCell() { - String id = "id"; + String id = "0x00"; String addr = "0x0011223344556677880011223344556677889900"; RskAddress expectedAddress = new RskAddress(addr); String storageIdx = "0x01"; DataWord expectedIdx = DataWord.valueOf(HexUtils.stringHexToByteArray(storageIdx)); + HexAddressParam hexAddressParam = new HexAddressParam(addr); + HexNumberParam hexNumberParam = new HexNumberParam(storageIdx); + BlockRefParam blockRefParam = new BlockRefParam(new BlockRef(id)); + AccountInformationProvider aip = mock(AccountInformationProvider.class); when(retriever.getInformationProvider(id)).thenReturn(aip); when(aip.getStorageValue(expectedAddress, expectedIdx)) .thenReturn(null); - String result = target.eth_getStorageAt(addr, storageIdx, id); + String result = target.eth_getStorageAt(hexAddressParam, hexNumberParam, blockRefParam); assertEquals("0x0", result); } From aefe3d76aee304c6404348760eceb9e017c2c155 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Tue, 12 Sep 2023 12:47:38 -0400 Subject: [PATCH 31/47] Remove unused methods --- .../personal/PersonalModuleWalletEnabled.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java index 115a7a15005..544b6d90f54 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java @@ -216,19 +216,4 @@ private String sendTransaction(CallArguments args, Account senderAccount) throws } return tx.getHash().toJsonString(); } - - private String convertFromJsonHexToHex(String x) throws Exception { - if (!x.startsWith("0x")) { - throw new Exception("Incorrect hex syntax"); - } - - return x.substring(2); - } - - private long convertFromJsonHexToLong(String x) throws Exception { - if (!x.startsWith("0x")) { - throw new Exception("Incorrect hex syntax"); - } - return Long.parseLong(x.substring(2), 16); - } } From c717e6269814cbdeaab681c77ca9dd2bd3d32f5f Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 14 Sep 2023 08:44:04 -0400 Subject: [PATCH 32/47] Update methods arguments types --- .../main/java/co/rsk/rpc/Web3EthModule.java | 18 +++---- .../co/rsk/rpc/modules/eth/EthModule.java | 6 +-- .../main/java/org/ethereum/rpc/Web3Impl.java | 41 +++++++++++----- .../rpc/parameters/HexStringParam.java | 2 +- .../co/rsk/rpc/modules/eth/EthModuleTest.java | 4 +- .../java/org/ethereum/rpc/Web3ImplTest.java | 48 +++++++++---------- .../org/ethereum/rpc/Web3ImplUnitTest.java | 24 +++++----- 7 files changed, 81 insertions(+), 62 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index db5e2b1778d..289a7a47352 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -91,18 +91,18 @@ default String eth_chainId() { String eth_getBlockTransactionCountByHash(BlockHashParam blockHash)throws Exception; - String eth_getBlockTransactionCountByNumber(String bnOrId)throws Exception; + String eth_getBlockTransactionCountByNumber(BlockIdentifierParam bnOrId)throws Exception; - String eth_getUncleCountByBlockHash(String blockHash)throws Exception; + String eth_getUncleCountByBlockHash(BlockHashParam blockHash)throws Exception; - String eth_getUncleCountByBlockNumber(String bnOrId)throws Exception; + String eth_getUncleCountByBlockNumber(BlockIdentifierParam bnOrId)throws Exception; - default String eth_getCode(String address, String blockId) { + String eth_getCode(HexAddressParam address, BlockRefParam blockRefParam) throws Exception; + + default String getCode(HexAddressParam address, String blockId) { return getEthModule().getCode(address, blockId); } - String eth_getCode(String address, Map blockRef) throws Exception; // NOSONAR - default String eth_sendRawTransaction(HexDataParam rawData) { return getEthModule().sendRawTransaction(rawData); } @@ -113,19 +113,19 @@ default String eth_sendTransaction(CallArgumentsParam args) { BlockResultDTO eth_getBlockByHash(BlockHashParam blockHash, Boolean fullTransactionObjects) throws Exception; - BlockResultDTO eth_getBlockByNumber(String bnOrId, Boolean fullTransactionObjects) throws Exception; + BlockResultDTO eth_getBlockByNumber(BlockIdentifierParam bnOrId, Boolean fullTransactionObjects) throws Exception; TransactionResultDTO eth_getTransactionByHash(TxHashParam transactionHash) throws Exception; TransactionResultDTO eth_getTransactionByBlockHashAndIndex(BlockHashParam blockHash, HexIndexParam index) throws Exception; - TransactionResultDTO eth_getTransactionByBlockNumberAndIndex(String bnOrId, String index) throws Exception; + TransactionResultDTO eth_getTransactionByBlockNumberAndIndex(BlockIdentifierParam bnOrId, HexIndexParam index) throws Exception; TransactionReceiptDTO eth_getTransactionReceipt(TxHashParam transactionHash) throws Exception; BlockResultDTO eth_getUncleByBlockHashAndIndex(BlockHashParam blockHash, HexIndexParam uncleIdx) throws Exception; - BlockResultDTO eth_getUncleByBlockNumberAndIndex(String blockId, String uncleIdx) throws Exception; + BlockResultDTO eth_getUncleByBlockNumberAndIndex(BlockIdentifierParam blockId, HexIndexParam uncleIdx) throws Exception; String[] eth_getCompilers(); diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java index 92ff0febc7a..3b5166534c0 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java @@ -217,14 +217,14 @@ public String chainId() { return HexUtils.toJsonHex(new byte[]{chainId}); } - public String getCode(String address, String blockId) { + public String getCode(HexAddressParam address, String blockId) { if (blockId == null) { throw new NullPointerException(); } String s = null; + RskAddress addr = address.getAddress(); try { - RskAddress addr = new RskAddress(address); AccountInformationProvider accountInformationProvider = getAccountInformationProvider(blockId); @@ -242,7 +242,7 @@ public String getCode(String address, String blockId) { return s; } finally { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("eth_getCode({}, {}): {}", address, blockId, s); + LOGGER.debug("eth_getCode({}, {}): {}", addr.toHexString(), blockId, s); } } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index e52cd91e58d..7f9de9a7da1 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -413,8 +413,16 @@ public String eth_call(CallArgumentsParam args, Map inputs) { } @Override - public String eth_getCode(String address, Map inputs) { - return invokeByBlockRef(inputs, blockNumber -> this.eth_getCode(address, blockNumber)); + public String eth_getCode(HexAddressParam address, BlockRefParam blockRefParam) { + if (blockRefParam.getIdentifier() != null) { + return this.getCode(address, blockRefParam.getIdentifier()); + } else { + return this.eth_getCode(address, blockRefParam.getInputs()); + } + } + + private String eth_getCode(HexAddressParam address, Map inputs) { + return invokeByBlockRef(inputs, blockNumber -> this.getCode(address, blockNumber)); } @Override @@ -607,11 +615,11 @@ public static Block getBlockByNumberOrStr(String bnOrId, Blockchain blockchain) } @Override - public String eth_getBlockTransactionCountByNumber(String bnOrId) { + public String eth_getBlockTransactionCountByNumber(BlockIdentifierParam bnOrId) { String s = null; try { - List txs = web3InformationRetriever.getTransactions(bnOrId); + List txs = web3InformationRetriever.getTransactions(bnOrId.getIdentifier()); s = toQuantityJsonHex(txs.size()); return s; @@ -623,7 +631,8 @@ public String eth_getBlockTransactionCountByNumber(String bnOrId) { } @Override - public String eth_getUncleCountByBlockHash(String blockHash) { + public String eth_getUncleCountByBlockHash(BlockHashParam blockHashParam) { + String blockHash = blockHashParam.getHash().toString(); Block b = getBlockByJSonHash(blockHash); if (b == null) { throw blockNotFound(String.format("Block with hash %s not found", blockHash)); @@ -634,12 +643,13 @@ public String eth_getUncleCountByBlockHash(String blockHash) { } @Override - public String eth_getUncleCountByBlockNumber(String bnOrId) { - return web3InformationRetriever.getBlock(bnOrId) + public String eth_getUncleCountByBlockNumber(BlockIdentifierParam identifierParam) { + String bnorId = identifierParam.getIdentifier(); + return web3InformationRetriever.getBlock(bnorId) .map(Block::getUncleList) .map(List::size) .map(HexUtils::toQuantityJsonHex) - .orElseThrow(() -> blockNotFound(String.format("Block %s not found", bnOrId))); + .orElseThrow(() -> blockNotFound(String.format("Block %s not found", bnorId))); } public BlockInformationResult getBlockInformationResult(BlockInformation blockInformation) { @@ -694,8 +704,10 @@ public BlockResultDTO eth_getBlockByHash(BlockHashParam blockHash, Boolean fullT } @Override - public BlockResultDTO eth_getBlockByNumber(String bnOrId, Boolean fullTransactionObjects) { + public BlockResultDTO eth_getBlockByNumber(BlockIdentifierParam identifierParam, Boolean fullTransactionObjects) { BlockResultDTO s = null; + String bnOrId = identifierParam.getIdentifier(); + try { s = web3InformationRetriever.getBlock(bnOrId) @@ -783,15 +795,16 @@ public TransactionResultDTO eth_getTransactionByBlockHashAndIndex(BlockHashParam } @Override - public TransactionResultDTO eth_getTransactionByBlockNumberAndIndex(String bnOrId, String index) { + public TransactionResultDTO eth_getTransactionByBlockNumberAndIndex(BlockIdentifierParam identifierParam, HexIndexParam index) { TransactionResultDTO s = null; + String bnOrId = identifierParam.getIdentifier(); try { Optional block = web3InformationRetriever.getBlock(bnOrId); if (!block.isPresent()) { return null; } - int idx = jsonHexToInt(index); + int idx = index.getIndex(); List txs = web3InformationRetriever.getTransactions(bnOrId); if (idx >= txs.size()) { return null; @@ -864,15 +877,17 @@ private BlockResultDTO getUncleResultDTO(Integer uncleIdx, Block block) { } @Override - public BlockResultDTO eth_getUncleByBlockNumberAndIndex(String blockId, String uncleIdx) { + public BlockResultDTO eth_getUncleByBlockNumberAndIndex(BlockIdentifierParam identifierParam, HexIndexParam uncleIdx) { BlockResultDTO s = null; + String blockId = identifierParam.getIdentifier(); + try { Optional block = web3InformationRetriever.getBlock(blockId); if (!block.isPresent()) { return null; } - int idx = jsonHexToInt(uncleIdx); + int idx = uncleIdx.getIndex(); s = getUncleResultDTO(idx, block.get()); return s; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java index fe6f5572ea3..1c8adce1c93 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java @@ -10,7 +10,7 @@ public abstract class HexStringParam { } if (!HexUtils.hasHexPrefix(hexString) || !HexUtils.isHex(hexString,2)) { - throw RskJsonRpcRequestException.invalidParamError("Invalid argument \"" + hexString + "\": param should be a hex value string."); + throw RskJsonRpcRequestException.invalidParamError("Invalid argument " + hexString + ": param should be a hex value string."); } } } diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java index 12a4c9a16d3..cd7aa34140f 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java @@ -38,6 +38,7 @@ import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.BlockIdentifierParam; import org.ethereum.rpc.parameters.CallArgumentsParam; +import org.ethereum.rpc.parameters.HexAddressParam; import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.util.ByteUtil; import org.ethereum.util.TransactionFactoryHelper; @@ -336,7 +337,8 @@ void getCode() { config.getCallGasCap() ); - String addr = eth.getCode(TestUtils.generateAddress("addr").toHexString(), "pending"); + HexAddressParam addressParam = new HexAddressParam(TestUtils.generateAddress("addr").toHexString()); + String addr = eth.getCode(addressParam, "pending"); MatcherAssert.assertThat(Hex.decode(addr.substring("0x".length())), is(expectedCode)); } 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 ff8c5c5737a..9eba6815883 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -477,70 +477,70 @@ void getStorageAtAccountAndNonCanonicalBlockHash() { //[ "0x
", { "blockNumber": "0x0" } -> return code at given address in genesis block void getCodeAtAccountAndBlockNumber() { final ChainParams chain = createChainWithAContractCode(false); - assertByBlockNumber("0x010203", blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertByBlockNumber("0x010203", blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return code at given address in genesis block void getCodeAtAccountAndBlockHash() { final ChainParams chain = createChainWithAContractCode(false); - assertByBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertByBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHash() { final ChainParams chain = createChainWithAContractCode(false); - assertNonExistentBlockHash(blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertNonExistentBlockHash(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(false); - assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(false); - assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getCodeAtAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(true); - assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return code at given address in genesis block void getCodeAtAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(false); - assertCanonicalBlockHashWhenCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertCanonicalBlockHashWhenCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return code at given address in genesis block void getCodeAtAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(false); - assertCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return code at given address in specified block void getCodeAtAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(true); - assertNonCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertNonCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test // [ "0x
", { "blockHash": "0x" } -> return code at given address in specified bloc void getCodeAtAccountAndNonCanonicalBlockHash() { final ChainParams chain = createChainWithAContractCode(true); - assertNonCanonicalBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(chain.accountAddress, blockRef)); + assertNonCanonicalBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); } @Test @@ -991,7 +991,7 @@ void getTransactionByBlockNumberAndIndex() { String hashString = tx.getHash().toHexString(); String blockHashString = block1.getHash().toHexString(); - TransactionResultDTO tr = web3.eth_getTransactionByBlockNumberAndIndex("0x01", "0x0"); + TransactionResultDTO tr = web3.eth_getTransactionByBlockNumberAndIndex(new BlockIdentifierParam("0x01"), new HexIndexParam("0x0")); assertNotNull(tr); assertEquals("0x" + hashString, tr.getHash()); @@ -1010,7 +1010,7 @@ void getUnknownTransactionByBlockNumberAndIndex() { world.getBlockStore()).trieStore(world.getTrieStore()).parent(genesis).build(); assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block1)); - TransactionResultDTO tr = web3.eth_getTransactionByBlockNumberAndIndex("0x1", "0x0"); + TransactionResultDTO tr = web3.eth_getTransactionByBlockNumberAndIndex(new BlockIdentifierParam("0x1"), new HexIndexParam("0x0")); Assertions.assertNull(tr); } @@ -1102,7 +1102,7 @@ void getBlockByNumber() { assertEquals(ImportResult.IMPORTED_NOT_BEST, world.getBlockChain().tryToConnect(block1b)); assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block2b)); - BlockResultDTO bresult = web3.eth_getBlockByNumber("0x1", false); + BlockResultDTO bresult = web3.eth_getBlockByNumber(new BlockIdentifierParam("0x1"), false); assertNotNull(bresult); @@ -1110,7 +1110,7 @@ void getBlockByNumber() { assertEquals(blockHash, bresult.getHash()); String bnOrId = "0x2"; - bresult = web3.eth_getBlockByNumber("0x2", true); + bresult = web3.eth_getBlockByNumber(new BlockIdentifierParam("0x2"), true); assertNotNull(bresult); @@ -1166,7 +1166,7 @@ void getBlockByNumberRetrieveLatestBlock() { block1.setBitcoinMergedMiningHeader(new byte[]{0x01}); assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block1)); - BlockResultDTO blockResult = web3.eth_getBlockByNumber("latest", false); + BlockResultDTO blockResult = web3.eth_getBlockByNumber(new BlockIdentifierParam("latest"), false); assertNotNull(blockResult); String blockHash = HexUtils.toJsonHex(block1.getHash().toString()); @@ -1186,7 +1186,7 @@ void getBlockByNumberRetrieveEarliestBlock() { assertEquals(ImportResult.IMPORTED_BEST, world.getBlockChain().tryToConnect(block1)); String bnOrId = "earliest"; - BlockResultDTO blockResult = web3.eth_getBlockByNumber(bnOrId, false); + BlockResultDTO blockResult = web3.eth_getBlockByNumber(new BlockIdentifierParam(bnOrId), false); assertNotNull(blockResult); @@ -1205,7 +1205,7 @@ void getBlockByNumberBlockDoesNotExists() { Web3Impl web3 = createWeb3(world); String bnOrId = "0x1234"; - BlockResultDTO blockResult = web3.eth_getBlockByNumber(bnOrId, false); + BlockResultDTO blockResult = web3.eth_getBlockByNumber(new BlockIdentifierParam(bnOrId), false); Assertions.assertNull(blockResult); @@ -1235,7 +1235,7 @@ void getBlockByNumberWhenNumberIsInvalidThrowsException() { String bnOrId = "991234"; - Assertions.assertThrows(org.ethereum.rpc.exception.RskJsonRpcRequestException.class, () -> web3.eth_getBlockByNumber(bnOrId, false)); + Assertions.assertThrows(org.ethereum.rpc.exception.RskJsonRpcRequestException.class, () -> web3.eth_getBlockByNumber(new BlockIdentifierParam(bnOrId), false)); } @Test @@ -1486,7 +1486,7 @@ void getBlockByNumberBlockWithUncles() { String block1cHashString = "0x" + block1c.getHash(); String block2HashString = "0x" + block2.getHash(); - BlockResultDTO result = web3.eth_getBlockByNumber("0x02", false); + BlockResultDTO result = web3.eth_getBlockByNumber(new BlockIdentifierParam("0x02"), false); assertEquals(block2HashString, result.getHash()); assertEquals(block1HashString, result.getParentHash()); @@ -1685,7 +1685,7 @@ void getUncleByBlockNumberAndIndexBlockWithUncles() { String blockBhash = "0x" + blockB.getHash(); String blockChash = "0x" + blockC.getHash(); - BlockResultDTO result = web3.eth_getUncleByBlockNumberAndIndex("0x03", "0x00"); + BlockResultDTO result = web3.eth_getUncleByBlockNumberAndIndex(new BlockIdentifierParam("0x03"), new HexIndexParam("0x00")); assertEquals(blockEhash, result.getHash()); assertEquals(2, result.getUncles().size()); @@ -1749,7 +1749,7 @@ void getUncleByBlockNumberAndIndexBlockWithUnclesCorrespondingToAnUnknownBlock() String blockEhash = "0x" + blockE.getHash(); - BlockResultDTO result = web3.eth_getUncleByBlockNumberAndIndex("0x" + blockF.getNumber(), "0x00"); + BlockResultDTO result = web3.eth_getUncleByBlockNumberAndIndex(new BlockIdentifierParam("0x" + blockF.getNumber()), new HexIndexParam("0x00")); assertEquals(blockEhash, result.getHash()); assertEquals(0, result.getUncles().size()); @@ -1776,7 +1776,7 @@ void getCode() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - String scode = web3.eth_getCode(accountAddress, "0x1"); + String scode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1"))); assertNotNull(scode); assertEquals("0x" + ByteUtil.toHexString(code), scode); @@ -1918,7 +1918,7 @@ void getCodeBlockDoesNotExist() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - String resultCode = web3.eth_getCode(accountAddress, "0x100"); + String resultCode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x100"))); assertNull(resultCode); } @@ -2436,7 +2436,7 @@ void getNoCode() throws Exception { String accountAddress = Hex.toHexString(acc1.getAddress().getBytes()); - String scode = web3.eth_getCode(accountAddress, "0x1"); + String scode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1"))); assertNotNull(scode); Assertions.assertEquals("0x", scode); diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java index a687120b11c..5d090af8968 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java @@ -25,6 +25,8 @@ import org.ethereum.net.server.ChannelManager; import org.ethereum.net.server.PeerServer; import org.ethereum.rpc.exception.RskJsonRpcRequestException; +import org.ethereum.rpc.parameters.BlockHashParam; +import org.ethereum.rpc.parameters.BlockIdentifierParam; import org.ethereum.rpc.parameters.BlockRefParam; import org.ethereum.rpc.parameters.HexAddressParam; import org.ethereum.rpc.parameters.HexNumberParam; @@ -226,24 +228,24 @@ void eth_getStorageAtEmptyCell() { @Test void eth_getBlockTransactionCountByNumber_blockNotFound() { - String id = "id"; + String id = "0x00"; when(retriever.getTransactions(id)).thenThrow(RskJsonRpcRequestException.blockNotFound("Block not found")); TestUtils.assertThrows(RskJsonRpcRequestException.class, - () -> target.eth_getBlockTransactionCountByNumber(id)); + () -> target.eth_getBlockTransactionCountByNumber(new BlockIdentifierParam(id))); } @Test void eth_getBlockTransactionCountByNumber() { - String id = "id"; + String id = "0x00"; List txs = new LinkedList<>(); txs.add(mock(Transaction.class)); txs.add(mock(Transaction.class)); when(retriever.getTransactions(id)).thenReturn(txs); - String result = target.eth_getBlockTransactionCountByNumber(id); + String result = target.eth_getBlockTransactionCountByNumber(new BlockIdentifierParam(id)); assertEquals("0x2", result); } @@ -260,7 +262,7 @@ void eth_getCode() { final Web3Impl spyTarget = spy(target); final String expectedData = "0x010203"; doReturn(expectedData).when(spyTarget).invokeByBlockRef(eq(blockRef),any()); - String result = spyTarget.eth_getCode(addr,blockRef); + String result = spyTarget.eth_getCode(new HexAddressParam(addr), new BlockRefParam(new BlockRef(blockRef))); assertEquals(expectedData, result); verify(spyTarget).invokeByBlockRef(eq(blockRef),any()); } @@ -310,7 +312,7 @@ void eth_getUncleCountByBlockHash_blockNotFound() { when(blockchain.getBlockByHash(bytesHash)).thenReturn(null); RskJsonRpcRequestException exception = TestUtils - .assertThrows(RskJsonRpcRequestException.class, () -> target.eth_getUncleCountByBlockHash(hash)); + .assertThrows(RskJsonRpcRequestException.class, () -> target.eth_getUncleCountByBlockHash(new BlockHashParam(hash))); assertEquals(-32602, (int) exception.getCode()); } @@ -329,22 +331,22 @@ void eth_getUncleCountByBlockHash() { when(block.getUncleList()).thenReturn(uncles); when(blockchain.getBlockByHash(bytesHash)).thenReturn(block); - String result = target.eth_getUncleCountByBlockHash(hash); + String result = target.eth_getUncleCountByBlockHash(new BlockHashParam(hash)); assertEquals("0x2", result); } @Test void eth_getUncleCountByBlockNumber_notFound() { - String identifier = "notFoundable"; + String identifier = "0x00"; when(retriever.getBlock(identifier)).thenReturn(Optional.empty()); TestUtils.assertThrows(RskJsonRpcRequestException.class, - () -> target.eth_getUncleCountByBlockNumber(identifier)); + () -> target.eth_getUncleCountByBlockNumber(new BlockIdentifierParam(identifier))); } @Test void eth_getUncleCountByBlockNumber() { - String identifier = "notFoundable"; + String identifier = "0x00"; Block block = mock(Block.class); List uncles = new LinkedList<>(); uncles.add(mock(BlockHeader.class)); @@ -353,7 +355,7 @@ void eth_getUncleCountByBlockNumber() { when(block.getUncleList()).thenReturn(uncles); when(retriever.getBlock(identifier)).thenReturn(Optional.of(block)); - String result = target.eth_getUncleCountByBlockNumber(identifier); + String result = target.eth_getUncleCountByBlockNumber(new BlockIdentifierParam(identifier)); assertEquals("0x2", result); } From 66589f9a7e3e02aec444567e2ee2e57b27068446 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 14 Sep 2023 09:57:13 -0400 Subject: [PATCH 33/47] Fix failing tests --- .../main/java/org/ethereum/rpc/parameters/HexStringParam.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java index 1c8adce1c93..7dfb5272fea 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java @@ -10,7 +10,7 @@ public abstract class HexStringParam { } if (!HexUtils.hasHexPrefix(hexString) || !HexUtils.isHex(hexString,2)) { - throw RskJsonRpcRequestException.invalidParamError("Invalid argument " + hexString + ": param should be a hex value string."); + throw RskJsonRpcRequestException.invalidParamError(String.format("Invalid argument \"%s\": param should be a hex value string.", hexString)); } } } From 50412d2bdcbbcee213a7efaddd69a259f672b643 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Mon, 18 Sep 2023 09:05:24 -0400 Subject: [PATCH 34/47] Addressing comments --- .../main/java/org/ethereum/rpc/BlockRef.java | 24 ----- .../rpc/parameters/BlockIdentifierParam.java | 4 + .../rpc/parameters/BlockRefParam.java | 69 ++++++++----- .../rpc/parameters/CallArgumentsParam.java | 97 ++++--------------- .../ethereum/rpc/parameters/HexKeyParam.java | 4 + .../java/org/ethereum/rpc/Web3ImplTest.java | 96 +++++++++--------- .../org/ethereum/rpc/Web3ImplUnitTest.java | 18 ++-- .../parameters/BlockIdentifierParamTest.java | 2 + .../rpc/parameters/BlockRefParamTest.java | 56 ++++++++--- .../rpc/parameters/HexKeyParamTest.java | 2 + 10 files changed, 176 insertions(+), 196 deletions(-) delete mode 100644 rskj-core/src/main/java/org/ethereum/rpc/BlockRef.java diff --git a/rskj-core/src/main/java/org/ethereum/rpc/BlockRef.java b/rskj-core/src/main/java/org/ethereum/rpc/BlockRef.java deleted file mode 100644 index 302d1e7c0d6..00000000000 --- a/rskj-core/src/main/java/org/ethereum/rpc/BlockRef.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.ethereum.rpc; - -import java.util.Map; - -public class BlockRef { - private String identifier; - private Map inputs; - - public BlockRef(String identifier) { - this.identifier = identifier; - } - - public BlockRef(Map inputs) { - this.inputs = inputs; - } - - public String getIdentifier() { - return identifier; - } - - public Map getInputs() { - return inputs; - } -} diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java index 03fddeb0f7a..3b7d1b70873 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java @@ -18,6 +18,10 @@ public class BlockIdentifierParam implements Serializable { private final String identifier; public BlockIdentifierParam(String identifier) { + if (identifier == null || identifier.isEmpty()) { + throw RskJsonRpcRequestException.invalidParamError("Invalid block identifier: empty or null."); + } + if(BlockTag.fromString(identifier) == null && !Utils.isDecimalString(identifier) && !Utils.isHexadecimalString(identifier)) { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java index df583fc65da..d4d17866ed6 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java @@ -2,10 +2,11 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import org.ethereum.rpc.BlockRef; +import com.fasterxml.jackson.databind.node.JsonNodeType; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.util.Utils; @@ -19,35 +20,52 @@ public class BlockRefParam implements Serializable { private static final long serialVersionUID = 1L; + private static final String REQUIRED_CANONICAL_KEY = "requireCanonical"; + private static final String BLOCK_HASH_KEY = "blockHash"; + private static final String BLOCK_NUMBER_KEY = "blockNumber"; + private static final List BLOCK_INPUT_KEYS_TO_VALIDATE = Arrays.asList(BLOCK_HASH_KEY, BLOCK_NUMBER_KEY); private static final List IDENTIFIERS_TO_VALIDATE = Arrays.asList("earliest", "latest", "pending"); - private static final List BLOCK_INPUT_KEYS_TO_VALIDATE = Arrays.asList("blockHash", "blockNumber"); - private final String identifier; - private final Map inputs; + private String identifier; + private Map inputs; - public BlockRefParam(BlockRef blockRef) { - if(blockRef.getIdentifier() != null) { - validateString(blockRef.getIdentifier()); - } else { - validateMap(blockRef.getInputs()); - } - - this.identifier = blockRef.getIdentifier(); - this.inputs = blockRef.getInputs(); - } - - private void validateString(String identifier) { + public BlockRefParam(String identifier) { if(!IDENTIFIERS_TO_VALIDATE.contains(identifier) && !Utils.isDecimalString(identifier) && !Utils.isHexadecimalString(identifier)) { throw RskJsonRpcRequestException.invalidParamError("Invalid block identifier '" + identifier + "'"); } + + this.identifier = identifier; } - private void validateMap(Map inputs) { + public BlockRefParam(Map inputs) { if(inputs.keySet().stream().noneMatch(BLOCK_INPUT_KEYS_TO_VALIDATE::contains)) { throw RskJsonRpcRequestException.invalidParamError("Invalid block input"); } + + validateMapItems(inputs); + + this.inputs = inputs; + } + + private void validateMapItems(Map inputs) { + inputs.forEach((key, value) -> { + switch (key) { + case REQUIRED_CANONICAL_KEY: + if(!value.equalsIgnoreCase("true") && !value.equalsIgnoreCase("false")) { + throw RskJsonRpcRequestException.invalidParamError(String + .format("Invalid input: %s must be a String \"true\" or \"false\"", REQUIRED_CANONICAL_KEY)); + } + break; + case BLOCK_HASH_KEY: + new BlockHashParam(value); + break; + case BLOCK_NUMBER_KEY: + new HexNumberParam(value); + break; + } + }); } public String getIdentifier() { @@ -68,18 +86,17 @@ public static class Deserializer extends StdDeserializer { @Override public BlockRefParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { - Object objectParam = mapper.readValue(jp, Object.class); - BlockRef blockRef; - - if(objectParam instanceof String) { - blockRef = new BlockRef(objectParam.toString()); - } else if (objectParam instanceof Map) { - blockRef = new BlockRef((Map) objectParam); + JsonNode node = jp.getCodec().readTree(jp); + JsonNodeType nodeType = node.getNodeType(); + + if(nodeType == JsonNodeType.STRING) { + return new BlockRefParam(node.asText()); + } else if(nodeType == JsonNodeType.OBJECT) { + Map inputs = mapper.convertValue(node, Map.class); + return new BlockRefParam(inputs); } else { throw RskJsonRpcRequestException.invalidParamError("Invalid input"); } - - return new BlockRefParam(blockRef); } } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java index 14d9448cbc9..93a3a8d4291 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java @@ -1,6 +1,5 @@ package org.ethereum.rpc.parameters; -import co.rsk.core.RskAddress; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; @@ -9,7 +8,6 @@ import org.ethereum.rpc.CallArguments; import java.io.IOException; -import java.util.Optional; @JsonDeserialize(using = CallArgumentsParam.Deserializer.class) public class CallArgumentsParam { @@ -75,35 +73,16 @@ public HexDataParam getData() { } public CallArguments toCallArguments() { - String caFrom = Optional.ofNullable(this.from) - .map(HexAddressParam::getAddress) - .map(RskAddress::toJsonString) - .orElse(null); - String caTo = Optional.ofNullable(this.to) - .map(HexAddressParam::getAddress) - .map(RskAddress::toJsonString) - .orElse(null); - String caGas = Optional.ofNullable(this.gas) - .map(HexNumberParam::getHexNumber) - .orElse(null); - String caGasPrice = Optional.ofNullable(this.gasPrice) - .map(HexNumberParam::getHexNumber) - .orElse(null); - String caGasLimit = Optional.ofNullable(this.gasLimit) - .map(HexNumberParam::getHexNumber) - .orElse(null); - String caNonce = Optional.ofNullable(this.nonce) - .map(HexNumberParam::getHexNumber) - .orElse(null); - String caChainId = Optional.ofNullable(this.chainId) - .map(HexNumberParam::getHexNumber) - .orElse(null); - String caValue = Optional.ofNullable(this.value) - .map(HexNumberParam::getHexNumber) - .orElse(null); - String caData = Optional.ofNullable(this.data) - .map(HexDataParam::getAsHexString) - .orElse(null); + + String caFrom = this.from == null ? null : this.from.getAddress().toJsonString(); + String caTo = this.to == null ? null : this.to.getAddress().toJsonString(); + String caGas = this.gas == null ? null : this.gas.getHexNumber(); + String caGasPrice = this.gasPrice == null ? null : this.gasPrice.getHexNumber(); + String caGasLimit = this.gasLimit == null ? null : this.gasLimit.getHexNumber(); + String caNonce = this.nonce == null ? null : this.nonce.getHexNumber(); + String caChainId = this.chainId == null ? null : this.chainId.getHexNumber(); + String caValue = this.value == null ? null : this.value.getHexNumber(); + String caData = this.data == null ? null : this.data.getAsHexString(); CallArguments callArguments = new CallArguments(); callArguments.setFrom(caFrom); @@ -130,51 +109,17 @@ public static class Deserializer extends StdDeserializer { public CallArgumentsParam deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { JsonNode node = jp.getCodec().readTree(jp); - HexAddressParam from = Optional.ofNullable(node) - .map(n -> n.get("from")) - .map(JsonNode::asText) - .map(HexAddressParam::new) - .orElse(null); - HexAddressParam to = Optional.ofNullable(node) - .map(n -> n.get("to")) - .map(JsonNode::asText) - .map(HexAddressParam::new) - .orElse(null); - HexNumberParam gas = Optional.ofNullable(node) - .map(n -> n.get("gas")) - .map(JsonNode::asText) - .map(HexNumberParam::new) - .orElse(null); - HexNumberParam gasPrice = Optional.ofNullable(node) - .map(n -> n.get("gasPrice")) - .map(JsonNode::asText) - .map(HexNumberParam::new) - .orElse(null); - HexNumberParam gasLimit = Optional.ofNullable(node) - .map(n -> n.get("gasLimit")) - .map(JsonNode::asText) - .map(HexNumberParam::new) - .orElse(null); - HexNumberParam nonce = Optional.ofNullable(node) - .map(n -> n.get("nonce")) - .map(JsonNode::asText) - .map(HexNumberParam::new) - .orElse(null); - HexNumberParam chainId = Optional.ofNullable(node) - .map(n -> n.get("chainId")) - .map(JsonNode::asText) - .map(HexNumberParam::new) - .orElse(null); - HexNumberParam value = Optional.ofNullable(node) - .map(n -> n.get("value")) - .map(JsonNode::asText) - .map(HexNumberParam::new) - .orElse(null); - HexDataParam data = Optional.ofNullable(node) - .map(n -> n.get("data")) - .map(JsonNode::asText) - .map(HexDataParam::new) - .orElse(null); + BlockIdentifierParam fromBlock = node.has("fromBlock") ? new BlockIdentifierParam(node.get("fromBlock").asText()) : null; + + HexAddressParam from = node.has("from") ? new HexAddressParam(node.get("from").asText()) : null; + HexAddressParam to = node.has("to") ? new HexAddressParam(node.get("to").asText()) : null; + HexNumberParam gas = node.has("gas") ? new HexNumberParam(node.get("gas").asText()) : null; + HexNumberParam gasPrice = node.has("gasPrice") ? new HexNumberParam(node.get("gasPrice").asText()) : null; + HexNumberParam gasLimit = node.has("gasLimit") ? new HexNumberParam(node.get("gasLimit").asText()) : null; + HexNumberParam nonce = node.has("nonce") ? new HexNumberParam(node.get("nonce").asText()) : null; + HexNumberParam chainId = node.has("chainId") ? new HexNumberParam(node.get("chainId").asText()) : null; + HexNumberParam value = node.has("value") ? new HexNumberParam(node.get("value").asText()) : null; + HexDataParam data = node.has("data") ? new HexDataParam(node.get("data").asText()) : null; return new CallArgumentsParam(from, to, gas, gasPrice, gasLimit, nonce, chainId, value, data); } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java index 3a5e796a4cb..61ce6083a6c 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java @@ -17,6 +17,10 @@ public class HexKeyParam implements Serializable { private final String hexKey; public HexKeyParam(String hexKey) { + if (hexKey == null || hexKey.isEmpty()) { + throw RskJsonRpcRequestException.invalidParamError("Invalid key: empty or null."); + } + boolean hasPrefix = HexUtils.hasHexPrefix(hexKey); if (!HexUtils.isHex(hexKey.toLowerCase(), hasPrefix ? 2 : 0)) { throw RskJsonRpcRequestException.invalidParamError("Invalid param " + hexKey + ": value must be a valid hex."); 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 81f68b3c5e2..b9aa27680ae 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplTest.java @@ -230,7 +230,7 @@ void getBalanceWithAccountAndLatestBlock() { assertEquals(BALANCE_10K_HEX, web3.eth_getBalance( new HexAddressParam(ByteUtil.toHexString(acc1.getAddress().getBytes())), - new BlockRefParam(new BlockRef("latest")))); + new BlockRefParam("latest"))); } @Test @@ -242,7 +242,7 @@ void getBalanceWithAccountAndGenesisBlock() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x0")))); + assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam("0x0"))); } @Test @@ -255,42 +255,42 @@ void getBalanceWithAccountAndBlock() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1")))); + assertEquals(BALANCE_10K_HEX, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam("0x1"))); } @Test //[ "0x
", { "blockNumber": "0x0" } -> return balance at given address in genesis block void getBalanceWithAccountAndBlockNumber() { final ChainParams chain = chainWithAccount10kBalance(false); - assertByBlockNumber(BALANCE_10K_HEX, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertByBlockNumber(BALANCE_10K_HEX, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException void getBalanceWithAccountAndInvalidInputThrowsException() { final ChainParams chain = chainWithAccount10kBalance(false); - assertInvalidInput(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertInvalidInput(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return balance at given address in genesis block void getBalanceWithAccountAndBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); - assertByBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertByBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonExistentBlockHash(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonExistentBlockHash(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @@ -298,14 +298,14 @@ void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void getBalanceWithAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @@ -313,28 +313,28 @@ void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return balance at given address in genesis block void getBalanceWithAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertCanonicalBlockHashWhenCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertCanonicalBlockHashWhenCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return balance at given address in genesis block void getBalanceWithAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(false); - assertCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return balance at given address in specified block void getBalanceWithAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonCanonicalBlockHashWhenNotCanonical(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test // [ "0x
", { "blockHash": "0x" } -> return balance at given address in specified bloc void getBalanceWithAccountAndNonCanonicalBlockHash() { final ChainParams chain = chainWithAccount10kBalance(true); - assertNonCanonicalBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonCanonicalBlockHash(BALANCE_10K_HEX, chain.block, blockRef -> chain.web3.eth_getBalance(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test @@ -358,9 +358,9 @@ void getBalanceWithAccountAndBlockWithTransaction() { String accountAddress = ByteUtil.toHexString(acc2.getAddress().getBytes()); String balanceString = BALANCE_10K_HEX; - assertEquals("0x0", web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x0")))); - assertEquals(balanceString, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1")))); - assertEquals(balanceString, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("pending")))); + assertEquals("0x0", web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam("0x0"))); + assertEquals(balanceString, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam("0x1"))); + assertEquals(balanceString, web3.eth_getBalance(new HexAddressParam(accountAddress), new BlockRefParam("pending"))); } @Test @@ -370,7 +370,7 @@ void getStorageAtAccountAndBlockNumber() { assertByBlockNumber("0x0", blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @Test @@ -380,7 +380,7 @@ void getStorageAtAccountAndBlockHash() { assertByBlockHash("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @Test @@ -390,7 +390,7 @@ void getStorageAtAccountAndNonExistentBlockHash() { assertNonExistentBlockHash(blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @@ -401,7 +401,7 @@ void getStorageAtAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @Test @@ -411,7 +411,7 @@ void getStorageAtAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @Test @@ -421,7 +421,7 @@ void getStorageAtAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @Test @@ -431,7 +431,7 @@ void getStorageAtAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { assertCanonicalBlockHashWhenCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @Test @@ -441,7 +441,7 @@ void getStorageAtAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { assertCanonicalBlockHashWhenNotCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @Test @@ -451,7 +451,7 @@ void getStorageAtAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { assertNonCanonicalBlockHashWhenNotCanonical("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @Test @@ -461,7 +461,7 @@ void getStorageAtAccountAndNonCanonicalBlockHash() { assertNonCanonicalBlockHash("0x0", chain.block, blockRef -> chain.web3.eth_getStorageAt( new HexAddressParam(chain.accountAddress), new HexNumberParam("0x0"), - new BlockRefParam(new BlockRef(blockRef)))); + new BlockRefParam(blockRef))); } @@ -469,70 +469,70 @@ void getStorageAtAccountAndNonCanonicalBlockHash() { //[ "0x
", { "blockNumber": "0x0" } -> return code at given address in genesis block void getCodeAtAccountAndBlockNumber() { final ChainParams chain = createChainWithAContractCode(false); - assertByBlockNumber("0x010203", blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertByBlockNumber("0x010203", blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return code at given address in genesis block void getCodeAtAccountAndBlockHash() { final ChainParams chain = createChainWithAContractCode(false); - assertByBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertByBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHash() { final ChainParams chain = createChainWithAContractCode(false); - assertNonExistentBlockHash(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonExistentBlockHash(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(false); - assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonBlockHashWhenCanonical(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0x", "requireCanonical": false } -> raise block-not-found error void getCodeAtAccountAndNonExistentBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(false); - assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonBlockHashWhenIsNotCanonical(blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getCodeAtAccountAndNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(true); - assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": true } -> return code at given address in genesis block void getCodeAtAccountAndCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithAContractCode(false); - assertCanonicalBlockHashWhenCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertCanonicalBlockHashWhenCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", "requireCanonical": false } -> return code at given address in genesis block void getCodeAtAccountAndCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(false); - assertCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": false } -> return code at given address in specified block void getCodeAtAccountAndNonCanonicalBlockHashWhenCanonicalIsNotRequired() { final ChainParams chain = createChainWithAContractCode(true); - assertNonCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonCanonicalBlockHashWhenNotCanonical("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test // [ "0x
", { "blockHash": "0x" } -> return code at given address in specified bloc void getCodeAtAccountAndNonCanonicalBlockHash() { final ChainParams chain = createChainWithAContractCode(true); - assertNonCanonicalBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonCanonicalBlockHash("0x010203", chain.block, blockRef -> chain.web3.eth_getCode(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test @@ -1022,12 +1022,12 @@ void getTransactionCount() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - String count = web3.eth_getTransactionCount(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1"))); + String count = web3.eth_getTransactionCount(new HexAddressParam(accountAddress), new BlockRefParam("0x1")); assertNotNull(count); assertEquals("0x1", count); - count = web3.eth_getTransactionCount(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x0"))); + count = web3.eth_getTransactionCount(new HexAddressParam(accountAddress), new BlockRefParam("0x0")); assertNotNull(count); assertEquals("0x0", count); @@ -1037,42 +1037,42 @@ void getTransactionCount() { //[ "0x
", { "blockNumber": "0x0" } -> return tx count at given address in genesis block void getTransactionCountByBlockNumber() { final ChainParams chain = createChainWithATransaction(false); - assertByBlockNumber("0x1", blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertByBlockNumber("0x1", blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "invalidInput": "0x0" } -> throw RskJsonRpcRequestException void getTransactionCountAndInvalidInputThrowsException() { final ChainParams chain = createChainWithATransaction(false); - assertInvalidInput(blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertInvalidInput(blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" } -> return tx count at given address in genesis block void getTransactionCountByBlockHash() { final ChainParams chain = createChainWithATransaction(false); - assertByBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertByBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test //[ "0x
", { "blockHash": "0x" } -> raise block-not-found error void getTransactionCountByNonExistentBlockHash() { final ChainParams chain = chainWithAccount10kBalance(false); - assertNonExistentBlockHash(blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonExistentBlockHash(blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test // [ "0x
", { "blockHash": "0x", "requireCanonical": true } -> raise block-not-canonical error void getTransactionCountByNonCanonicalBlockHashWhenCanonicalIsRequired() { final ChainParams chain = createChainWithATransaction(true); - assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonCanonicalBlockHashWhenCanonical(chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test // [ "0x
", { "blockHash": "0x" } -> return tx count at given address in specified bloc void getTransactionCountByNonCanonicalBlockHash() { final ChainParams chain = createChainWithATransaction(true); - assertNonCanonicalBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(new BlockRef(blockRef)))); + assertNonCanonicalBlockHash("0x1", chain.block, blockRef -> chain.web3.eth_getTransactionCount(new HexAddressParam(chain.accountAddress), new BlockRefParam(blockRef))); } @Test @@ -1768,7 +1768,7 @@ void getCode() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - String scode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1"))); + String scode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam("0x1")); assertNotNull(scode); assertEquals("0x" + ByteUtil.toHexString(code), scode); @@ -1910,7 +1910,7 @@ void getCodeBlockDoesNotExist() { String accountAddress = ByteUtil.toHexString(acc1.getAddress().getBytes()); - String resultCode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x100"))); + String resultCode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam("0x100")); assertNull(resultCode); } @@ -2444,7 +2444,7 @@ void getNoCode() throws Exception { String accountAddress = Hex.toHexString(acc1.getAddress().getBytes()); - String scode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam(new BlockRef("0x1"))); + String scode = web3.eth_getCode(new HexAddressParam(accountAddress), new BlockRefParam("0x1")); assertNotNull(scode); Assertions.assertEquals("0x", scode); diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java index 5d090af8968..57bf522c671 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java @@ -107,7 +107,7 @@ void eth_getBalance_stateCannotBeRetrieved() { when(retriever.getInformationProvider(id)) .thenThrow(RskJsonRpcRequestException.blockNotFound("Block not found")); TestUtils.assertThrows(RskJsonRpcRequestException.class, - () -> target.eth_getBalance(new HexAddressParam(addr), new BlockRefParam(new BlockRef(id)))); + () -> target.eth_getBalance(new HexAddressParam(addr), new BlockRefParam(id))); } @Test @@ -121,7 +121,7 @@ void eth_getBalance() { when(aip.getBalance(expectedAddress)) .thenReturn(new Coin(BigInteger.ONE)); - String result = target.eth_getBalance(new HexAddressParam(addr),new BlockRefParam(new BlockRef(id))); + String result = target.eth_getBalance(new HexAddressParam(addr),new BlockRefParam(id)); assertEquals("0x1", result); } @@ -136,7 +136,7 @@ void eth_getBalanceByBlockRef() { }; final Web3Impl spyTarget = spy(target); doReturn("0x1").when(spyTarget).invokeByBlockRef(eq(blockRef),any()); - String result = spyTarget.eth_getBalance(new HexAddressParam(addr), new BlockRefParam(new BlockRef(blockRef))); + String result = spyTarget.eth_getBalance(new HexAddressParam(addr), new BlockRefParam(blockRef)); assertEquals("0x1", result); verify(spyTarget).invokeByBlockRef(eq(blockRef),any()); } @@ -149,7 +149,7 @@ void eth_getStorageAt_stateCannotBeRetrieved() { HexAddressParam hexAddressParam = new HexAddressParam(addr); HexNumberParam hexNumberParam = new HexNumberParam(storageIdx); - BlockRefParam blockRefParam = new BlockRefParam(new BlockRef(id)); + BlockRefParam blockRefParam = new BlockRefParam(id); when(retriever.getInformationProvider(id)) .thenThrow(RskJsonRpcRequestException.blockNotFound("Block not found")); @@ -168,7 +168,7 @@ void eth_getStorageAt() { HexAddressParam hexAddressParam = new HexAddressParam(addr); HexNumberParam hexNumberParam = new HexNumberParam(storageIdx); - BlockRefParam blockRefParam = new BlockRefParam(new BlockRef(id)); + BlockRefParam blockRefParam = new BlockRefParam(id); AccountInformationProvider aip = mock(AccountInformationProvider.class); when(retriever.getInformationProvider(id)).thenReturn(aip); @@ -195,7 +195,7 @@ void eth_getStorageAtByBlockRef() { HexAddressParam hexAddressParam = new HexAddressParam(addr); HexNumberParam hexNumberParam = new HexNumberParam(storageIdx); - BlockRefParam blockRefParam = new BlockRefParam(new BlockRef(blockRef)); + BlockRefParam blockRefParam = new BlockRefParam(blockRef); doReturn(expectedData).when(spyTarget).invokeByBlockRef(eq(blockRef),any()); String result = spyTarget.eth_getStorageAt(hexAddressParam, hexNumberParam, blockRefParam); @@ -214,7 +214,7 @@ void eth_getStorageAtEmptyCell() { HexAddressParam hexAddressParam = new HexAddressParam(addr); HexNumberParam hexNumberParam = new HexNumberParam(storageIdx); - BlockRefParam blockRefParam = new BlockRefParam(new BlockRef(id)); + BlockRefParam blockRefParam = new BlockRefParam(id); AccountInformationProvider aip = mock(AccountInformationProvider.class); when(retriever.getInformationProvider(id)).thenReturn(aip); @@ -262,7 +262,7 @@ void eth_getCode() { final Web3Impl spyTarget = spy(target); final String expectedData = "0x010203"; doReturn(expectedData).when(spyTarget).invokeByBlockRef(eq(blockRef),any()); - String result = spyTarget.eth_getCode(new HexAddressParam(addr), new BlockRefParam(new BlockRef(blockRef))); + String result = spyTarget.eth_getCode(new HexAddressParam(addr), new BlockRefParam(blockRef)); assertEquals(expectedData, result); verify(spyTarget).invokeByBlockRef(eq(blockRef),any()); } @@ -299,7 +299,7 @@ void eth_getBlockTransactionCountByBlockRef() { }; final Web3Impl spyTarget = spy(target); doReturn("0x1").when(spyTarget).invokeByBlockRef(eq(blockRef),any()); - String result = spyTarget.eth_getTransactionCount(new HexAddressParam(addr), new BlockRefParam(new BlockRef(blockRef))); + String result = spyTarget.eth_getTransactionCount(new HexAddressParam(addr), new BlockRefParam(blockRef)); assertEquals("0x1", result); verify(spyTarget).invokeByBlockRef(eq(blockRef),any()); } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java index 95abb2014cd..b3e68111c8e 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java @@ -42,5 +42,7 @@ public void testInvalidHexAddressParam() { assertThrows(RskJsonRpcRequestException.class, () -> new BlockIdentifierParam(invalidStringIdentifier)); assertThrows(RskJsonRpcRequestException.class, () -> new BlockIdentifierParam(invalidHexIdentifier)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockIdentifierParam(null)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockIdentifierParam("")); } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java index e624de4a61d..887f5028663 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java @@ -1,6 +1,5 @@ package org.ethereum.rpc.parameters; -import org.ethereum.rpc.BlockRef; import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.junit.jupiter.api.Test; @@ -15,9 +14,8 @@ public class BlockRefParamTest { @Test public void testValidIdentifier() { String identifier = "latest"; - BlockRef blockRef = new BlockRef(identifier); - BlockRefParam blockRefParam = new BlockRefParam(blockRef); + BlockRefParam blockRefParam = new BlockRefParam(identifier); assertEquals(identifier, blockRefParam.getIdentifier()); assertNull(blockRefParam.getInputs()); @@ -27,12 +25,11 @@ public void testValidIdentifier() { public void testValidInputs() { Map inputs = new HashMap() { { - put("blockHash", "0x0011223344556677880011223344556677889900"); + put("blockHash", "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"); } }; - BlockRef blockRef = new BlockRef(inputs); - BlockRefParam blockRefParam = new BlockRefParam(blockRef); + BlockRefParam blockRefParam = new BlockRefParam(inputs); assertEquals(inputs, blockRefParam.getInputs()); assertNull(blockRefParam.getIdentifier()); @@ -41,28 +38,61 @@ public void testValidInputs() { @Test public void testInvalidIdentifierString() { String invalidStringIdentifier = "first"; - BlockRef blockRef = new BlockRef(invalidStringIdentifier); - assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(blockRef)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(invalidStringIdentifier)); } @Test public void testInvalidIdentifierHexString() { String invalidStringIdentifier = "0x1aw"; - BlockRef blockRef = new BlockRef(invalidStringIdentifier); - assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(blockRef)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(invalidStringIdentifier)); } @Test public void testInvalidInputsInvalidKey() { Map inputs = new HashMap() { { - put("invalidKey", "0x0011223344556677880011223344556677889900"); + put("invalidKey", "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"); } }; - BlockRef blockRef = new BlockRef(inputs); - assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(blockRef)); + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(inputs)); + } + + @Test + public void testInvalidInputsInvalidBlockHash() { + Map inputs = new HashMap() { + { + put("blockHash", "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fxk"); + put("requireCanonical", "false"); + } + }; + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(inputs)); + } + + @Test + public void testInvalidInputsInvalidBlockNumber() { + Map inputs = new HashMap() { + { + put("blockNumber", "0x76ty"); + put("requireCanonical", "false"); + } + }; + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(inputs)); + } + + @Test + public void testInvalidInputsInvalidRequireCanonical() { + Map inputs = new HashMap() { + { + put("blockNumber", "0x76c0"); + put("requireCanonical", "first"); + } + }; + + assertThrows(RskJsonRpcRequestException.class, () -> new BlockRefParam(inputs)); } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java index c49a6f2dd8c..ae1d86bd2f9 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java @@ -22,5 +22,7 @@ void testInvalidHexKeyParam() { String invalidHexValue = "0xcd3376bb711cb332ee3fb2ca04c6a8b9f70c316fcdf7a1f44ef4c79994832zxt"; assertThrows(RskJsonRpcRequestException.class, () -> new HexKeyParam(invalidHexValue)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexKeyParam(null)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexKeyParam("")); } } From d770ff752b31aac72bdaf847d99212e936f2db36 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Mon, 18 Sep 2023 09:43:53 -0400 Subject: [PATCH 35/47] Fix failing tests --- .../test/java/org/ethereum/rpc/Web3ImplUnitTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java index 57bf522c671..6dfe17b61fd 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/Web3ImplUnitTest.java @@ -131,7 +131,7 @@ void eth_getBalanceByBlockRef() { String addr = "0x0011223344556677880011223344556677889900"; Map blockRef = new HashMap() { { - put("blockHash", "0x0011223344556677880011223344556677889900"); + put("blockHash", "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8"); } }; final Web3Impl spyTarget = spy(target); @@ -187,7 +187,7 @@ void eth_getStorageAtByBlockRef() { final String storageIdx = "0x01"; Map blockRef = new HashMap() { { - put("blockHash", "0x0011223344556677880011223344556677889900"); + put("blockHash", "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8"); } }; final Web3Impl spyTarget = spy(target); @@ -256,7 +256,7 @@ void eth_getCode() { final String addr = "0x0011223344556677880011223344556677889900"; Map blockRef = new HashMap() { { - put("blockHash", "0x0011223344556677880011223344556677889900"); + put("blockHash", "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8"); } }; final Web3Impl spyTarget = spy(target); @@ -276,7 +276,7 @@ void eth_callAtByBlockRef() { argsForCall.setData("ead710c40000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000568656c6c6f000000000000000000000000000000000000000000000000000000"); Map blockRef = new HashMap() { { - put("blockHash", "0x0011223344556677880011223344556677889900"); + put("blockHash", "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8"); } }; final Web3Impl spyTarget = spy(target); @@ -294,7 +294,7 @@ void eth_getBlockTransactionCountByBlockRef() { String addr = "0x0011223344556677880011223344556677889900"; Map blockRef = new HashMap() { { - put("blockHash", "0x0011223344556677880011223344556677889900"); + put("blockHash", "0xc2b835124172db5bd051bb94fa123721eacac43b5cba2499b22c7583a35689b8"); } }; final Web3Impl spyTarget = spy(target); From 016b547b9853f44e1de2012af3ca88f5ed5085db Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Tue, 19 Sep 2023 08:37:32 -0400 Subject: [PATCH 36/47] Move null check from HexKeyParam to the importRawKey method --- .../rpc/modules/personal/PersonalModuleWalletEnabled.java | 6 +++++- .../main/java/org/ethereum/rpc/parameters/HexKeyParam.java | 4 ---- .../modules/personal/PersonalModuleWalletEnabledTest.java | 4 ++-- .../java/org/ethereum/rpc/parameters/HexKeyParamTest.java | 2 -- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java index 544b6d90f54..eb294b1f43e 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabled.java @@ -128,7 +128,11 @@ public String[] listAccounts() { @Override public String importRawKey(HexKeyParam keyParam, String passphrase) { String s = null; - String key = Optional.ofNullable(keyParam).map(HexKeyParam::getHexKey).orElse(null); + String key = Optional.ofNullable(keyParam).map(HexKeyParam::getHexKey) + .orElseThrow( + () -> RskJsonRpcRequestException.invalidParamError("Key cannot be null.") + ); + try { if (key != null && key.startsWith("0x")) { key = key.substring(2); diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java index 61ce6083a6c..3a5e796a4cb 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java @@ -17,10 +17,6 @@ public class HexKeyParam implements Serializable { private final String hexKey; public HexKeyParam(String hexKey) { - if (hexKey == null || hexKey.isEmpty()) { - throw RskJsonRpcRequestException.invalidParamError("Invalid key: empty or null."); - } - boolean hasPrefix = HexUtils.hasHexPrefix(hexKey); if (!HexUtils.isHex(hexKey.toLowerCase(), hasPrefix ? 2 : 0)) { throw RskJsonRpcRequestException.invalidParamError("Invalid param " + hexKey + ": value must be a valid hex."); diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabledTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabledTest.java index fff87a50406..33bca0142b4 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabledTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/personal/PersonalModuleWalletEnabledTest.java @@ -3,9 +3,9 @@ import co.rsk.config.TestSystemProperties; import co.rsk.core.RskAddress; import co.rsk.core.Wallet; -import org.bouncycastle.util.encoders.DecoderException; import org.bouncycastle.util.encoders.Hex; import org.ethereum.crypto.ECKey; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.HexKeyParam; import org.ethereum.util.ByteUtil; import org.junit.jupiter.api.Assertions; @@ -26,7 +26,7 @@ class PersonalModuleWalletEnabledTest { @Test void importRawKey_KeyIsNull_ThrowsNullPointerException() { PersonalModuleWalletEnabled personalModuleWalletEnabled = createPersonalModuleWalletEnabled(null); - Assertions.assertThrows(DecoderException.class, () -> personalModuleWalletEnabled.importRawKey(null, "passphrase1")); + Assertions.assertThrows(RskJsonRpcRequestException.class, () -> personalModuleWalletEnabled.importRawKey(null, "passphrase1")); } @Test diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java index ae1d86bd2f9..c49a6f2dd8c 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java @@ -22,7 +22,5 @@ void testInvalidHexKeyParam() { String invalidHexValue = "0xcd3376bb711cb332ee3fb2ca04c6a8b9f70c316fcdf7a1f44ef4c79994832zxt"; assertThrows(RskJsonRpcRequestException.class, () -> new HexKeyParam(invalidHexValue)); - assertThrows(RskJsonRpcRequestException.class, () -> new HexKeyParam(null)); - assertThrows(RskJsonRpcRequestException.class, () -> new HexKeyParam("")); } } From bdc6dd12650801181e76f4c4185ab096f92f09e0 Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Wed, 20 Sep 2023 12:48:41 +0200 Subject: [PATCH 37/47] Check null value in newAccount method --- .../src/main/java/org/ethereum/rpc/Web3Impl.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java index 452daa5085e..7d415bfd9cc 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/Web3Impl.java @@ -60,6 +60,7 @@ import org.ethereum.rpc.dto.CompilationResultDTO; import org.ethereum.rpc.dto.TransactionReceiptDTO; import org.ethereum.rpc.dto.TransactionResultDTO; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; import org.ethereum.rpc.parameters.*; import org.ethereum.util.BuildInfo; import org.ethereum.vm.DataWord; @@ -419,7 +420,7 @@ private String eth_getCode(HexAddressParam address, Map inputs) @Override public String eth_getBalance(HexAddressParam address, BlockRefParam blockRefParam) { - if(blockRefParam.getIdentifier() != null) { + if (blockRefParam.getIdentifier() != null) { return this.eth_getBalance(address, blockRefParam.getIdentifier()); } else { return this.eth_getBalance(address, blockRefParam.getInputs()); @@ -462,7 +463,7 @@ public String eth_getBalance(HexAddressParam address) { @Override public String eth_getStorageAt(HexAddressParam address, HexNumberParam storageIdx, BlockRefParam blockRefParam) { - if(blockRefParam.getIdentifier() != null) { + if (blockRefParam.getIdentifier() != null) { return this.eth_getStorageAt(address, storageIdx, blockRefParam.getIdentifier()); } else { return this.eth_getStorageAt(address, storageIdx, blockRefParam.getInputs()); @@ -501,7 +502,7 @@ private String eth_getStorageAt(HexAddressParam address, HexNumberParam storageI @Override public String eth_getTransactionCount(HexAddressParam address, BlockRefParam blockRefParam) { - if(blockRefParam.getIdentifier() != null) { + if (blockRefParam.getIdentifier() != null) { return this.eth_getTransactionCount(address, blockRefParam.getIdentifier()); } else { return this.eth_getTransactionCount(address, blockRefParam.getInputs()); @@ -1079,11 +1080,17 @@ public void db_getHex() { @Override public String personal_newAccountWithSeed(String seed) { + if (seed == null) { + throw RskJsonRpcRequestException.invalidParamError("Seed is null"); + } return personalModule.newAccountWithSeed(seed); } @Override public String personal_newAccount(String passphrase) { + if (passphrase == null) { + throw RskJsonRpcRequestException.invalidParamError("Passphrase is null"); + } return personalModule.newAccount(passphrase); } From aabccddd8e20c1bbd1cb3795b9457f42b05a6bc6 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Wed, 20 Sep 2023 08:56:56 -0400 Subject: [PATCH 38/47] Revert changes on EthModuleWallet sign method --- .../src/main/java/co/rsk/rpc/Web3EthModule.java | 2 +- .../main/java/co/rsk/rpc/modules/eth/EthModule.java | 2 +- .../java/co/rsk/rpc/modules/eth/EthModuleWallet.java | 5 +---- .../rsk/rpc/modules/eth/EthModuleWalletDisabled.java | 2 +- .../rsk/rpc/modules/eth/EthModuleWalletEnabled.java | 12 ++++++------ 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java index 622c0bf0a28..f4e7df6e256 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/Web3EthModule.java @@ -44,7 +44,7 @@ default String[] eth_accounts() { } default String eth_sign(HexAddressParam addr, HexDataParam data) { - return getEthModule().sign(addr, data); + return getEthModule().sign(addr.getAddress().toHexString(), data.getAsHexString()); } default String eth_call(CallArgumentsParam args, BlockIdentifierParam bnOrId) { diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java index 92b88d24440..e89355cdc5e 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModule.java @@ -212,7 +212,7 @@ public String sendRawTransaction(HexDataParam rawData) { } @Override - public String sign(HexAddressParam addr, HexDataParam data) { + public String sign(String addr, String data) { return ethModuleWallet.sign(addr, data); } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWallet.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWallet.java index eca121e7341..aaf90d7ff35 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWallet.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWallet.java @@ -18,12 +18,9 @@ package co.rsk.rpc.modules.eth; -import org.ethereum.rpc.parameters.HexAddressParam; -import org.ethereum.rpc.parameters.HexDataParam; - public interface EthModuleWallet { String[] accounts(); - String sign(HexAddressParam addr, HexDataParam data); + String sign(String addr, String data); } \ No newline at end of file diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java index 1d29f3899be..11bdbd3bdc5 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java @@ -39,7 +39,7 @@ public String[] accounts() { } @Override - public String sign(HexAddressParam addr, HexDataParam data) { + public String sign(String addr, String data) { LOGGER.debug("eth_sign({}, {}): {}", addr, data, null); throw invalidParamError("Local wallet is disabled in this node"); } diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java index 3d254713132..7ac52b5e3a1 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletEnabled.java @@ -23,13 +23,12 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; +import co.rsk.core.RskAddress; import org.bouncycastle.util.BigIntegers; import org.ethereum.core.Account; import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.crypto.signature.ECDSASignature; -import org.ethereum.rpc.parameters.HexAddressParam; -import org.ethereum.rpc.parameters.HexDataParam; import org.ethereum.util.ByteUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,15 +47,15 @@ public EthModuleWalletEnabled(Wallet wallet) { } @Override - public String sign(HexAddressParam addr, HexDataParam data) { + public String sign(String addr, String data) { String s = null; try { - Account account = this.wallet.getAccount(addr.getAddress()); + Account account = this.wallet.getAccount(new RskAddress(addr)); if (account == null) { throw invalidParamError("Account not found"); } - s = this.sign(data.getRawDataBytes(), account.getEcKey()); + s = this.sign(data, account.getEcKey()); return s; } finally { @@ -74,7 +73,8 @@ public String[] accounts() { } } - private String sign(byte[] dataHash, ECKey ecKey) { + private String sign(String data, ECKey ecKey) { + byte[] dataHash = HexUtils.stringHexToByteArray(data); // 0x19 = 25, length should be an ascii decimals, message - original String prefix = (char) 25 + "Ethereum Signed Message:\n" + dataHash.length; From 61c068736b2e54f94f763139a31382aac8be0517 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Wed, 20 Sep 2023 09:32:38 -0400 Subject: [PATCH 39/47] Remove unused imports --- .../java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java index 11bdbd3bdc5..4cf03242cd2 100644 --- a/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java +++ b/rskj-core/src/main/java/co/rsk/rpc/modules/eth/EthModuleWalletDisabled.java @@ -18,8 +18,6 @@ package co.rsk.rpc.modules.eth; -import org.ethereum.rpc.parameters.HexAddressParam; -import org.ethereum.rpc.parameters.HexDataParam; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From 0dd8a3e4b858c426316b7550c52e36edb227cab2 Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 21 Sep 2023 08:23:38 -0400 Subject: [PATCH 40/47] Add (C) header to new files --- .../rpc/parameters/BlockIdentifierParam.java | 17 +++++++++++++++++ .../rpc/parameters/BlockRefParam.java | 17 +++++++++++++++++ .../rpc/parameters/CallArgumentsParam.java | 17 +++++++++++++++++ .../ethereum/rpc/parameters/HashParam32.java | 2 +- .../rpc/parameters/HexAddressParam.java | 19 ++++++++++++++++++- .../ethereum/rpc/parameters/HexDataParam.java | 19 ++++++++++++++++++- .../rpc/parameters/HexDurationParam.java | 17 +++++++++++++++++ .../rpc/parameters/HexIndexParam.java | 1 - .../ethereum/rpc/parameters/HexKeyParam.java | 17 +++++++++++++++++ .../rpc/parameters/HexNumberParam.java | 17 +++++++++++++++++ .../rpc/parameters/HexStringParam.java | 17 +++++++++++++++++ .../ethereum/rpc/parameters/TxHashParam.java | 1 - .../parameters/BlockIdentifierParamTest.java | 17 +++++++++++++++++ .../rpc/parameters/BlockRefParamTest.java | 17 +++++++++++++++++ .../rpc/parameters/HashParamTest.java | 17 +++++++++++++++++ .../rpc/parameters/HexAddressParamTest.java | 17 +++++++++++++++++ .../rpc/parameters/HexDataParamTest.java | 17 +++++++++++++++++ .../rpc/parameters/HexDurationParamTest.java | 17 +++++++++++++++++ .../rpc/parameters/HexIndexParamTest.java | 1 - .../rpc/parameters/HexKeyParamTest.java | 17 +++++++++++++++++ .../rpc/parameters/HexNumberParamTest.java | 17 +++++++++++++++++ 21 files changed, 292 insertions(+), 6 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java index 3b7d1b70873..53d7bb3c1a4 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockIdentifierParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import com.fasterxml.jackson.core.JsonParser; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java index d4d17866ed6..b47b89af84d 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/BlockRefParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import com.fasterxml.jackson.core.JsonParser; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java index 93a3a8d4291..c7b40fee4a6 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/CallArgumentsParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import com.fasterxml.jackson.core.JsonParser; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java index aeeee8475cc..1824ab6126f 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java @@ -37,7 +37,7 @@ public abstract class HashParam32 { try { hashBytes = HexUtils.stringHexToByteArray(hash); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + " format. " + e.getMessage()); + throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + " format. " + e); } if (HASH_BYTE_LENGTH != hashBytes.length) { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java index 2e624235ab0..05c7f2382d7 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import co.rsk.core.RskAddress; @@ -24,7 +41,7 @@ public HexAddressParam(String hexAddress) { try { this.address = new RskAddress(hexAddress); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid address format. " + e.getMessage()); + throw RskJsonRpcRequestException.invalidParamError("Invalid address format. " + e); } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java index 61696ede095..a8c5af57442 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import co.rsk.util.HexUtils; @@ -21,7 +38,7 @@ public HexDataParam(String rawData){ try { this.rawDataBytes = HexUtils.stringHexToByteArray(rawData); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid data format. " + e.getMessage()); + throw RskJsonRpcRequestException.invalidParamError("Invalid data format. " + e); } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java index aea668b9cff..a6b0e8f1bad 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import com.fasterxml.jackson.core.JsonParser; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java index 1f1aec99b7e..92e87560321 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -15,7 +15,6 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - package org.ethereum.rpc.parameters; import co.rsk.util.HexUtils; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java index 3a5e796a4cb..48d86c83ad4 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexKeyParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import co.rsk.util.HexUtils; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java index d2e333f6ae8..b25fdcb8eef 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import co.rsk.util.HexUtils; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java index 7dfb5272fea..c36d838ed86 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexStringParam.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import co.rsk.util.HexUtils; diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java index e2e0bc3814b..b1c9b3674b7 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/TxHashParam.java @@ -15,7 +15,6 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - package org.ethereum.rpc.parameters; import com.fasterxml.jackson.core.JsonParser; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java index b3e68111c8e..c733f465c8f 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockIdentifierParamTest.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import org.ethereum.core.genesis.BlockTag; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java index 887f5028663..65a055668ed 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/BlockRefParamTest.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import org.ethereum.rpc.exception.RskJsonRpcRequestException; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HashParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HashParamTest.java index 80396db89dc..446ab0ef7b6 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HashParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HashParamTest.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import org.ethereum.rpc.exception.RskJsonRpcRequestException; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexAddressParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexAddressParamTest.java index 86255b7d7fb..76b2e7838c5 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexAddressParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexAddressParamTest.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import org.ethereum.rpc.exception.RskJsonRpcRequestException; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDataParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDataParamTest.java index a49070d5a8a..9953dd1b219 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDataParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDataParamTest.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import co.rsk.util.HexUtils; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java index a8dd9c66300..2d47047a3c7 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import org.ethereum.rpc.exception.RskJsonRpcRequestException; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java index 21cd89ce9f7..10d755c4480 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java @@ -15,7 +15,6 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ - package org.ethereum.rpc.parameters; import org.ethereum.rpc.exception.RskJsonRpcRequestException; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java index c49a6f2dd8c..58305c00278 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexKeyParamTest.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import org.ethereum.rpc.exception.RskJsonRpcRequestException; diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexNumberParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexNumberParamTest.java index f12bc6b4ad1..ad819283fec 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexNumberParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexNumberParamTest.java @@ -1,3 +1,20 @@ +/* + * This file is part of RskJ + * Copyright (C) 2018 RSK Labs Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ package org.ethereum.rpc.parameters; import org.ethereum.rpc.exception.RskJsonRpcRequestException; From 5ca790ac2553e42864a4bffbce22d1ec6a867d5a Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 21 Sep 2023 09:04:29 -0400 Subject: [PATCH 41/47] Update invalid hex error messages --- .../main/java/org/ethereum/rpc/parameters/HashParam32.java | 2 +- .../java/org/ethereum/rpc/parameters/HexAddressParam.java | 2 +- .../main/java/org/ethereum/rpc/parameters/HexDataParam.java | 2 +- .../java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java index 1824ab6126f..cee7930f320 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java @@ -37,7 +37,7 @@ public abstract class HashParam32 { try { hashBytes = HexUtils.stringHexToByteArray(hash); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + " format. " + e); + throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + " format: invalid hex value"); } if (HASH_BYTE_LENGTH != hashBytes.length) { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java index 05c7f2382d7..4febba555c2 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java @@ -41,7 +41,7 @@ public HexAddressParam(String hexAddress) { try { this.address = new RskAddress(hexAddress); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid address format. " + e); + throw RskJsonRpcRequestException.invalidParamError("Invalid address format: invalid hex value"); } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java index a8c5af57442..5ad4dd5b856 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java @@ -38,7 +38,7 @@ public HexDataParam(String rawData){ try { this.rawDataBytes = HexUtils.stringHexToByteArray(rawData); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid data format. " + e); + throw RskJsonRpcRequestException.invalidParamError("Invalid data format: invalid hex value"); } } diff --git a/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java b/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java index 3c70c2eae48..a7bec0637a0 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/netty/JsonRPCParamValidationTest.java @@ -92,7 +92,7 @@ void eth_getBlockByHash_invalidHexCharInHash_returnsError() throws Exception { JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); assertEquals(-32602, response.getCode()); String message = response.getResponse().get("error").get("message").asText(); - assertEquals("Invalid block hash format. exception decoding Hex string: invalid characters encountered in Hex string", message); + assertEquals("Invalid block hash format: invalid hex value", message); } @Test @@ -192,7 +192,7 @@ void eth_getTransactionByHash_invalidHash_returnsError() throws Exception { JsonResponse response = jsonRpcServer.handleJsonNodeRequest(request); assertEquals(-32602, response.getCode()); String message = response.getResponse().get("error").get("message").asText(); - assertEquals("Invalid transaction hash format. exception decoding Hex string: invalid characters encountered in Hex string", message); + assertEquals("Invalid transaction hash format: invalid hex value", message); } @Test From 8d27c79fb162aaa4a209621a1b4c20bfb44def1f Mon Sep 17 00:00:00 2001 From: Reynold Morel Date: Thu, 21 Sep 2023 10:06:18 -0400 Subject: [PATCH 42/47] Send error object to invalidParamError for logging --- .../src/main/java/org/ethereum/rpc/parameters/HashParam32.java | 2 +- .../main/java/org/ethereum/rpc/parameters/HexAddressParam.java | 2 +- .../src/main/java/org/ethereum/rpc/parameters/HexDataParam.java | 2 +- .../main/java/org/ethereum/rpc/parameters/HexNumberParam.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java index cee7930f320..4ff85034314 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HashParam32.java @@ -37,7 +37,7 @@ public abstract class HashParam32 { try { hashBytes = HexUtils.stringHexToByteArray(hash); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + " format: invalid hex value"); + throw RskJsonRpcRequestException.invalidParamError("Invalid " + hashType + " format: invalid hex value", e); } if (HASH_BYTE_LENGTH != hashBytes.length) { diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java index 4febba555c2..a8c939cc7e5 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexAddressParam.java @@ -41,7 +41,7 @@ public HexAddressParam(String hexAddress) { try { this.address = new RskAddress(hexAddress); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid address format: invalid hex value"); + throw RskJsonRpcRequestException.invalidParamError("Invalid address format: invalid hex value.", e); } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java index 5ad4dd5b856..940a5f2f0d1 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDataParam.java @@ -38,7 +38,7 @@ public HexDataParam(String rawData){ try { this.rawDataBytes = HexUtils.stringHexToByteArray(rawData); } catch (Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid data format: invalid hex value"); + throw RskJsonRpcRequestException.invalidParamError("Invalid data format: invalid hex value.", e); } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java index b25fdcb8eef..aca8eeb28ef 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexNumberParam.java @@ -40,7 +40,7 @@ public HexNumberParam(String hexNumber) { try { new BigInteger(hexNumber); } catch(Exception e) { - throw RskJsonRpcRequestException.invalidParamError("Invalid param " + hexNumber + ": value must be a valid hex or string number."); + throw RskJsonRpcRequestException.invalidParamError("Invalid param " + hexNumber + ": value must be a valid hex or string number.", e); } } From 24fe9400c8097260e067d1d76f3da4cf07a446ef Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Thu, 21 Sep 2023 18:57:13 +0200 Subject: [PATCH 43/47] Adding support for null topics --- .../rpc/parameters/FilterRequestParam.java | 19 +++++++++---------- .../parameters/FilterRequestParamTest.java | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java index 0d732021132..512c41b339f 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java @@ -99,21 +99,17 @@ private Object parseAddressArray() { private Object[] parseTopicArrayToObjectArray() { if (this.topics == null) { - return null; + return new Object[0]; } Object[] result = new Object[this.topics.length]; for (int i = 0; i < this.topics.length; i++) { TopicParam[] topicArray = this.topics[i]; if (topicArray.length == 1) { - if (topicArray[0] != null) { - result[i] = topicArray[0].getHash().toJsonString(); - } + result[i] = topicArray[0] != null ? topicArray[0].getHash().toJsonString() : null; } else { List arrayList = new ArrayList<>(); - for (int j = 0; j < topicArray.length; j++) { - if (topicArray[j] != null) { - arrayList.add(topicArray[j].getHash().toJsonString()); - } + for (TopicParam topicParam : topicArray) { + arrayList.add(topicParam != null ? topicParam.getHash().toJsonString() : null); } result[i] = arrayList; } @@ -172,7 +168,8 @@ private TopicParam[][] getTopicArray(JsonNode node) { TopicParam[] topicParams = getTopics(subNode); topics[i] = topicParams; } else { - topics[i] = new TopicParam[]{new TopicParam(subNode.asText())}; + TopicParam subNodeTopic = subNode.asText().contentEquals("null") ? null : new TopicParam(subNode.asText()); + topics[i] = new TopicParam[]{subNodeTopic}; } } return topics; @@ -184,10 +181,12 @@ private TopicParam[][] getTopicArray(JsonNode node) { private TopicParam[] getTopics(JsonNode jsonNode) { TopicParam[] topicParams = new TopicParam[jsonNode.size()]; for (int j = 0; j < jsonNode.size(); j++) { - topicParams[j] = new TopicParam(jsonNode.get(j).asText()); + JsonNode subNode = jsonNode.get(j); + topicParams[j] = subNode.asText().contentEquals("null") ? null : new TopicParam(subNode.asText()); } return topicParams; } + } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java index 94ed7d5adb7..acf2f7c55b3 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/FilterRequestParamTest.java @@ -136,4 +136,20 @@ void toFilterRequestProducesValidObject() { } + @Test + void canHandleNullTopics() throws JsonProcessingException { + String filterRequestInput = "{\n" + + " \"topics\":[\"0x000000000000000000000000000000006d696e696e675f6665655f746f706963\", null, [\"0x000000000000000000000000000000006d696e696e675f6665655f746f706963\",null]]}"; + JsonNode jsonNode = objectMapper.readTree(filterRequestInput); + FilterRequestParam filterRequestParam = objectMapper.convertValue(jsonNode, FilterRequestParam.class); + FilterRequest fr = objectMapper.convertValue(jsonNode, FilterRequest.class); + + assertNotNull(filterRequestParam); + assertEquals("0x000000000000000000000000000000006d696e696e675f6665655f746f706963", filterRequestParam.getTopics()[0][0].getHash().toJsonString()); + FilterRequest filterRequest = filterRequestParam.toFilterRequest(); + assertNotNull(filterRequest); + assertEquals(3, filterRequest.getTopics().length); + assertEquals(2, ((List) filterRequest.getTopics()[2]).size()); + + } } \ No newline at end of file From 73909be23e015679fab22ba5ac9fe4226787a058 Mon Sep 17 00:00:00 2001 From: Angel Soto Date: Fri, 22 Sep 2023 11:44:21 +0200 Subject: [PATCH 44/47] minor code improvement --- .../java/org/ethereum/rpc/parameters/FilterRequestParam.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java index 512c41b339f..2042cc82d70 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/FilterRequestParam.java @@ -168,7 +168,7 @@ private TopicParam[][] getTopicArray(JsonNode node) { TopicParam[] topicParams = getTopics(subNode); topics[i] = topicParams; } else { - TopicParam subNodeTopic = subNode.asText().contentEquals("null") ? null : new TopicParam(subNode.asText()); + TopicParam subNodeTopic = subNode.isNull() ? null : new TopicParam(subNode.asText()); topics[i] = new TopicParam[]{subNodeTopic}; } } @@ -182,7 +182,7 @@ private TopicParam[] getTopics(JsonNode jsonNode) { TopicParam[] topicParams = new TopicParam[jsonNode.size()]; for (int j = 0; j < jsonNode.size(); j++) { JsonNode subNode = jsonNode.get(j); - topicParams[j] = subNode.asText().contentEquals("null") ? null : new TopicParam(subNode.asText()); + topicParams[j] = subNode.isNull() ? null : new TopicParam(subNode.asText()); } return topicParams; } From 55b42e8259e028b0ddff3894820e14366b8a83f7 Mon Sep 17 00:00:00 2001 From: Volodymyr Kravets Date: Fri, 22 Sep 2023 13:40:55 +0300 Subject: [PATCH 45/47] Fixed tests after the merge from master --- .../co/rsk/rpc/modules/eth/EthModuleTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java index cf9025fecf6..e2e030935a0 100644 --- a/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java +++ b/rskj-core/src/test/java/co/rsk/rpc/modules/eth/EthModuleTest.java @@ -510,7 +510,7 @@ void whenExecuteEstimateGasWithDataParameter_callExecutorWithData() { .thenReturn(executorResult); ReversibleTransactionExecutor reversibleTransactionExecutor = mock(ReversibleTransactionExecutor.class); - when(reversibleTransactionExecutor.estimateGas(eq(block), any(), any(), any(), any(), any(), any(), any())) + when(reversibleTransactionExecutor.estimateGas(eq(block), any(), any(), any(), any(), any(), any(), any(), any())) .thenReturn(transactionExecutor); EthModule eth = new EthModule( @@ -520,7 +520,7 @@ void whenExecuteEstimateGasWithDataParameter_callExecutorWithData() { null, reversibleTransactionExecutor, retriever, - null, + mock(RepositoryLocator.class), null, null, new BridgeSupportFactory( @@ -534,7 +534,7 @@ void whenExecuteEstimateGasWithDataParameter_callExecutorWithData() { ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(reversibleTransactionExecutor, times(1)) - .estimateGas(eq(block), any(), any(), any(), any(), any(), dataCaptor.capture(), any()); + .estimateGas(eq(block), any(), any(), any(), any(), any(), dataCaptor.capture(), any(), any()); assertArrayEquals(HexUtils.strHexOrStrNumberToByteArray(args.getData()), dataCaptor.getValue()); } @@ -555,7 +555,7 @@ void whenExecuteEstimateGasWithInputParameter_callExecutorWithInput() { .thenReturn(executorResult); ReversibleTransactionExecutor reversibleTransactionExecutor = mock(ReversibleTransactionExecutor.class); - when(reversibleTransactionExecutor.estimateGas(eq(block), any(), any(), any(), any(), any(), any(), any())) + when(reversibleTransactionExecutor.estimateGas(eq(block), any(), any(), any(), any(), any(), any(), any(), any())) .thenReturn(transactionExecutor); EthModule eth = new EthModule( @@ -565,7 +565,7 @@ void whenExecuteEstimateGasWithInputParameter_callExecutorWithInput() { null, reversibleTransactionExecutor, retriever, - null, + mock(RepositoryLocator.class), null, null, new BridgeSupportFactory( @@ -579,7 +579,7 @@ void whenExecuteEstimateGasWithInputParameter_callExecutorWithInput() { ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(reversibleTransactionExecutor, times(1)) - .estimateGas(eq(block), any(), any(), any(), any(), any(), dataCaptor.capture(), any()); + .estimateGas(eq(block), any(), any(), any(), any(), any(), dataCaptor.capture(), any(), any()); assertArrayEquals(HexUtils.strHexOrStrNumberToByteArray(args.getInput()), dataCaptor.getValue()); } @@ -601,7 +601,7 @@ void whenExecuteEstimateGasWithInputAndDataParameters_callExecutorWithInput() { .thenReturn(executorResult); ReversibleTransactionExecutor reversibleTransactionExecutor = mock(ReversibleTransactionExecutor.class); - when(reversibleTransactionExecutor.estimateGas(eq(block), any(), any(), any(), any(), any(), any(), any())) + when(reversibleTransactionExecutor.estimateGas(eq(block), any(), any(), any(), any(), any(), any(), any(), any())) .thenReturn(transactionExecutor); EthModule eth = new EthModule( @@ -611,7 +611,7 @@ void whenExecuteEstimateGasWithInputAndDataParameters_callExecutorWithInput() { null, reversibleTransactionExecutor, retriever, - null, + mock(RepositoryLocator.class), null, null, new BridgeSupportFactory( @@ -625,7 +625,7 @@ void whenExecuteEstimateGasWithInputAndDataParameters_callExecutorWithInput() { ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(byte[].class); verify(reversibleTransactionExecutor, times(1)) - .estimateGas(eq(block), any(), any(), any(), any(), any(), dataCaptor.capture(), any()); + .estimateGas(eq(block), any(), any(), any(), any(), any(), dataCaptor.capture(), any(), any()); assertArrayEquals(HexUtils.strHexOrStrNumberToByteArray(args.getInput()), dataCaptor.getValue()); } From 3b3bcc616ee958250aece31e5c3f5f74e65f6f52 Mon Sep 17 00:00:00 2001 From: Volodymyr Kravets Date: Fri, 22 Sep 2023 15:01:20 +0300 Subject: [PATCH 46/47] Added proper handling of number parsing --- .../org/ethereum/rpc/parameters/HexDurationParam.java | 9 +++++++-- .../java/org/ethereum/rpc/parameters/HexIndexParam.java | 7 ++++++- .../ethereum/rpc/parameters/HexDurationParamTest.java | 2 ++ .../org/ethereum/rpc/parameters/HexIndexParamTest.java | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java index a6b0e8f1bad..aae2edb8395 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexDurationParam.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; import java.io.IOException; @@ -31,10 +32,14 @@ public class HexDurationParam extends HexStringParam { public HexDurationParam(String hexDurationStr) { super(hexDurationStr); - if(hexDurationStr.isEmpty()) { + if (hexDurationStr.isEmpty()) { this.duration = null; } else { - this.duration = Long.parseLong(hexDurationStr.substring(2), 16); + try { + this.duration = Long.parseLong(hexDurationStr.substring(2), 16); + } catch (NumberFormatException e) { + throw RskJsonRpcRequestException.invalidParamError("Invalid duration param: value must be a valid hex number.", e); + } } } diff --git a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java index 92e87560321..51376c1b59e 100644 --- a/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java +++ b/rskj-core/src/main/java/org/ethereum/rpc/parameters/HexIndexParam.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.ethereum.rpc.exception.RskJsonRpcRequestException; import java.io.IOException; @@ -33,7 +34,11 @@ public HexIndexParam(String indexString) { super(indexString); String preResult = HexUtils.removeHexPrefix(indexString); - this.index = Integer.parseInt(preResult, 16); + try { + this.index = Integer.parseInt(preResult, 16); + } catch (NumberFormatException e) { + throw RskJsonRpcRequestException.invalidParamError("Invalid index param: value must be a valid hex number.", e); + } } public Integer getIndex() { diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java index 2d47047a3c7..b85612e8ee6 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexDurationParamTest.java @@ -38,8 +38,10 @@ void testValidHexDurationParam() { void testInvalidHexDurationParam() { String invalidHexValue = "1e"; // Missing hex prefix String nonNumericHexValue = "0x1t"; // Non-valid hex value + String invalidDuration = "0xf1652d8322a880e520f996f7d28b645814a58a202d7d2ab7f058e5566fe4f9f3"; // invalid duration assertThrows(RskJsonRpcRequestException.class, () -> new HexDurationParam(invalidHexValue)); assertThrows(RskJsonRpcRequestException.class, () -> new HexDurationParam(nonNumericHexValue)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexDurationParam(invalidDuration)); } } diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java index 10d755c4480..d680ff72dfb 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java @@ -37,9 +37,11 @@ void testValidHexIndexParam() { void testInvalidHexIndexParam() { String invalidHexValue = "123"; // Missing hex prefix String nonNumericHexValue = "0xabcz"; // Non-valid hex value + String invalidIndex = "0xf1652d8322a880e520f996f7d28b645814a58a202d7d2ab7f058e5566fe4f9f3"; // Invalid index assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(invalidHexValue)); assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(nonNumericHexValue)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(invalidIndex)); } } \ No newline at end of file From 5d0a327d5941211fd972820a9b7274eaf4890793 Mon Sep 17 00:00:00 2001 From: Volodymyr Kravets Date: Fri, 22 Sep 2023 15:22:16 +0300 Subject: [PATCH 47/47] Added check for empty string in HexIndexParamTest --- .../java/org/ethereum/rpc/parameters/HexIndexParamTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java index d680ff72dfb..7b0b81058cf 100644 --- a/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java +++ b/rskj-core/src/test/java/org/ethereum/rpc/parameters/HexIndexParamTest.java @@ -37,10 +37,12 @@ void testValidHexIndexParam() { void testInvalidHexIndexParam() { String invalidHexValue = "123"; // Missing hex prefix String nonNumericHexValue = "0xabcz"; // Non-valid hex value + String emptyString = ""; // empty value String invalidIndex = "0xf1652d8322a880e520f996f7d28b645814a58a202d7d2ab7f058e5566fe4f9f3"; // Invalid index assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(invalidHexValue)); assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(nonNumericHexValue)); + assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(emptyString)); assertThrows(RskJsonRpcRequestException.class, () -> new HexIndexParam(invalidIndex)); }