diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java index 03329273f0..187c37d3ba 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java @@ -38,6 +38,7 @@ public enum RpcMethod { DEBUG_TRACE_BLOCK_BY_HASH("debug_traceBlockByHash"), DEBUG_TRACE_BLOCK_BY_NUMBER("debug_traceBlockByNumber"), DEBUG_TRACE_TRANSACTION("debug_traceTransaction"), + DEBUG_BATCH_RAW_TRANSACTION("debug_batchSendRawTransaction"), PRIV_CALL("priv_call"), PRIV_GET_PRIVATE_TRANSACTION("priv_getPrivateTransaction"), PRIV_GET_TRANSACTION_COUNT("priv_getTransactionCount"), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugBatchSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugBatchSendRawTransaction.java new file mode 100644 index 0000000000..e2b91edfce --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugBatchSendRawTransaction.java @@ -0,0 +1,131 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; + +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.api.util.DomainObjectDecodeUtils; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidator; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; +import java.util.stream.IntStream; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.google.common.base.Suppliers; + +public class DebugBatchSendRawTransaction implements JsonRpcMethod { + private final Supplier transactionPool; + + public DebugBatchSendRawTransaction(final TransactionPool transactionPool) { + this(Suppliers.ofInstance(transactionPool)); + } + + public DebugBatchSendRawTransaction(final Supplier transactionPool) { + this.transactionPool = transactionPool; + } + + @Override + public String getName() { + return RpcMethod.DEBUG_BATCH_RAW_TRANSACTION.getMethodName(); + } + + @Override + public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { + final List executionStatuses = new ArrayList<>(); + IntStream.range(0, requestContext.getRequest().getParamLength()) + .forEach( + i -> + executionStatuses.add( + process(i, requestContext.getRequiredParameter(i, String.class)))); + + return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), executionStatuses); + } + + private ExecutionStatus process(final int index, final String rawTransaction) { + try { + final ValidationResult validationResult = + transactionPool + .get() + .addLocalTransaction(DomainObjectDecodeUtils.decodeRawTransaction(rawTransaction)); + return validationResult.either( + () -> new ExecutionStatus(index), + errorReason -> new ExecutionStatus(index, false, errorReason.name())); + } catch (final Throwable e) { + return new ExecutionStatus(index, false, e.getMessage()); + } + } + + @JsonPropertyOrder({"index", "success", "errorMessage"}) + static class ExecutionStatus { + private final int index; + private final boolean success; + private final String errorMessage; + + ExecutionStatus(final int index) { + this(index, true, null); + } + + ExecutionStatus(final int index, final boolean success, final String errorMessage) { + this.index = index; + this.success = success; + this.errorMessage = errorMessage; + } + + @JsonGetter(value = "index") + public int getIndex() { + return index; + } + + @JsonGetter(value = "success") + public boolean isSuccess() { + return success; + } + + @JsonGetter(value = "errorMessage") + @JsonInclude(Include.NON_NULL) + public String getErrorMessage() { + return errorMessage; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final ExecutionStatus other = (ExecutionStatus) o; + return index == other.index + && success == other.success + && Objects.equals(errorMessage, other.errorMessage); + } + + @Override + public int hashCode() { + return Objects.hash(index, success, errorMessage); + } + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java index 41d90d254a..6d9468fc49 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java @@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugAccountRange; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugBatchSendRawTransaction; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugMetrics; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugStorageRangeAt; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlock; @@ -28,6 +29,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTracer; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTracer; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import org.hyperledger.besu.metrics.ObservableMetricsSystem; @@ -39,14 +41,17 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { private final BlockchainQueries blockchainQueries; private final ProtocolSchedule protocolSchedule; private final ObservableMetricsSystem metricsSystem; + private final TransactionPool transactionPool; DebugJsonRpcMethods( final BlockchainQueries blockchainQueries, final ProtocolSchedule protocolSchedule, - final ObservableMetricsSystem metricsSystem) { + final ObservableMetricsSystem metricsSystem, + final TransactionPool transactionPool) { this.blockchainQueries = blockchainQueries; this.protocolSchedule = protocolSchedule; this.metricsSystem = metricsSystem; + this.transactionPool = transactionPool; } @Override @@ -72,6 +77,7 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { ScheduleBasedBlockHeaderFunctions.create(protocolSchedule), blockchainQueries), new DebugTraceBlockByNumber(() -> new BlockTracer(blockReplay), blockchainQueries), - new DebugTraceBlockByHash(() -> new BlockTracer(blockReplay))); + new DebugTraceBlockByHash(() -> new BlockTracer(blockReplay)), + new DebugBatchSendRawTransaction(transactionPool)); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java index 44c020cf56..45af5338de 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java @@ -84,7 +84,8 @@ public class JsonRpcMethodsFactory { blockchainQueries, namedPlugins, natService), - new DebugJsonRpcMethods(blockchainQueries, protocolSchedule, metricsSystem), + new DebugJsonRpcMethods( + blockchainQueries, protocolSchedule, metricsSystem, transactionPool), new EeaJsonRpcMethods( blockchainQueries, protocolSchedule, transactionPool, privacyParameters), new EthJsonRpcMethods( diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugBatchSendRawTransactionTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugBatchSendRawTransactionTest.java new file mode 100644 index 0000000000..feec12cba0 --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugBatchSendRawTransactionTest.java @@ -0,0 +1,126 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugBatchSendRawTransaction.ExecutionStatus; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +@SuppressWarnings("unchecked") +public class DebugBatchSendRawTransactionTest { + + private static final String NAME = RpcMethod.DEBUG_BATCH_RAW_TRANSACTION.getMethodName(); + private static final String VERSION = "2.0"; + @Mock TransactionPool transactionPool; + DebugBatchSendRawTransaction method; + + @Before + public void setUp() { + method = new DebugBatchSendRawTransaction(transactionPool); + } + + @Test + public void nominalCaseSingleTransaction() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest( + VERSION, + NAME, + new Object[] { + "0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ba0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43" + })); + when(transactionPool.addLocalTransaction(any(Transaction.class))) + .thenReturn(ValidationResult.valid()); + final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request); + assertThat(response).isNotNull(); + final List result = (List) response.getResult(); + assertThat(result).isNotNull().hasSize(1).containsExactly(new ExecutionStatus(0)); + } + + @Test + public void nominalCaseMultipleTransactions() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest( + VERSION, + NAME, + new Object[] { + "0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ba0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43", + "0xf868018203e882520894627306090abab3a6e1400e9345bc60c78a8bef57876a94d74f430000801ba092faeec7bcb7418a79cd9f74c739237d72d52b5ab25aa08e332053304456e129a0386e3e9205a3553ecc5e85fc753c93196484c0fdeaaacdd61425caeb11bc6e5a" + })); + when(transactionPool.addLocalTransaction(any(Transaction.class))) + .thenReturn(ValidationResult.valid()); + final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request); + assertThat(response).isNotNull(); + final List result = (List) response.getResult(); + assertThat(result) + .isNotNull() + .hasSize(2) + .containsExactly(new ExecutionStatus(0), new ExecutionStatus(1)); + } + + @Test + public void errorSingleTransactionHexParsing() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext(new JsonRpcRequest(VERSION, NAME, new Object[] {"www"})); + + final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request); + assertThat(response).isNotNull(); + final List result = (List) response.getResult(); + assertThat(result) + .isNotNull() + .hasSize(1) + .containsExactly(new ExecutionStatus(0, false, "Invalid raw transaction hex")); + } + + @Test + public void errorSingleTransactionSignatureInvalidV() { + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest( + VERSION, + NAME, + new Object[] { + "0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801fa0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43" + })); + + final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) method.response(request); + assertThat(response).isNotNull(); + final List result = (List) response.getResult(); + assertThat(result) + .isNotNull() + .hasSize(1) + .containsExactly( + new ExecutionStatus(0, false, "An unsupported encoded `v` value of 31 was found")); + } +} diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxError.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxError.json new file mode 100644 index 0000000000..aded02d002 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxError.json @@ -0,0 +1,28 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "debug_batchSendRawTransaction", + "params": [ + "0x416", + "zXDf" + ], + "id": 1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "index": 0, + "success": false, + "errorMessage": "Invalid raw transaction hex" + }, + { + "index": 1, + "success": false, + "errorMessage": "Invalid raw transaction hex" + } + ] + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxMixedStatuses.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxMixedStatuses.json new file mode 100644 index 0000000000..6cbd3853fb --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxMixedStatuses.json @@ -0,0 +1,38 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "debug_batchSendRawTransaction", + "params": [ + "0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ba0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43", + "gdTr", + "0xf868018203e882520894627306090abab3a6e1400e9345bc60c78a8bef57876a94d74f430000801ba092faeec7bcb7418a79cd9f74c739237d72d52b5ab25aa08e332053304456e129a0386e3e9205a3553ecc5e85fc753c93196484c0fdeaaacdd61425caeb11bc6e5a", + "0x147" + ], + "id": 1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "index": 0, + "success": true + }, + { + "index": 1, + "success": false, + "errorMessage": "Invalid raw transaction hex" + }, + { + "index": 2, + "success": true + }, + { + "index": 3, + "success": false, + "errorMessage": "Invalid raw transaction hex" + } + ] + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxSuccess.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxSuccess.json new file mode 100644 index 0000000000..728138e788 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_multipleTxSuccess.json @@ -0,0 +1,26 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "debug_batchSendRawTransaction", + "params": [ + "0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ba0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43", + "0xf868018203e882520894627306090abab3a6e1400e9345bc60c78a8bef57876a94d74f430000801ba092faeec7bcb7418a79cd9f74c739237d72d52b5ab25aa08e332053304456e129a0386e3e9205a3553ecc5e85fc753c93196484c0fdeaaacdd61425caeb11bc6e5a" + ], + "id": 1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "index": 0, + "success": true + }, + { + "index": 1, + "success": true + } + ] + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxError.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxError.json new file mode 100644 index 0000000000..480817bc54 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxError.json @@ -0,0 +1,21 @@ +{ + "request": { + "jsonrpc":"2.0", + "method":"debug_batchSendRawTransaction", + "params":[ + "0x416" ], + "id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "index": 0, + "success": false, + "errorMessage": "Invalid raw transaction hex" + } + ] + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxErrorInvalidSignatureV.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxErrorInvalidSignatureV.json new file mode 100644 index 0000000000..7681047083 --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxErrorInvalidSignatureV.json @@ -0,0 +1,22 @@ +{ + "request": { + "jsonrpc": "2.0", + "method": "debug_batchSendRawTransaction", + "params": [ + "0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801fa0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43" + ], + "id": 1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "index": 0, + "success": false, + "errorMessage": "An unsupported encoded `v` value of 31 was found" + } + ] + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxSuccess.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxSuccess.json new file mode 100644 index 0000000000..04c31d068b --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/debug/debug_batchSendRawTransaction_singleTxSuccess.json @@ -0,0 +1,20 @@ +{ + "request": { + "jsonrpc":"2.0", + "method":"debug_batchSendRawTransaction", + "params":[ + "0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ba0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43" ], + "id":1 + }, + "response": { + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "index": 0, + "success": true + } + ] + }, + "statusCode": 200 +} \ No newline at end of file