@ -51,6 +51,8 @@ import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler ;
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler ;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator ;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator ;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult ;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult ;
import org.hyperledger.besu.ethereum.util.AccountOverride ;
import org.hyperledger.besu.ethereum.util.AccountOverrideMap ;
import java.util.Optional ;
import java.util.Optional ;
@ -92,6 +94,33 @@ public class EthCallTest {
assertThat ( method . getName ( ) ) . isEqualTo ( "eth_call" ) ;
assertThat ( method . getName ( ) ) . isEqualTo ( "eth_call" ) ;
}
}
@Test
public void noAccountOverrides ( ) {
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "latest" ) ;
Optional < AccountOverrideMap > overrideMap = method . getAddressAccountOverrideMap ( request ) ;
assertThat ( overrideMap . isPresent ( ) ) . isFalse ( ) ;
}
@Test
public void someAccountOverrides ( ) {
AccountOverrideMap expectedOverrides = new AccountOverrideMap ( ) ;
AccountOverride override = new AccountOverride . Builder ( ) . withNonce ( 88L ) . build ( ) ;
final Address address = Address . fromHexString ( "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3" ) ;
expectedOverrides . put ( address , override ) ;
final JsonRpcRequestContext request =
ethCallRequestWithStateOverrides ( callParameter ( ) , "latest" , expectedOverrides ) ;
Optional < AccountOverrideMap > maybeOverrideMap = method . getAddressAccountOverrideMap ( request ) ;
assertThat ( maybeOverrideMap . isPresent ( ) ) . isTrue ( ) ;
AccountOverrideMap overrideMap = maybeOverrideMap . get ( ) ;
assertThat ( overrideMap . keySet ( ) ) . hasSize ( 1 ) ;
assertThat ( overrideMap . values ( ) ) . hasSize ( 1 ) ;
assertThat ( overrideMap ) . containsKey ( address ) ;
assertThat ( overrideMap ) . containsValue ( override ) ;
}
@Test
@Test
public void shouldReturnInternalErrorWhenProcessorReturnsEmpty ( ) {
public void shouldReturnInternalErrorWhenProcessorReturnsEmpty ( ) {
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "latest" ) ;
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "latest" ) ;
@ -99,7 +128,7 @@ public class EthCallTest {
when ( blockchainQueries . getBlockchain ( ) ) . thenReturn ( blockchain ) ;
when ( blockchainQueries . getBlockchain ( ) ) . thenReturn ( blockchain ) ;
when ( blockchain . getChainHead ( ) ) . thenReturn ( chainHead ) ;
when ( blockchain . getChainHead ( ) ) . thenReturn ( chainHead ) ;
when ( transactionSimulator . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
when ( transactionSimulator . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
. thenReturn ( Optional . empty ( ) ) ;
. thenReturn ( Optional . empty ( ) ) ;
final BlockHeader blockHeader = mock ( BlockHeader . class ) ;
final BlockHeader blockHeader = mock ( BlockHeader . class ) ;
@ -109,7 +138,7 @@ public class EthCallTest {
final JsonRpcResponse response = method . response ( request ) ;
final JsonRpcResponse response = method . response ( request ) ;
assertThat ( response ) . usingRecursiveComparison ( ) . isEqualTo ( expectedResponse ) ;
assertThat ( response ) . usingRecursiveComparison ( ) . isEqualTo ( expectedResponse ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
}
}
@Test
@Test
@ -130,12 +159,13 @@ public class EthCallTest {
when ( result . isSuccessful ( ) ) . thenReturn ( true ) ;
when ( result . isSuccessful ( ) ) . thenReturn ( true ) ;
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . getOutput ( ) ) . thenReturn ( Bytes . of ( ) ) ;
when ( result . getOutput ( ) ) . thenReturn ( Bytes . of ( ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
verify ( transactionSimulator )
. process (
eq ( callParameter ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
assertThat ( response ) . usingRecursiveComparison ( ) . isEqualTo ( expectedResponse ) ;
assertThat ( response ) . usingRecursiveComparison ( ) . isEqualTo ( expectedResponse ) ;
verify ( transactionSimulator ) . process ( eq ( callParameter ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
}
}
@Test
@Test
@ -158,7 +188,8 @@ public class EthCallTest {
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . getOutput ( ) ) . thenReturn ( Bytes . of ( 1 ) ) ;
when ( result . getOutput ( ) ) . thenReturn ( Bytes . of ( 1 ) ) ;
verify ( transactionSimulator )
verify ( transactionSimulator )
. process ( eq ( callParameter ( ) ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
. process (
eq ( callParameter ( ) ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
@ -196,7 +227,8 @@ public class EthCallTest {
when ( result . isSuccessful ( ) ) . thenReturn ( false ) ;
when ( result . isSuccessful ( ) ) . thenReturn ( false ) ;
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . result ( ) ) . thenReturn ( processingResult ) ;
when ( result . result ( ) ) . thenReturn ( processingResult ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
verify ( transactionSimulator )
. process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
@ -235,7 +267,8 @@ public class EthCallTest {
when ( result . isSuccessful ( ) ) . thenReturn ( false ) ;
when ( result . isSuccessful ( ) ) . thenReturn ( false ) ;
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . result ( ) ) . thenReturn ( processingResult ) ;
when ( result . result ( ) ) . thenReturn ( processingResult ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
verify ( transactionSimulator )
. process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
@ -277,7 +310,8 @@ public class EthCallTest {
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . getValidationResult ( ) ) . thenReturn ( ValidationResult . valid ( ) ) ;
when ( result . result ( ) ) . thenReturn ( processingResult ) ;
when ( result . result ( ) ) . thenReturn ( processingResult ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
verify ( transactionSimulator )
. process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , mapperCaptor . capture ( ) , any ( ) ) ;
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
assertThat ( mapperCaptor . getValue ( ) . apply ( mock ( MutableWorldState . class ) , Optional . of ( result ) ) )
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
. isEqualTo ( Optional . of ( expectedResponse ) ) ;
@ -291,7 +325,7 @@ public class EthCallTest {
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "latest" ) ;
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "latest" ) ;
when ( blockchainQueries . getBlockchain ( ) ) . thenReturn ( blockchain ) ;
when ( blockchainQueries . getBlockchain ( ) ) . thenReturn ( blockchain ) ;
when ( blockchain . getChainHead ( ) ) . thenReturn ( chainHead ) ;
when ( blockchain . getChainHead ( ) ) . thenReturn ( chainHead ) ;
when ( transactionSimulator . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
when ( transactionSimulator . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
. thenReturn ( Optional . empty ( ) ) ;
. thenReturn ( Optional . empty ( ) ) ;
final BlockHeader blockHeader = mock ( BlockHeader . class ) ;
final BlockHeader blockHeader = mock ( BlockHeader . class ) ;
@ -301,7 +335,7 @@ public class EthCallTest {
method . response ( request ) ;
method . response ( request ) ;
verify ( blockchainQueries , atLeastOnce ( ) ) . getBlockchain ( ) ;
verify ( blockchainQueries , atLeastOnce ( ) ) . getBlockchain ( ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
}
}
@Test
@Test
@ -315,7 +349,7 @@ public class EthCallTest {
method . response ( request ) ;
method . response ( request ) ;
verify ( blockchainQueries ) . getBlockHeaderByHash ( eq ( Hash . ZERO ) ) ;
verify ( blockchainQueries ) . getBlockHeaderByHash ( eq ( Hash . ZERO ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
}
}
@Test
@Test
@ -323,13 +357,13 @@ public class EthCallTest {
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "safe" ) ;
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "safe" ) ;
when ( blockchainQueries . getBlockHeaderByHash ( Hash . ZERO ) ) . thenReturn ( Optional . of ( blockHeader ) ) ;
when ( blockchainQueries . getBlockHeaderByHash ( Hash . ZERO ) ) . thenReturn ( Optional . of ( blockHeader ) ) ;
when ( blockchainQueries . safeBlockHeader ( ) ) . thenReturn ( Optional . of ( blockHeader ) ) ;
when ( blockchainQueries . safeBlockHeader ( ) ) . thenReturn ( Optional . of ( blockHeader ) ) ;
when ( transactionSimulator . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
when ( transactionSimulator . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
. thenReturn ( Optional . empty ( ) ) ;
. thenReturn ( Optional . empty ( ) ) ;
method . response ( request ) ;
method . response ( request ) ;
verify ( blockchainQueries ) . getBlockHeaderByHash ( Hash . ZERO ) ;
verify ( blockchainQueries ) . getBlockHeaderByHash ( Hash . ZERO ) ;
verify ( blockchainQueries ) . safeBlockHeader ( ) ;
verify ( blockchainQueries ) . safeBlockHeader ( ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
}
}
@Test
@Test
@ -337,13 +371,13 @@ public class EthCallTest {
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "finalized" ) ;
final JsonRpcRequestContext request = ethCallRequest ( callParameter ( ) , "finalized" ) ;
when ( blockchainQueries . getBlockHeaderByHash ( Hash . ZERO ) ) . thenReturn ( Optional . of ( blockHeader ) ) ;
when ( blockchainQueries . getBlockHeaderByHash ( Hash . ZERO ) ) . thenReturn ( Optional . of ( blockHeader ) ) ;
when ( blockchainQueries . finalizedBlockHeader ( ) ) . thenReturn ( Optional . of ( blockHeader ) ) ;
when ( blockchainQueries . finalizedBlockHeader ( ) ) . thenReturn ( Optional . of ( blockHeader ) ) ;
when ( transactionSimulator . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
when ( transactionSimulator . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
. thenReturn ( Optional . empty ( ) ) ;
. thenReturn ( Optional . empty ( ) ) ;
method . response ( request ) ;
method . response ( request ) ;
verify ( blockchainQueries ) . getBlockHeaderByHash ( Hash . ZERO ) ;
verify ( blockchainQueries ) . getBlockHeaderByHash ( Hash . ZERO ) ;
verify ( blockchainQueries ) . finalizedBlockHeader ( ) ;
verify ( blockchainQueries ) . finalizedBlockHeader ( ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
}
}
@Test
@Test
@ -353,13 +387,13 @@ public class EthCallTest {
when ( blockchainQueries . getBlockHashByNumber ( anyLong ( ) ) ) . thenReturn ( Optional . of ( Hash . ZERO ) ) ;
when ( blockchainQueries . getBlockHashByNumber ( anyLong ( ) ) ) . thenReturn ( Optional . of ( Hash . ZERO ) ) ;
when ( blockchainQueries . getBlockHeaderByHash ( Hash . ZERO ) )
when ( blockchainQueries . getBlockHeaderByHash ( Hash . ZERO ) )
. thenReturn ( Optional . of ( mock ( BlockHeader . class ) ) ) ;
. thenReturn ( Optional . of ( mock ( BlockHeader . class ) ) ) ;
when ( transactionSimulator . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
when ( transactionSimulator . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
. thenReturn ( Optional . empty ( ) ) ;
. thenReturn ( Optional . empty ( ) ) ;
method . response ( request ) ;
method . response ( request ) ;
verify ( blockchainQueries ) . getBlockHeaderByHash ( eq ( Hash . ZERO ) ) ;
verify ( blockchainQueries ) . getBlockHeaderByHash ( eq ( Hash . ZERO ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
verify ( transactionSimulator ) . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) ;
}
}
@Test
@Test
@ -431,7 +465,7 @@ public class EthCallTest {
. build ( ) ;
. build ( ) ;
verify ( transactionSimulator )
verify ( transactionSimulator )
. process ( any ( ) , eq ( transactionValidationParams ) , any ( ) , any ( ) , any ( ) ) ;
. process ( any ( ) , eq ( Optional . empty ( ) ) , eq ( transactionValidationParams ) , any ( ) , any ( ) , any ( ) ) ;
}
}
private JsonCallParameter callParameter ( ) {
private JsonCallParameter callParameter ( ) {
@ -458,8 +492,17 @@ public class EthCallTest {
new JsonRpcRequest ( "2.0" , "eth_call" , new Object [ ] { callParameter , blockNumberInHex } ) ) ;
new JsonRpcRequest ( "2.0" , "eth_call" , new Object [ ] { callParameter , blockNumberInHex } ) ) ;
}
}
private JsonRpcRequestContext ethCallRequestWithStateOverrides (
final CallParameter callParameter ,
final String blockNumberInHex ,
final AccountOverrideMap overrides ) {
return new JsonRpcRequestContext (
new JsonRpcRequest (
"2.0" , "eth_call" , new Object [ ] { callParameter , blockNumberInHex , overrides } ) ) ;
}
private void mockTransactionProcessorSuccessResult ( final JsonRpcResponse jsonRpcResponse ) {
private void mockTransactionProcessorSuccessResult ( final JsonRpcResponse jsonRpcResponse ) {
when ( transactionSimulator . process ( any ( ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
when ( transactionSimulator . process ( any ( ) , eq ( Optional . empty ( ) ) , any ( ) , any ( ) , any ( ) , any ( ) ) )
. thenReturn ( Optional . of ( jsonRpcResponse ) ) ;
. thenReturn ( Optional . of ( jsonRpcResponse ) ) ;
}
}
}
}