diff --git a/CHANGELOG.md b/CHANGELOG.md index e2b3ea072bd..bee4620060c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Implement gnark-crypto for eip-2537 [#7316](https://github.com/hyperledger/besu/pull/7316) ### Bug fixes +- Fix `eth_call` deserialization to correctly ignore unknown fields in the transaction object. [#7323](https://github.com/hyperledger/besu/pull/7323) ## 24.7.0 diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCallIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCallIntegrationTest.java index 14aa15c5c8f..886f7bc0158 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCallIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCallIntegrationTest.java @@ -64,20 +64,12 @@ public void setUp() { @Test public void shouldReturnExpectedResultForCallAtLatestBlock() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - null, - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -91,20 +83,12 @@ public void shouldReturnExpectedResultForCallAtLatestBlock() { @Test public void shouldReturnExpectedResultForCallAtSpecificBlock() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - null, - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "0x8"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -118,21 +102,13 @@ public void shouldReturnExpectedResultForCallAtSpecificBlock() { @Test public void shouldReturnSuccessWhenCreatingContract() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - null, - null, - null, - null, - null, - null, - Bytes.fromHexString( - "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withInput( + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -147,20 +123,13 @@ public void shouldReturnSuccessWhenCreatingContract() { @Test public void shouldReturnErrorWithGasLimitTooLow() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - 0L, - null, - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withGas(0L) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.INTRINSIC_GAS_EXCEEDS_LIMIT); @@ -173,20 +142,14 @@ public void shouldReturnErrorWithGasLimitTooLow() { @Test public void shouldReturnErrorWithGasPriceTooHighAndStrict() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - Wei.fromHexString("0x10000000000000"), - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - true, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withGasPrice(Wei.fromHexString("0x10000000000000")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .withStrict(true) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE); @@ -199,20 +162,14 @@ public void shouldReturnErrorWithGasPriceTooHighAndStrict() { @Test public void shouldReturnSuccessWithGasPriceTooHighNotStrict() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - Wei.fromHexString("0x10000000000000"), - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - false, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withGasPrice(Wei.fromHexString("0x10000000000000")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .withStrict(false) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -226,20 +183,13 @@ public void shouldReturnSuccessWithGasPriceTooHighNotStrict() { @Test public void shouldReturnErrorWithGasPriceTooHigh() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - Wei.fromHexString("0x10000000000000"), - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withGasPrice(Wei.fromHexString("0x10000000000000")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE); @@ -252,20 +202,13 @@ public void shouldReturnErrorWithGasPriceTooHigh() { @Test public void shouldReturnSuccessWithValidGasPrice() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - Wei.fromHexString("0x10"), - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withGasPrice(Wei.fromHexString("0x10")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -279,20 +222,13 @@ public void shouldReturnSuccessWithValidGasPrice() { @Test public void shouldReturnErrorWithGasPriceAndEmptyBalance() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xdeadbeef00000000000000000000000000000000"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - Wei.fromHexString("0x10"), - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xdeadbeef00000000000000000000000000000000")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withGasPrice(Wei.fromHexString("0x10")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE); @@ -305,20 +241,13 @@ public void shouldReturnErrorWithGasPriceAndEmptyBalance() { @Test public void shouldReturnSuccessWithZeroGasPriceAndEmptyBalance() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xdeadbeef00000000000000000000000000000000"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - Wei.fromHexString("0x0"), - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xdeadbeef00000000000000000000000000000000")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withGasPrice(Wei.fromHexString("0x0")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -332,20 +261,12 @@ public void shouldReturnSuccessWithZeroGasPriceAndEmptyBalance() { @Test public void shouldReturnSuccessWithoutGasPriceAndEmptyBalance() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xdeadbeef00000000000000000000000000000000"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - null, - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xdeadbeef00000000000000000000000000000000")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -359,20 +280,13 @@ public void shouldReturnSuccessWithoutGasPriceAndEmptyBalance() { @Test public void shouldReturnSuccessWithInvalidGasPricingAndEmptyBalance() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xdeadbeef00000000000000000000000000000000"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - null, - Wei.fromHexString("0x0A"), - null, - null, - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xdeadbeef00000000000000000000000000000000")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withMaxPriorityFeePerGas(Wei.fromHexString("0x0A")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -386,20 +300,10 @@ public void shouldReturnSuccessWithInvalidGasPricingAndEmptyBalance() { @Test public void shouldReturnEmptyHashResultForCallWithOnlyToField() { final JsonCallParameter callParameter = - new JsonCallParameter( - null, - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x"); @@ -411,20 +315,13 @@ public void shouldReturnEmptyHashResultForCallWithOnlyToField() { @Test public void shouldReturnSuccessWithInputAndDataFieldSetToSameValue() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - null, - null, - null, - null, - Bytes.fromHexString("0x12a7b914"), - Bytes.fromHexString("0x12a7b914"), - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withInput(Bytes.fromHexString("0x12a7b914")) + .withData(Bytes.fromHexString("0x12a7b914")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCreateAccessListIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCreateAccessListIntegrationTest.java index e68fd29d18b..49b9659fd9d 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCreateAccessListIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthCreateAccessListIntegrationTest.java @@ -79,10 +79,11 @@ public void shouldSucceedWhenCreateAccessListMultipleReads() { "0x0000000000000000000000000000000000000000000000000000000000000003")))); final JsonCallParameter callParameter = - createAccessListJsonCallParameters( - "0x658bdf435d810c91414ec09147daa6db62406379", - "0xbb00000000000000000000000000000000000000", - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x658bdf435d810c91414ec09147daa6db62406379")) + .withTo(Address.fromHexString("0xbb00000000000000000000000000000000000000")) + .withAccessList(null) + .build(); assertAccessListExpectedResult(callParameter, expectedAccessListEntryList, expectedGasUsed); } @@ -101,10 +102,11 @@ public void shouldSucceedWhenCreateAccessListMultipleReads_withAccessListParam() "0x0000000000000000000000000000000000000000000000000000000000000003")))); final JsonCallParameter callParameter = - createAccessListJsonCallParameters( - "0x658bdf435d810c91414ec09147daa6db62406379", - "0xbb00000000000000000000000000000000000000", - expectedAccessListEntryList); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x658bdf435d810c91414ec09147daa6db62406379")) + .withTo(Address.fromHexString("0xbb00000000000000000000000000000000000000")) + .withAccessList(expectedAccessListEntryList) + .build(); assertAccessListExpectedResult(callParameter, expectedAccessListEntryList, expectedGasUsed); } @@ -115,10 +117,11 @@ public void shouldSucceedWhenCreateAccessListSimpleTransfer() { final List expectedAccessListEntryList = new ArrayList<>(); final JsonCallParameter callParameter = - createAccessListJsonCallParameters( - "0x658bdf435d810c91414ec09147daa6db62406379", - "0x0100000000000000000000000000000000000000", - expectedAccessListEntryList); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x658bdf435d810c91414ec09147daa6db62406379")) + .withTo(Address.fromHexString("0x0100000000000000000000000000000000000000")) + .withAccessList(expectedAccessListEntryList) + .build(); assertAccessListExpectedResult(callParameter, expectedAccessListEntryList, expectedGasUsed); } @@ -129,10 +132,11 @@ public void shouldSucceedWhenCreateAccessListSimpleContract() { final List expectedAccessListEntryList = new ArrayList<>(); final JsonCallParameter callParameter = - createAccessListJsonCallParameters( - "0x658bdf435d810c91414ec09147daa6db62406379", - "0xaa00000000000000000000000000000000000000", - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x658bdf435d810c91414ec09147daa6db62406379")) + .withTo(Address.fromHexString("0xaa00000000000000000000000000000000000000")) + .withAccessList(null) + .build(); assertAccessListExpectedResult(callParameter, expectedAccessListEntryList, expectedGasUsed); } @@ -140,8 +144,8 @@ public void shouldSucceedWhenCreateAccessListSimpleContract() { @Test public void shouldReturnExpectedValueForEmptyCallParameter() { final JsonCallParameter callParameter = - new JsonCallParameter( - null, null, null, null, null, null, null, null, null, null, null, null, null); + new JsonCallParameter.JsonCallParameterBuilder().build(); + final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, new CreateAccessListResult(new ArrayList<>(), 0xcf08)); @@ -154,20 +158,12 @@ public void shouldReturnExpectedValueForEmptyCallParameter() { @Test public void shouldReturnExpectedValueForTransfer() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1"), - null, - null, - null, - null, - Wei.ZERO, - null, - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1")) + .withValue(Wei.ZERO) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, new CreateAccessListResult(new ArrayList<>(), 0x5208)); @@ -180,21 +176,13 @@ public void shouldReturnExpectedValueForTransfer() { @Test public void shouldReturnExpectedValueForContractDeploy() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - null, - null, - null, - null, - null, - null, - Bytes.fromHexString( - "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withInput( + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, new CreateAccessListResult(new ArrayList<>(), 0x1f081)); @@ -207,21 +195,16 @@ public void shouldReturnExpectedValueForContractDeploy() { @Test public void shouldIgnoreSenderBalanceAccountWhenStrictModeDisabledAndReturnExpectedValue() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0x0000000000000000000000000000000000000000"), - null, - 1L, - Wei.fromHexString("0x9999999999"), - null, - null, - null, - Bytes.fromHexString( - "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), - null, - false, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0000000000000000000000000000000000000000")) + .withGas(1L) + .withGasPrice(Wei.fromHexString("0x9999999999")) + .withInput( + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029")) + .withStrict(false) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, new CreateAccessListResult(new ArrayList<>(), 0x1f081)); @@ -234,8 +217,7 @@ public void shouldIgnoreSenderBalanceAccountWhenStrictModeDisabledAndReturnExpec @Test public void shouldReturnExpectedValueForInsufficientGas() { final JsonCallParameter callParameter = - new JsonCallParameter( - null, null, 1L, null, null, null, null, null, null, null, null, null, null); + new JsonCallParameter.JsonCallParameterBuilder().withGas(1L).build(); final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, new CreateAccessListResult(new ArrayList<>(), 0xcf08)); @@ -257,24 +239,6 @@ private void assertAccessListExpectedResult( assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); } - private JsonCallParameter createAccessListJsonCallParameters( - final String from, final String to, final List accessList) { - return new JsonCallParameter( - Address.fromHexString(from), - Address.fromHexString(to), - null, - null, - null, - null, - null, - null, - null, - null, - accessList, - null, - null); - } - private JsonRpcRequestContext requestWithParams(final Object... params) { return new JsonRpcRequestContext(new JsonRpcRequest("2.0", "eth_createAccessList", params)); } diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthEstimateGasIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthEstimateGasIntegrationTest.java index a461539030f..d17a2774e6c 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthEstimateGasIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/EthEstimateGasIntegrationTest.java @@ -66,8 +66,7 @@ public void setUp() { @Test public void shouldReturnExpectedValueForEmptyCallParameter() { final JsonCallParameter callParameter = - new JsonCallParameter( - null, null, null, null, null, null, null, null, null, null, null, null, null); + new JsonCallParameter.JsonCallParameterBuilder().build(); final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x5208"); @@ -79,20 +78,12 @@ public void shouldReturnExpectedValueForEmptyCallParameter() { @Test public void shouldReturnExpectedValueForTransfer() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1"), - null, - null, - null, - null, - Wei.ONE, - null, - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1")) + .withValue(Wei.ONE) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x5208"); @@ -104,21 +95,13 @@ public void shouldReturnExpectedValueForTransfer() { @Test public void shouldReturnExpectedValueForContractDeploy() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - null, - null, - null, - null, - null, - null, - Bytes.fromHexString( - "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withInput( + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x1b551"); @@ -130,21 +113,16 @@ public void shouldReturnExpectedValueForContractDeploy() { @Test public void shouldIgnoreSenderBalanceAccountWhenStrictModeDisabledAndReturnExpectedValue() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0x0000000000000000000000000000000000000000"), - null, - 1L, - Wei.fromHexString("0x9999999999"), - null, - null, - null, - Bytes.fromHexString( - "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), - null, - false, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0000000000000000000000000000000000000000")) + .withGas(1L) + .withGasPrice(Wei.fromHexString("0x9999999999")) + .withInput( + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029")) + .withStrict(false) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x1b551"); @@ -156,21 +134,16 @@ public void shouldIgnoreSenderBalanceAccountWhenStrictModeDisabledAndReturnExpec @Test public void shouldNotIgnoreSenderBalanceAccountWhenStrictModeDisabledAndThrowError() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"), - null, - 1L, - Wei.fromHexString("0x9999999999"), - null, - null, - null, - Bytes.fromHexString( - "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), - null, - true, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f")) + .withGas(1L) + .withGasPrice(Wei.fromHexString("0x9999999999")) + .withInput( + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029")) + .withStrict(true) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter); final ValidationResult validationResult = ValidationResult.invalid( @@ -186,8 +159,7 @@ public void shouldNotIgnoreSenderBalanceAccountWhenStrictModeDisabledAndThrowErr @Test public void shouldReturnExpectedValueForInsufficientGas() { final JsonCallParameter callParameter = - new JsonCallParameter( - null, null, 1L, null, null, null, null, null, null, null, null, null, null); + new JsonCallParameter.JsonCallParameterBuilder().withGas(1L).build(); final JsonRpcRequestContext request = requestWithParams(callParameter); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x5208"); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthCallIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthCallIntegrationTest.java index e92076123b2..5f03d7f4d5f 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthCallIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthCallIntegrationTest.java @@ -64,20 +64,12 @@ public void setUp() { @Test public void shouldReturnSuccessWithoutGasPriceAndEmptyBalance() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xdeadbeef00000000000000000000000000000000"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - null, - null, - null, - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xdeadbeef00000000000000000000000000000000")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -91,20 +83,13 @@ public void shouldReturnSuccessWithoutGasPriceAndEmptyBalance() { @Test public void shouldReturnErrorWithGasPriceTooHigh() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - Wei.fromHexString("0x10000000000000"), - null, - null, - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withGasPrice(Wei.fromHexString("0x10000000000000")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE); @@ -117,20 +102,13 @@ public void shouldReturnErrorWithGasPriceTooHigh() { @Test public void shouldReturnSuccessWithValidGasPrice() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - Wei.fromHexString("0x3B9ACA01"), - null, - null, - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withGasPrice(Wei.fromHexString("0x3B9ACA01")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -144,20 +122,13 @@ public void shouldReturnSuccessWithValidGasPrice() { @Test public void shouldReturnErrorWithGasPriceLessThanCurrentBaseFee() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - Wei.fromHexString("0x0A"), - null, - null, - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withGasPrice(Wei.fromHexString("0x0A")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.GAS_PRICE_BELOW_CURRENT_BASE_FEE); @@ -170,20 +141,13 @@ public void shouldReturnErrorWithGasPriceLessThanCurrentBaseFee() { @Test public void shouldReturnSuccessWithValidMaxFeePerGas() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - null, - null, - Wei.fromHexString("0x3B9ACA01"), - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withMaxFeePerGas(Wei.fromHexString("0x3B9ACA01")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -197,20 +161,14 @@ public void shouldReturnSuccessWithValidMaxFeePerGas() { @Test public void shouldReturnSuccessWithValidMaxFeePerGasAndMaxPriorityFeePerGas() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - null, - Wei.fromHexString("0x3B9ACA00"), - Wei.fromHexString("0x3B9ACA01"), - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withMaxPriorityFeePerGas(Wei.fromHexString("0x3B9ACA00")) + .withMaxFeePerGas(Wei.fromHexString("0x3B9ACA01")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse( @@ -224,20 +182,13 @@ public void shouldReturnSuccessWithValidMaxFeePerGasAndMaxPriorityFeePerGas() { @Test public void shouldReturnErrorWithValidMaxFeePerGasLessThanCurrentBaseFee() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - null, - null, - Wei.fromHexString("0x0A"), - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withMaxFeePerGas(Wei.fromHexString("0x0A")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.GAS_PRICE_BELOW_CURRENT_BASE_FEE); @@ -250,20 +201,14 @@ public void shouldReturnErrorWithValidMaxFeePerGasLessThanCurrentBaseFee() { @Test public void shouldReturnErrorWithValidMaxFeePerGasLessThanMaxPriorityFeePerGas() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - null, - Wei.fromHexString("0x3B9ACA02"), - Wei.fromHexString("0x3B9ACA01"), - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withMaxPriorityFeePerGas(Wei.fromHexString("0x3B9ACA02")) + .withMaxFeePerGas(Wei.fromHexString("0x3B9ACA01")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse( @@ -277,20 +222,13 @@ public void shouldReturnErrorWithValidMaxFeePerGasLessThanMaxPriorityFeePerGas() @Test public void shouldReturnErrorWithMaxFeePerGasAndEmptyBalance() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xdeadbeef00000000000000000000000000000000"), - Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517"), - null, - null, - null, - Wei.fromHexString("0x3B9ACA01"), - null, - Bytes.fromHexString("0x2e64cec1"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xdeadbeef00000000000000000000000000000000")) + .withTo(Address.fromHexString("0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517")) + .withMaxFeePerGas(Wei.fromHexString("0x3B9ACA01")) + .withInput(Bytes.fromHexString("0x2e64cec1")) + .build(); + final JsonRpcRequestContext request = requestWithParams(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcErrorResponse(null, RpcErrorType.TRANSACTION_UPFRONT_COST_EXCEEDS_BALANCE); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthEstimateGasIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthEstimateGasIntegrationTest.java index 0a3ba1be7fe..84447dfc9d3 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthEstimateGasIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthEstimateGasIntegrationTest.java @@ -67,20 +67,11 @@ public void setUp() { @Test public void shouldReturnExpectedValueForTransfer() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1"), - null, - null, - null, - null, - Wei.ONE, - null, - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1")) + .withValue(Wei.ONE) + .build(); final JsonRpcResponse response = method.response(requestWithParams(callParameter)); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x5208"); @@ -89,22 +80,13 @@ public void shouldReturnExpectedValueForTransfer() { @Test public void shouldReturnExpectedValueForTransfer_WithAccessList() { - final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1"), - null, - null, - null, - null, - Wei.ONE, - null, - null, - null, - createAccessList(), - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withTo(Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1")) + .withValue(Wei.ONE) + .withAccessList(createAccessList()) + .build(); final JsonRpcResponse response = method.response(requestWithParams(callParameter)); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x62d4"); @@ -114,21 +96,13 @@ public void shouldReturnExpectedValueForTransfer_WithAccessList() { @Test public void shouldReturnExpectedValueForContractDeploy() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - null, - null, - null, - null, - null, - null, - Bytes.fromHexString( - "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withInput( + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029")) + .build(); + final JsonRpcResponse response = method.response(requestWithParams(callParameter)); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x1f081"); assertThat(response).usingRecursiveComparison().isEqualTo(expectedResponse); @@ -137,21 +111,13 @@ public void shouldReturnExpectedValueForContractDeploy() { @Test public void shouldReturnExpectedValueForContractDeploy_WithAccessList() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"), - null, - null, - null, - null, - null, - null, - Bytes.fromHexString( - "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029"), - null, - null, - createAccessList(), - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) + .withInput( + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b50610157806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633bdab8bf146100515780639ae97baa14610068575b600080fd5b34801561005d57600080fd5b5061006661007f565b005b34801561007457600080fd5b5061007d6100b9565b005b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60016040518082815260200191505060405180910390a1565b7fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60026040518082815260200191505060405180910390a17fa53887c1eed04528e23301f55ad49a91634ef5021aa83a97d07fd16ed71c039a60036040518082815260200191505060405180910390a15600a165627a7a7230582010ddaa52e73a98c06dbcd22b234b97206c1d7ed64a7c048e10c2043a3d2309cb0029")) + .withAccessList(createAccessList()) + .build(); final JsonRpcResponse response = method.response(requestWithParams(callParameter)); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, "0x2014d"); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java index 237eef2e022..ef8ca5b316d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java @@ -17,7 +17,6 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; @@ -94,16 +93,6 @@ protected long processEstimateGas( return ((long) ((gasUsedByTransaction + gasStipend) * subCallMultiplier)); } - protected JsonCallParameter validateAndGetCallParams(final JsonRpcRequestContext request) { - final JsonCallParameter callParams = request.getRequiredParameter(0, JsonCallParameter.class); - if (callParams.getGasPrice() != null - && (callParams.getMaxFeePerGas().isPresent() - || callParams.getMaxPriorityFeePerGas().isPresent())) { - throw new InvalidJsonRpcParameters("gasPrice cannot be used with baseFee or maxFeePerGas"); - } - return callParams; - } - protected JsonRpcErrorResponse errorResponse( final JsonRpcRequestContext request, final TransactionSimulatorResult result) { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessList.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessList.java index b6b9f5171fa..2be5047a24a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessList.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessList.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonCallParameterUtil.validateAndGetCallParams; + import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java index c0631bf44cb..ca084ba0fbb 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonCallParameterUtil.validateAndGetCallParams; + 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.parameters.JsonCallParameter; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/JsonCallParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/JsonCallParameter.java index b084ebc9135..987b68c2e2f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/JsonCallParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/JsonCallParameter.java @@ -26,68 +26,338 @@ import java.util.Optional; import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.apache.tuweni.bytes.Bytes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * This class is used to deserialize JSON parameters for a call to the JSON-RPC method eth_call. It + * extends {@link CallParameter} by adding support for JSON-specific fields such as strict mode, + * access lists, and blob versioned hashes. It also handles unknown JSON properties gracefully. + * + *

To build an instance of this class, use the {@link JsonCallParameterBuilder}: + * + *

{@code
+ * JsonCallParameter param = new JsonCallParameter.JsonCallParameterBuilder()
+ *     .withFrom(Address.fromHexString("0x..."))
+ *     .withTo(Address.fromHexString("0x..."))
+ *     .withGas(21000L)
+ *     .withGasPrice(Wei.of(1000000000L))
+ *     .withValue(Wei.ZERO)
+ *     .withInput(Bytes.fromHexString("0x..."))
+ *     .withStrict(true) // Optional
+ *     .withAccessList(accessList) // Optional
+ *     .withMaxFeePerGas(Wei.of(2)) // Optional
+ *     .withMaxPriorityFeePerGas(Wei.of(1)) // Optional
+ *     .withMaxFeePerBlobGas(Wei.of(3)) // Optional
+ *     .withBlobVersionedHashes(blobVersionedHashes) // Optional
+ *     .build();
+ * }
+ * + *

Note: Only one of 'data' or 'input' should be provided to the builder. If both are provided + * and their values differ, an {@link IllegalArgumentException} is thrown. + * + *

Unknown JSON properties encountered during deserialization are logged but do not affect the + * deserialization process, allowing for flexibility in JSON formats. + */ @JsonIgnoreProperties(ignoreUnknown = true) +@JsonDeserialize(builder = JsonCallParameter.JsonCallParameterBuilder.class) public class JsonCallParameter extends CallParameter { private static final Logger LOG = LoggerFactory.getLogger(JsonCallParameter.class); private final Optional strict; - @JsonCreator - public JsonCallParameter( - @JsonProperty("from") final Address from, - @JsonProperty("to") final Address to, - @JsonDeserialize(using = GasDeserializer.class) @JsonProperty("gas") final Long gasLimit, - @JsonProperty("gasPrice") final Wei gasPrice, - @JsonProperty("maxPriorityFeePerGas") final Wei maxPriorityFeePerGas, - @JsonProperty("maxFeePerGas") final Wei maxFeePerGas, - @JsonProperty("value") final Wei value, - @JsonDeserialize(using = HexStringDeserializer.class) @JsonProperty("data") final Bytes data, - @JsonDeserialize(using = HexStringDeserializer.class) @JsonProperty("input") - final Bytes input, - @JsonProperty("strict") final Boolean strict, - @JsonProperty("accessList") final List accessList, - @JsonProperty("maxFeePerBlobGas") final Wei maxFeePerBlobGas, - @JsonProperty("blobVersionedHashes") final List blobVersionedHashes) { + private JsonCallParameter( + final Address from, + final Address to, + final Long gasLimit, + final Wei gasPrice, + final Optional maxPriorityFeePerGas, + final Optional maxFeePerGas, + final Wei value, + final Bytes payload, + final Optional strict, + final Optional> accessList, + final Optional maxFeePerBlobGas, + final Optional> blobVersionedHashes) { super( from, to, - gasLimit != null ? gasLimit : -1L, + gasLimit, gasPrice, - Optional.ofNullable(maxPriorityFeePerGas), - Optional.ofNullable(maxFeePerGas), + maxPriorityFeePerGas, + maxFeePerGas, value, - Optional.ofNullable(input != null ? input : data).orElse(null), - Optional.ofNullable(accessList), - Optional.ofNullable(maxFeePerBlobGas), - Optional.ofNullable(blobVersionedHashes)); + payload, + accessList, + maxFeePerBlobGas, + blobVersionedHashes); - if (input != null && data != null && !input.equals(data)) { - throw new IllegalArgumentException("Only one of 'input' or 'data' should be provided"); - } - - this.strict = Optional.ofNullable(strict); + this.strict = strict; } + /** + * Returns whether the call should be executed in strict mode. + * + * @return Optional strict mode flag + */ public Optional isMaybeStrict() { return strict; } - @JsonAnySetter - public void logUnknownProperties(final String key, final Object value) { - LOG.debug( - "unknown property - {} with value - {} and type - {} caught during serialization", - key, - value, - value.getClass()); + /** + * Builder for {@link JsonCallParameter}. Used by Jackson to deserialize {@code + * JsonCallParameter}. + */ + public static final class JsonCallParameterBuilder { + private Optional strict = Optional.empty(); + private Address from; + private Address to; + private long gas = -1; + private Optional maxPriorityFeePerGas = Optional.empty(); + private Optional maxFeePerGas = Optional.empty(); + private Optional maxFeePerBlobGas = Optional.empty(); + private Wei gasPrice; + private Wei value; + private Bytes data; + private Bytes input; + private Optional> accessList = Optional.empty(); + private Optional> blobVersionedHashes = Optional.empty(); + + /** Default constructor. */ + public JsonCallParameterBuilder() {} + + /** + * Sets the strict mode for the {@link JsonCallParameter}. If strict mode is enabled, the call + * will be executed with stricter validation rules. This is optional and defaults to not being + * in strict mode if not specified. + * + * @param strict the strict mode flag, can be {@code null} to indicate the absence of a strict + * mode preference + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withStrict(final Boolean strict) { + this.strict = Optional.ofNullable(strict); + return this; + } + + /** + * Sets the "from" address for the {@link JsonCallParameter}. This address represents the sender + * of the call. + * + * @param from the sender's address + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withFrom(final Address from) { + this.from = from; + return this; + } + + /** + * Sets the "to" address for the {@link JsonCallParameter}. This address represents the + * recipient of the call. It can be null for contract creation transactions. + * + * @param to the recipient's address + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withTo(final Address to) { + this.to = to; + return this; + } + + /** + * Sets the gas for the {@link JsonCallParameter} used for transaction execution. eth_call uses + * 0 gas but this parameter may be needed by some executions. By default, if not specified, the + * gas is set to -1, indicating that it is not set. + * + * @param gas the gas limit for the call, can be {@code null} to indicate that the gas limit is + * not set + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + @JsonDeserialize(using = GasDeserializer.class) + public JsonCallParameterBuilder withGas(final Long gas) { + this.gas = Optional.ofNullable(gas).orElse(-1L); + return this; + } + + /** + * Sets the maximum priority fee per gas for the {@link JsonCallParameter}. This fee is used to + * incentivize miners to include the transaction in a block. It is an optional parameter, and if + * not specified, it defaults to an empty {@link Optional}. + * + * @param maxPriorityFeePerGas the maximum priority fee per gas, can be {@code null} to indicate + * no preference + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withMaxPriorityFeePerGas(final Wei maxPriorityFeePerGas) { + this.maxPriorityFeePerGas = Optional.ofNullable(maxPriorityFeePerGas); + return this; + } + + /** + * Sets the maximum fee per gas for the {@link JsonCallParameter}. This fee represents the + * maximum amount of gas that the sender is willing to pay. It is an optional parameter, and if + * not specified, it defaults to an empty {@link Optional}. + * + * @param maxFeePerGas the maximum fee per gas, can be {@code null} to indicate no preference + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withMaxFeePerGas(final Wei maxFeePerGas) { + this.maxFeePerGas = Optional.ofNullable(maxFeePerGas); + return this; + } + + /** + * Sets the maximum fee per blob gas for the {@link JsonCallParameter}. This fee is specific to + * certain types of transactions and is an optional parameter. If not specified, it defaults to + * an empty {@link Optional}. + * + * @param maxFeePerBlobGas the maximum fee per blob gas, can be {@code null} to indicate no + * preference + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withMaxFeePerBlobGas(final Wei maxFeePerBlobGas) { + this.maxFeePerBlobGas = Optional.ofNullable(maxFeePerBlobGas); + return this; + } + + /** + * Sets the gas price for the {@link JsonCallParameter}. The gas price is used to calculate the + * transaction fee as the product of gas price and gas used. It is an optional parameter, and if + * not specified, it defaults to the network's current gas price. + * + * @param gasPrice the gas price, can be {@code null} to indicate that the network's current gas + * price should be used + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withGasPrice(final Wei gasPrice) { + this.gasPrice = gasPrice; + return this; + } + + /** + * Sets the value to be transferred with the call for the {@link JsonCallParameter}. This value + * is the amount of Wei to be transferred from the sender to the recipient. It is an optional + * parameter, and if not specified, it defaults to 0, indicating that no value is transferred. + * + * @param value the value to be transferred, can be {@code null} to indicate no value is + * transferred + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withValue(final Wei value) { + this.value = value; + return this; + } + + /** + * Sets the data for the {@link JsonCallParameter}. This data represents the payload of the + * call. Note: Only one of 'data' or 'input' should be provided. If both are provided and their + * values differ, an exception will be thrown during the build process. + * + * @param data the payload data + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + @JsonDeserialize(using = HexStringDeserializer.class) + public JsonCallParameterBuilder withData(final Bytes data) { + this.data = data; + return this; + } + + /** + * Sets the input for the {@link JsonCallParameter}. This input is an alternative representation + * of the payload for the call. Note: Only one of 'input' or 'data' should be provided. If both + * are provided and their values differ, an exception will be thrown during the build process. + * + * @param input the payload input + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + @JsonDeserialize(using = HexStringDeserializer.class) + public JsonCallParameterBuilder withInput(final Bytes input) { + this.input = input; + return this; + } + + /** + * Sets the access list for the {@link JsonCallParameter}. The access list is a list of + * addresses and storage keys that the transaction plans to access. This is an optional + * parameter, and if not specified, it defaults to an empty {@link Optional}. + * + * @param accessList the access list, can be {@code null} to indicate no access list is provided + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withAccessList(final List accessList) { + this.accessList = Optional.ofNullable(accessList); + return this; + } + + /** + * Sets the blob versioned hashes for the {@link JsonCallParameter}. This is a list of versioned + * hashes related to blob transactions, allowing for more complex transaction types. It is an + * optional parameter, and if not specified, it defaults to an empty {@link Optional}. + * + * @param blobVersionedHashes the list of versioned hashes, can be {@code null} to indicate no + * versioned hashes are provided + * @return the {@link JsonCallParameterBuilder} instance for chaining + */ + public JsonCallParameterBuilder withBlobVersionedHashes( + final List blobVersionedHashes) { + this.blobVersionedHashes = Optional.ofNullable(blobVersionedHashes); + return this; + } + + /** + * Handles unknown JSON properties during deserialization. This method is invoked when an + * unknown property is encountered in the JSON being deserialized into a {@link + * JsonCallParameter} object. It logs the unknown property's key, value, and the value's type if + * the value is not null. This allows for flexibility in JSON formats and aids in debugging + * issues related to unexpected properties. + * + * @param key the key of the unknown property + * @param value the value of the unknown property, which can be any type + */ + @JsonAnySetter + public void withUnknownProperties(final String key, final Object value) { + LOG.debug( + "unknown property - {} with value - {} and type - {} caught during serialization", + key, + value, + value != null ? value.getClass() : "NULL"); + } + + /** + * Builds a {@link JsonCallParameter} instance based on the provided parameters. This method + * also validates that only one of 'input' or 'data' is provided. If both are provided and their + * values differ, an {@link IllegalArgumentException} is thrown. This ensures the integrity of + * the payload data for the call. + * + * @return a new {@link JsonCallParameter} instance with the specified configuration + * @throws IllegalArgumentException if both 'input' and 'data' are provided and their values are + * not equal + */ + public JsonCallParameter build() { + if (input != null && data != null && !input.equals(data)) { + throw new IllegalArgumentException("Only one of 'input' or 'data' should be provided"); + } + + final Bytes payload = input != null ? input : data; + + return new JsonCallParameter( + from, + to, + gas, + gasPrice, + maxPriorityFeePerGas, + maxFeePerGas, + value, + payload, + strict, + accessList, + maxFeePerBlobGas, + blobVersionedHashes); + } } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java index 261f8de505d..7570fe342c2 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java @@ -115,8 +115,7 @@ public void shouldReturnInternalErrorWhenProcessorReturnsEmpty() { @Test public void shouldAcceptRequestWhenMissingOptionalFields() { final JsonCallParameter callParameter = - new JsonCallParameter( - null, null, null, null, null, null, null, null, null, Boolean.FALSE, null, null, null); + new JsonCallParameter.JsonCallParameterBuilder().withStrict(Boolean.FALSE).build(); final JsonRpcRequestContext request = ethCallRequest(callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, Bytes.of().toString()); @@ -444,20 +443,16 @@ private JsonCallParameter callParameter() { private JsonCallParameter callParameter( final Wei gasPrice, final Wei maxFeesPerGas, final Wei maxPriorityFeesPerGas) { - return new JsonCallParameter( - Address.fromHexString("0x0"), - Address.fromHexString("0x0"), - 0L, - gasPrice, - maxFeesPerGas, - maxPriorityFeesPerGas, - Wei.ZERO, - Bytes.EMPTY, - null, - null, - null, - null, - null); + return new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0")) + .withTo(Address.fromHexString("0x0")) + .withGas(0L) + .withGasPrice(gasPrice) + .withMaxFeePerGas(maxFeesPerGas) + .withMaxPriorityFeePerGas(maxPriorityFeesPerGas) + .withValue(Wei.ZERO) + .withInput(Bytes.EMPTY) + .build(); } private JsonRpcRequestContext ethCallRequest( diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java index d23c10f23b4..8812a1e0a6a 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java @@ -142,7 +142,7 @@ public void shouldReturnGasEstimateErrorWhenGasPricePresentForEip1559Transaction Assertions.assertThatThrownBy(() -> method.response(request)) .isInstanceOf(InvalidJsonRpcParameters.class) - .hasMessageContaining("gasPrice cannot be used with baseFee or maxFeePerGas"); + .hasMessageContaining("gasPrice cannot be used with maxFeePerGas or maxPriorityFeePerGas"); } @Test @@ -305,20 +305,15 @@ private void mockTransactionSimulatorResult( } private JsonCallParameter legacyTransactionCallParameter(final Wei gasPrice) { - return new JsonCallParameter( - Address.fromHexString("0x0"), - Address.fromHexString("0x0"), - 0L, - gasPrice, - null, - null, - Wei.ZERO, - Bytes.EMPTY, - null, - false, - null, - null, - null); + return new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0")) + .withTo(Address.fromHexString("0x0")) + .withGas(0L) + .withGasPrice(gasPrice) + .withValue(Wei.ZERO) + .withInput(Bytes.EMPTY) + .withStrict(Boolean.FALSE) + .build(); } private CallParameter eip1559TransactionCallParameter() { @@ -336,20 +331,17 @@ private CallParameter eip1559TransactionCallParameter( private JsonCallParameter eip1559TransactionCallParameter( final Optional gasPrice, final List accessListEntries) { - return new JsonCallParameter( - Address.fromHexString("0x0"), - Address.fromHexString("0x0"), - null, - gasPrice.orElse(null), - Wei.fromHexString("0x10"), - Wei.fromHexString("0x10"), - Wei.ZERO, - Bytes.EMPTY, - null, - false, - accessListEntries, - null, - null); + return new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0")) + .withTo(Address.fromHexString("0x0")) + .withGasPrice(gasPrice.orElse(null)) + .withMaxFeePerGas(Wei.fromHexString("0x10")) + .withMaxPriorityFeePerGas(Wei.fromHexString("0x10")) + .withValue(Wei.ZERO) + .withInput(Bytes.EMPTY) + .withStrict(Boolean.FALSE) + .withAccessList(accessListEntries) + .build(); } private List createAccessList() { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java index aa52a31c1f9..a6f5008b29e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java @@ -167,7 +167,7 @@ public void shouldReturnGasEstimateErrorWhenGasPricePresentForEip1559Transaction mockTransientProcessorResultGasEstimate(1L, false, false); Assertions.assertThatThrownBy(() -> method.response(request)) .isInstanceOf(InvalidJsonRpcParameters.class) - .hasMessageContaining("gasPrice cannot be used with baseFee or maxFeePerGas"); + .hasMessageContaining("gasPrice cannot be used with maxFeePerGas or maxPriorityFeePerGas"); } @Test @@ -465,20 +465,15 @@ private JsonCallParameter defaultLegacyTransactionCallParameter(final Wei gasPri private JsonCallParameter legacyTransactionCallParameter( final Wei gasPrice, final boolean isStrict) { - return new JsonCallParameter( - Address.fromHexString("0x0"), - Address.fromHexString("0x0"), - 0L, - gasPrice, - null, - null, - Wei.ZERO, - Bytes.EMPTY, - null, - isStrict, - null, - null, - null); + return new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0")) + .withTo(Address.fromHexString("0x0")) + .withGas(0L) + .withGasPrice(gasPrice) + .withValue(Wei.ZERO) + .withInput(Bytes.EMPTY) + .withStrict(isStrict) + .build(); } private CallParameter modifiedLegacyTransactionCallParameter(final Wei gasPrice) { @@ -499,20 +494,16 @@ private CallParameter eip1559TransactionCallParameter() { } private JsonCallParameter eip1559TransactionCallParameter(final Optional gasPrice) { - return new JsonCallParameter( - Address.fromHexString("0x0"), - Address.fromHexString("0x0"), - null, - gasPrice.orElse(null), - Wei.fromHexString("0x10"), - Wei.fromHexString("0x10"), - Wei.ZERO, - Bytes.EMPTY, - null, - false, - null, - null, - null); + return new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0")) + .withTo(Address.fromHexString("0x0")) + .withGasPrice(gasPrice.orElse(null)) + .withMaxPriorityFeePerGas(Wei.fromHexString("0x10")) + .withMaxFeePerGas(Wei.fromHexString("0x10")) + .withValue(Wei.ZERO) + .withInput(Bytes.EMPTY) + .withStrict(false) + .build(); } private CallParameter modifiedEip1559TransactionCallParameter() { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/JsonCallParameterTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/JsonCallParameterTest.java index b74c68f97df..97d7feeeb13 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/JsonCallParameterTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/JsonCallParameterTest.java @@ -15,9 +15,12 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.Test; public class JsonCallParameterTest { @@ -25,7 +28,7 @@ public class JsonCallParameterTest { private final ObjectMapper objectMapper = new ObjectMapper(); @Test - public void acceptsAndCapMaxValueForGasLimit() throws JsonProcessingException { + public void acceptsAndCapMaxValueForGas() throws JsonProcessingException { final String json = """ { @@ -37,4 +40,79 @@ public void acceptsAndCapMaxValueForGasLimit() throws JsonProcessingException { assertThat(callParameter.getGasLimit()).isEqualTo(Long.MAX_VALUE); } + + @Test + public void dataAsPayLoad() throws JsonProcessingException { + final String json = + """ + { + "data": "0x1234" + } + """; + + final JsonCallParameter callParameter = objectMapper.readValue(json, JsonCallParameter.class); + + assertThat(callParameter.getPayload()).isEqualTo(Bytes.fromHexString("0x1234")); + } + + @Test + public void inputAsPayLoad() throws JsonProcessingException { + final String json = + """ + { + "input": "0x1234" + } + """; + + final JsonCallParameter callParameter = objectMapper.readValue(json, JsonCallParameter.class); + + assertThat(callParameter.getPayload()).isEqualTo(Bytes.fromHexString("0x1234")); + } + + @Test + public void inputAndDataWithSameValueAsPayLoad() throws JsonProcessingException { + final String json = + """ + { + "input": "0x1234", + "data": "0x1234" + } + """; + + final JsonCallParameter callParameter = objectMapper.readValue(json, JsonCallParameter.class); + + assertThat(callParameter.getPayload()).isEqualTo(Bytes.fromHexString("0x1234")); + } + + @Test + public void inputAndDataWithDifferentValueAsPayLoadCauseException() { + final String json = + """ + { + "input": "0x1234", + "data": "0x1235" + } + """; + + assertThatExceptionOfType(JsonMappingException.class) + .isThrownBy(() -> objectMapper.readValue(json, JsonCallParameter.class)) + .withMessageContaining("problem: Only one of 'input' or 'data' should be provided"); + } + + @Test + public void extraParametersAreIgnored() throws JsonProcessingException { + // 0x96 = 150 + final String json = + """ + { + "gas": "0x96", + "gasLimit": "0xfa", + "extraField": "extra" + } + """; + + final JsonCallParameter callParameter = objectMapper.readValue(json, JsonCallParameter.class); + + assertThat(callParameter.getGasLimit()).isEqualTo(150); + } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCallTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCallTest.java index 8456fa2847b..0919ea48e92 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCallTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCallTest.java @@ -75,20 +75,13 @@ public void shouldReturnCorrectMethodName() { @Test public void shouldThrowInvalidJsonRpcParametersExceptionWhenMissingToField() { final JsonCallParameter callParameter = - new JsonCallParameter( - Address.fromHexString("0x0"), - null, - 0L, - Wei.ZERO, - null, - null, - Wei.ZERO, - Bytes.EMPTY, - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0")) + .withGas(0L) + .withGasPrice(Wei.ZERO) + .withValue(Wei.ZERO) + .withInput(Bytes.EMPTY) + .build(); final JsonRpcRequestContext request = ethCallRequest(privacyGroupId, callParameter, "latest"); final Throwable thrown = catchThrowable(() -> method.response(request)); @@ -113,20 +106,9 @@ public void shouldReturnNullWhenProcessorReturnsEmpty() { @Test public void shouldAcceptRequestWhenMissingOptionalFields() { final JsonCallParameter callParameter = - new JsonCallParameter( - null, - Address.fromHexString("0x0"), - null, - null, - null, - null, - null, - null, - null, - null, - null, - null, - null); + new JsonCallParameter.JsonCallParameterBuilder() + .withTo(Address.fromHexString("0x0")) + .build(); final JsonRpcRequestContext request = ethCallRequest(privacyGroupId, callParameter, "latest"); final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, Bytes.of().toString()); @@ -196,20 +178,14 @@ public void shouldThrowCorrectExceptionWhenNoPrivacyGroupSpecified() { } private JsonCallParameter callParameter() { - return new JsonCallParameter( - Address.fromHexString("0x0"), - Address.fromHexString("0x0"), - 0L, - Wei.ZERO, - null, - null, - Wei.ZERO, - Bytes.EMPTY, - null, - null, - null, - null, - null); + return new JsonCallParameter.JsonCallParameterBuilder() + .withFrom(Address.fromHexString("0x0")) + .withTo(Address.fromHexString("0x0")) + .withGas(0L) + .withGasPrice(Wei.ZERO) + .withValue(Wei.ZERO) + .withInput(Bytes.EMPTY) + .build(); } private JsonRpcRequestContext ethCallRequest(