Add 0x check for Address, Bytes, and Bytes32 in GraphQl requests (#1057)

Produce error response if any of Address, Bytes or Bytes32 values
inside GraphQl requests are not prefixed with 0x as defined by the spec.

Fix old tests that used values that are not prefixed with 0x and add
additional tests to confirm Address, Bytes and Bytes32 values will be
rejected if not prefixed with 0x.

Signed-off-by: Mak Muftic <mak@nodefactory.io>
pull/1198/head
mace 4 years ago committed by GitHub
parent 9c409258b1
commit ba491c7ee0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/Scalars.java
  2. 10
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/Quantity.java
  3. 3
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/EthGraphQLHttpBySpecTest.java
  4. 2
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8.json
  5. 21
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_Block8_invalidHexBytesData.json
  6. 2
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_call_BlockLatest.json
  7. 20
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBalance_invalidHexAddress.json
  8. 20
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/eth_getBlock_byHash_InvalidHexBytes32Hash.json
  9. 2
      ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/graphql/graphql_pending.json

@ -14,6 +14,7 @@
*/ */
package org.hyperledger.besu.ethereum.api.graphql.internal; package org.hyperledger.besu.ethereum.api.graphql.internal;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity;
import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
@ -55,8 +56,13 @@ public class Scalars {
if (!(input instanceof StringValue)) { if (!(input instanceof StringValue)) {
throw new CoercingParseLiteralException("Value is not any Address : '" + input + "'"); throw new CoercingParseLiteralException("Value is not any Address : '" + input + "'");
} }
String inputValue = ((StringValue) input).getValue();
if (!Quantity.isValid(inputValue)) {
throw new CoercingParseLiteralException(
"Address value '" + inputValue + "' is not prefixed with 0x");
}
try { try {
return Address.fromHexStringStrict(((StringValue) input).getValue()); return Address.fromHexStringStrict(inputValue);
} catch (final IllegalArgumentException e) { } catch (final IllegalArgumentException e) {
throw new CoercingParseLiteralException("Value is not any Address : '" + input + "'"); throw new CoercingParseLiteralException("Value is not any Address : '" + input + "'");
} }
@ -121,8 +127,13 @@ public class Scalars {
if (!(input instanceof StringValue)) { if (!(input instanceof StringValue)) {
throw new CoercingParseLiteralException("Value is not any Bytes : '" + input + "'"); throw new CoercingParseLiteralException("Value is not any Bytes : '" + input + "'");
} }
String inputValue = ((StringValue) input).getValue();
if (!Quantity.isValid(inputValue)) {
throw new CoercingParseLiteralException(
"Bytes value '" + inputValue + "' is not prefixed with 0x");
}
try { try {
return Bytes.fromHexStringLenient(((StringValue) input).getValue()); return Bytes.fromHexStringLenient(inputValue);
} catch (final IllegalArgumentException e) { } catch (final IllegalArgumentException e) {
throw new CoercingParseLiteralException("Value is not any Bytes : '" + input + "'"); throw new CoercingParseLiteralException("Value is not any Bytes : '" + input + "'");
} }
@ -156,8 +167,13 @@ public class Scalars {
if (!(input instanceof StringValue)) { if (!(input instanceof StringValue)) {
throw new CoercingParseLiteralException("Value is not any Bytes32 : '" + input + "'"); throw new CoercingParseLiteralException("Value is not any Bytes32 : '" + input + "'");
} }
String inputValue = ((StringValue) input).getValue();
if (!Quantity.isValid(inputValue)) {
throw new CoercingParseLiteralException(
"Bytes32 value '" + inputValue + "' is not prefixed with 0x");
}
try { try {
return Bytes32.fromHexStringLenient(((StringValue) input).getValue()); return Bytes32.fromHexStringLenient(inputValue);
} catch (final IllegalArgumentException e) { } catch (final IllegalArgumentException e) {
throw new CoercingParseLiteralException("Value is not any Bytes32 : '" + input + "'"); throw new CoercingParseLiteralException("Value is not any Bytes32 : '" + input + "'");
} }

@ -77,6 +77,16 @@ public class Quantity {
return String.format("%s%s%s", HEX_PREFIX, zeroPadding, formatted); return String.format("%s%s%s", HEX_PREFIX, zeroPadding, formatted);
} }
/**
* Checks if value is prefixed with '0x'
*
* @param value that is checked
* @return true if value is prefixed with '0x', false otherwise
*/
public static boolean isValid(final String value) {
return value.startsWith(HEX_PREFIX);
}
private static String uint256ToHex(final UInt256Value<?> value) { private static String uint256ToHex(final UInt256Value<?> value) {
return value == null ? null : formatMinimalValue(value.toMinimalBytes().toShortHexString()); return value == null ? null : formatMinimalValue(value.toMinimalBytes().toShortHexString());
} }

@ -47,6 +47,7 @@ public class EthGraphQLHttpBySpecTest extends AbstractEthGraphQLHttpServiceTest
specs.add("eth_blockNumber"); specs.add("eth_blockNumber");
specs.add("eth_call_Block8"); specs.add("eth_call_Block8");
specs.add("eth_call_Block8_invalidHexBytesData");
specs.add("eth_call_BlockLatest"); specs.add("eth_call_BlockLatest");
specs.add("eth_estimateGas_transfer"); specs.add("eth_estimateGas_transfer");
@ -58,11 +59,13 @@ public class EthGraphQLHttpBySpecTest extends AbstractEthGraphQLHttpServiceTest
specs.add("eth_getBalance_0x19"); specs.add("eth_getBalance_0x19");
specs.add("eth_getBalance_invalidAccountBlockNumber"); specs.add("eth_getBalance_invalidAccountBlockNumber");
specs.add("eth_getBalance_invalidAccountLatest"); specs.add("eth_getBalance_invalidAccountLatest");
specs.add("eth_getBalance_invalidHexAddress");
specs.add("eth_getBalance_latest"); specs.add("eth_getBalance_latest");
specs.add("eth_getBalance_toobig_bn"); specs.add("eth_getBalance_toobig_bn");
specs.add("eth_getBalance_without_addr"); specs.add("eth_getBalance_without_addr");
specs.add("eth_getBlock_byHash"); specs.add("eth_getBlock_byHash");
specs.add("eth_getBlock_byHash_InvalidHexBytes32Hash");
specs.add("eth_getBlock_byHashInvalid"); specs.add("eth_getBlock_byHashInvalid");
specs.add("eth_getBlock_byNumber"); specs.add("eth_getBlock_byNumber");
specs.add("eth_getBlock_byNumberInvalid"); specs.add("eth_getBlock_byNumberInvalid");

@ -1,5 +1,5 @@
{ {
"request": "{block(number :\"0x8\") {number call (data : {from : \"a94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}" "request": "{block(number :\"0x8\") {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}"
, ,
"response":{ "response":{
"data" : { "data" : {

@ -0,0 +1,21 @@
{
"request": "{block(number :\"0x8\") {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"12a7b914\"}){data status}}}"
,
"response": {
"errors": [
{
"message": "Validation error of type WrongType: argument 'data.data' with value 'StringValue{value='12a7b914'}' is not a valid 'Bytes' - Bytes value '12a7b914' is not prefixed with 0x @ 'block/call'",
"locations": [
{
"line": 1,
"column": 37
}
],
"extensions": {
"classification": "ValidationError"
}
}
]
},
"statusCode": 400
}

@ -1,5 +1,5 @@
{ {
"request": "{block {number call (data : {from : \"a94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}" "request": "{block {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}}}"
, ,
"response":{ "response":{
"data" : { "data" : {

@ -0,0 +1,20 @@
{
"request": "{account(blockNumber:\"0x19\", address: \"6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance } }",
"response": {
"errors": [
{
"message": "Validation error of type WrongType: argument 'address' with value 'StringValue{value='6295ee1b4f6dd65047762f924ecd367c17eabf8f'}' is not a valid 'Address' - Address value '6295ee1b4f6dd65047762f924ecd367c17eabf8f' is not prefixed with 0x @ 'account'",
"locations": [
{
"line": 1,
"column": 30
}
],
"extensions": {
"classification": "ValidationError"
}
}
]
},
"statusCode": 400
}

@ -0,0 +1,20 @@
{
"request": "{block (hash : \"c8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6\") {number } }",
"response": {
"errors": [
{
"message": "Validation error of type WrongType: argument 'hash' with value 'StringValue{value='c8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6'}' is not a valid 'Bytes32' - Bytes32 value 'c8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6' is not prefixed with 0x @ 'block'",
"locations": [
{
"line": 1,
"column": 9
}
],
"extensions": {
"classification": "ValidationError"
}
}
]
},
"statusCode": 400
}

@ -1,6 +1,6 @@
{ {
"request": "request":
"{ pending { transactionCount transactions { nonce gas } account(address:\"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance} estimateGas(data:{}) call (data : {from : \"a94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}} }", "{ pending { transactionCount transactions { nonce gas } account(address:\"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\") { balance} estimateGas(data:{}) call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", data :\"0x12a7b914\"}){data status}} }",
"response": { "response": {
"data": { "data": {

Loading…
Cancel
Save