diff --git a/eosiojava/build.gradle b/eosiojava/build.gradle index 4092474..6aa59b2 100644 --- a/eosiojava/build.gradle +++ b/eosiojava/build.gradle @@ -31,6 +31,7 @@ dependencies { api 'com.google.code.gson:gson:2.8.5' api 'org.bouncycastle:bcprov-jdk15on:1.61' api 'org.bouncycastle:bcpkix-jdk15on:1.61' + api 'com.vdurmont:semver4j:3.1.0' // This works on android and non-android, but is necessary to keep us to 1.7 targets. api 'com.google.guava:guava:27.1-android' testCompile 'junit:junit:4.12' @@ -47,7 +48,7 @@ test { def libraryGroupId = 'one.block' def libraryArtifactId = 'eosiojava' -def libraryVersion = '1.0.0' +def libraryVersion = '1.0.1' task sourcesJar(type: Jar, dependsOn: classes){ classifier = 'sources' diff --git a/eosiojava/src/main/java/one/block/eosiojava/error/ErrorConstants.java b/eosiojava/src/main/java/one/block/eosiojava/error/ErrorConstants.java index 6faa3df..d1222b3 100644 --- a/eosiojava/src/main/java/one/block/eosiojava/error/ErrorConstants.java +++ b/eosiojava/src/main/java/one/block/eosiojava/error/ErrorConstants.java @@ -166,6 +166,11 @@ private ErrorConstants(){ */ public static final String TRANSACTION_PROCESSOR_PREPARE_RPC_GET_BLOCK_INFO = "Error happened on calling GetBlockInfo RPC."; + /** + * Error message get thrown if {@link IRPCProvider#getBlock(GetBlockRequest)} thrown exception during process of {@link TransactionProcessor#prepare(List)} + */ + public static final String TRANSACTION_PROCESSOR_PREPARE_RPC_GET_BLOCK = "Error happened on calling GetBlock RPC."; + /** * Error message get thrown if chain id from {@link GetInfoResponse#getChainId()} does not match with the input chain id */ diff --git a/eosiojava/src/main/java/one/block/eosiojava/interfaces/IRPCProvider.java b/eosiojava/src/main/java/one/block/eosiojava/interfaces/IRPCProvider.java index 394f195..c78e6c8 100644 --- a/eosiojava/src/main/java/one/block/eosiojava/interfaces/IRPCProvider.java +++ b/eosiojava/src/main/java/one/block/eosiojava/interfaces/IRPCProvider.java @@ -1,16 +1,19 @@ package one.block.eosiojava.interfaces; import one.block.eosiojava.error.rpcProvider.GetBlockInfoRpcError; +import one.block.eosiojava.error.rpcProvider.GetBlockRpcError; import one.block.eosiojava.error.rpcProvider.GetInfoRpcError; import one.block.eosiojava.error.rpcProvider.GetRawAbiRpcError; import one.block.eosiojava.error.rpcProvider.GetRequiredKeysRpcError; import one.block.eosiojava.error.rpcProvider.SendTransactionRpcError; import one.block.eosiojava.models.rpcProvider.request.GetBlockInfoRequest; +import one.block.eosiojava.models.rpcProvider.request.GetBlockRequest; import one.block.eosiojava.models.rpcProvider.request.GetRawAbiRequest; import one.block.eosiojava.models.rpcProvider.request.GetRequiredKeysRequest; import one.block.eosiojava.models.rpcProvider.request.SendTransactionRequest; import one.block.eosiojava.models.rpcProvider.response.GetBlockInfoResponse; +import one.block.eosiojava.models.rpcProvider.response.GetBlockResponse; import one.block.eosiojava.models.rpcProvider.response.GetInfoResponse; import one.block.eosiojava.models.rpcProvider.response.GetRawAbiResponse; import one.block.eosiojava.models.rpcProvider.response.GetRequiredKeysResponse; @@ -43,6 +46,17 @@ public interface IRPCProvider { @NotNull GetBlockInfoResponse getBlockInfo(GetBlockInfoRequest getBlockInfoRequest) throws GetBlockInfoRpcError; + /** + * Returns an object containing various details about a specific block on the blockchain. + * + * @param getBlockRequest Info of a specific block. + * @return the info/status of a specific block in the request + * @throws GetBlockRpcError thrown if there are any exceptions/backend error during the + * getBlockInfo() process. + */ + @NotNull + GetBlockResponse getBlock(GetBlockRequest getBlockRequest) throws GetBlockRpcError; + /** * Gets raw abi for a given contract. * diff --git a/eosiojava/src/main/java/one/block/eosiojava/models/rpcProvider/TransactionConfig.java b/eosiojava/src/main/java/one/block/eosiojava/models/rpcProvider/TransactionConfig.java index 1a3e35e..af30322 100644 --- a/eosiojava/src/main/java/one/block/eosiojava/models/rpcProvider/TransactionConfig.java +++ b/eosiojava/src/main/java/one/block/eosiojava/models/rpcProvider/TransactionConfig.java @@ -29,6 +29,18 @@ public class TransactionConfig { */ private static final boolean DEFAULT_USE_LAST_IRREVERSIBLE = true; + /** + * Default chain version string to use if none is specified and we cannot get the server version from + * the chain itself. + */ + private static final String DEFAULT_CHAIN_VERSION_STRING = "2.0.0"; + + /** + * Chain version at which {@link one.block.eosiojava.interfaces.IRPCProvider#getBlockInfo(GetBlockInfoRequest)} + * became available. + */ + private static final String GET_BLOCK_INFO_AVAILABLE_STRING = "2.1.0"; + /** * The Expires seconds. *
@@ -55,6 +67,15 @@ public class TransactionConfig { */ private boolean useLastIrreversible = DEFAULT_USE_LAST_IRREVERSIBLE; + /** + * Version of nodeos that the transaction is targeting. This will allow the library to work with 2.1+ version + * chains using {@link one.block.eosiojava.interfaces.IRPCProvider#getBlockInfo(GetBlockInfoRequest)} for + * calculating TAPOS rather than {@link one.block.eosiojava.interfaces.IRPCProvider#getBlock(GetBlockInfoRequest)}. + * If the value is left unset, the transaction will determine the chain version from the {@link IRPCProvider#getInfo()} call + * and use that as the chain version string. + */ + private String chainVersionString = null; + /** * Gets the expiration time for the transaction. *
@@ -117,4 +138,41 @@ public void setBlocksBehind(int blocksBehind) { public void setUseLastIrreversible(boolean useLastIrreversible) { this.useLastIrreversible = useLastIrreversible; } + + /** + * Gets the current chain version that the transaction is targeting. + *
+ * 2.1+ version chains will use {@link one.block.eosiojava.interfaces.IRPCProvider#getBlockInfo(GetBlockInfoRequest)} for + * calculating TAPOS rather than {@link one.block.eosiojava.interfaces.IRPCProvider#getBlock(GetBlockRequest)}. If + * the value is left unset, the transaction will determine the chain version from the {@link IRPCProvider#getInfo()} call + * and use that as the chain version string. + * @return chainVersionString current nodeos version that we are targeting for this transaction + */ + public String getChainVersionString() { return chainVersionString; } + + /** + * Sets the current chain version that the transaction is targeting. + *
+ * 2.1+ version chains will use {@link one.block.eosiojava.interfaces.IRPCProvider#getBlockInfo(GetBlockInfoRequest)} for + * calculating TAPOS rather than {@link one.block.eosiojava.interfaces.IRPCProvider#getBlock(GetBlockRequest)}. If + * the value is left unset, the transaction will determine the chain version from the {@link IRPCProvider#getInfo()} call + * and use that as the chain version string. + * @param chainVersionString set the target nodeos version that this transaction is for + */ + public void setChainVersionString(String chainVersionString) { this.chainVersionString = chainVersionString; } + + /** + * Get the default chain version string to use for transactions if one is not specified and the version cannot + * be read from the chain itself. + * @return defaultChainVersionString the version of nodeos if one is not set and the version cannot be read from the chain itself. + */ + public String getDefaultChainVersionString() { return DEFAULT_CHAIN_VERSION_STRING; } + + /** + * Chain version at which {@link one.block.eosiojava.interfaces.IRPCProvider#getBlockInfo(GetBlockInfoRequest)} + * became available. + * @return getBlockInfoAvailableString the version of nodeos where {@link one.block.eosiojava.interfaces.IRPCProvider#getBlockInfo(GetBlockInfoRequest)} + * became available. + */ + public String getGetBlockInfoAvailableString() { return GET_BLOCK_INFO_AVAILABLE_STRING; } } diff --git a/eosiojava/src/main/java/one/block/eosiojava/models/rpcProvider/request/GetBlockRequest.java b/eosiojava/src/main/java/one/block/eosiojava/models/rpcProvider/request/GetBlockRequest.java index 892e87e..ccfbca4 100644 --- a/eosiojava/src/main/java/one/block/eosiojava/models/rpcProvider/request/GetBlockRequest.java +++ b/eosiojava/src/main/java/one/block/eosiojava/models/rpcProvider/request/GetBlockRequest.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; /** - * The request class for getBlock() RPC call {@link one.block.eosiojava.interfaces.IRPCProvider#getBlockInfo(GetBlockInfoRequest)} + * The request class for getBlock() RPC call {@link one.block.eosiojava.interfaces.IRPCProvider#getBlock(GetBlockRequest)} */ public class GetBlockRequest { diff --git a/eosiojava/src/main/java/one/block/eosiojava/session/TransactionProcessor.java b/eosiojava/src/main/java/one/block/eosiojava/session/TransactionProcessor.java index 745e8d1..cd94a44 100644 --- a/eosiojava/src/main/java/one/block/eosiojava/session/TransactionProcessor.java +++ b/eosiojava/src/main/java/one/block/eosiojava/session/TransactionProcessor.java @@ -7,9 +7,13 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.List; + +import com.vdurmont.semver4j.Semver; +import com.vdurmont.semver4j.SemverException; import one.block.eosiojava.error.ErrorConstants; import one.block.eosiojava.error.abiProvider.GetAbiError; import one.block.eosiojava.error.rpcProvider.GetBlockInfoRpcError; +import one.block.eosiojava.error.rpcProvider.GetBlockRpcError; import one.block.eosiojava.error.rpcProvider.GetInfoRpcError; import one.block.eosiojava.error.rpcProvider.GetRequiredKeysRpcError; import one.block.eosiojava.error.rpcProvider.SendTransactionRpcError; @@ -51,9 +55,15 @@ import one.block.eosiojava.models.rpcProvider.ContextFreeData; import one.block.eosiojava.models.rpcProvider.TransactionConfig; import one.block.eosiojava.models.rpcProvider.request.GetBlockInfoRequest; +import one.block.eosiojava.models.rpcProvider.request.GetBlockRequest; import one.block.eosiojava.models.rpcProvider.request.GetRequiredKeysRequest; import one.block.eosiojava.models.rpcProvider.request.SendTransactionRequest; -import one.block.eosiojava.models.rpcProvider.response.*; + +import one.block.eosiojava.models.rpcProvider.response.GetBlockInfoResponse; +import one.block.eosiojava.models.rpcProvider.response.GetBlockResponse; +import one.block.eosiojava.models.rpcProvider.response.GetInfoResponse; +import one.block.eosiojava.models.rpcProvider.response.GetRequiredKeysResponse; +import one.block.eosiojava.models.rpcProvider.response.SendTransactionResponse; import one.block.eosiojava.models.signatureProvider.EosioTransactionSignatureRequest; import one.block.eosiojava.models.signatureProvider.EosioTransactionSignatureResponse; import one.block.eosiojava.utilities.DateFormatter; @@ -203,6 +213,13 @@ public class TransactionProcessor { */ private static final String PACKED_TRANSACTION_V0_PREFIX = "00"; + /** + * Index for the first character of a string, which in a version returned from + * the blockchain may contain a 'v'. If it does we will remove it before comparing + * versions against the transaction targeted version. + */ + private static final int CHAR_INDEX_V_PREFIX = 0; + /** * Constructor with all provider references from {@link TransactionSession} * @param serializationProvider the serialization provider. @@ -374,6 +391,15 @@ public void prepare(@NotNull List actions, @NotNull List context getInfoResponse.getChainId())); } + String chainVersionString = this.transactionConfig.getChainVersionString(); + if (Strings.isNullOrEmpty(chainVersionString)) { + if (Strings.isNullOrEmpty(getInfoResponse.getServerVersion())) { + chainVersionString = this.transactionConfig.getDefaultChainVersionString(); + } else { + chainVersionString = getInfoResponse.getServerVersionString(); + } + } + // Assigning value to refBlockNum and refBlockPrefix BigInteger taposBlockNum; @@ -393,20 +419,55 @@ public void prepare(@NotNull List actions, @NotNull List context } } - GetBlockInfoResponse getBlockInfoResponse; + + boolean useGetBlockInfo = false; + // Remove any leading non-digit character. + if (!Character.isDigit(chainVersionString.charAt(CHAR_INDEX_V_PREFIX))) { + chainVersionString = chainVersionString.substring(1); + } try { - getBlockInfoResponse = this.rpcProvider - .getBlockInfo(new GetBlockInfoRequest(taposBlockNum)); - } catch (GetBlockInfoRpcError getBlockInfoRpcError) { - throw new TransactionPrepareRpcError( - ErrorConstants.TRANSACTION_PROCESSOR_PREPARE_RPC_GET_BLOCK_INFO, getBlockInfoRpcError); + // Strip any kind of beta or rc suffix. + Semver chainVersion = new Semver(chainVersionString).withClearedSuffix(); + Semver getBlockInfoAvailableVersion = new Semver(this.transactionConfig.getGetBlockInfoAvailableString()); + useGetBlockInfo = chainVersion.isGreaterThanOrEqualTo(getBlockInfoAvailableVersion); + } catch (SemverException semverException) { + // Default back to getBlock as the safer alternative for now. + useGetBlockInfo = false; + } + + String strHeadBlockTime; + BigInteger blockNum; + BigInteger refBlockPrefix; + + if (useGetBlockInfo) { + GetBlockInfoResponse getBlockInfoResponse; + try { + getBlockInfoResponse = this.rpcProvider + .getBlockInfo(new GetBlockInfoRequest(taposBlockNum)); + strHeadBlockTime = getBlockInfoResponse.getTimestamp(); + blockNum = getBlockInfoResponse.getBlockNum(); + refBlockPrefix = getBlockInfoResponse.getRefBlockPrefix(); + } catch (GetBlockInfoRpcError getBlockInfoRpcError) { + throw new TransactionPrepareRpcError( + ErrorConstants.TRANSACTION_PROCESSOR_PREPARE_RPC_GET_BLOCK_INFO, getBlockInfoRpcError); + } + } else { + GetBlockResponse getBlockResponse; + try { + getBlockResponse = this.rpcProvider + .getBlock(new GetBlockRequest(taposBlockNum.toString())); + strHeadBlockTime = getBlockResponse.getTimestamp(); + blockNum = getBlockResponse.getBlockNum(); + refBlockPrefix = getBlockResponse.getRefBlockPrefix(); + } catch (GetBlockRpcError getBlockRpcError) { + throw new TransactionPrepareRpcError( + ErrorConstants.TRANSACTION_PROCESSOR_PREPARE_RPC_GET_BLOCK, getBlockRpcError); + } } // Calculate the expiration based on the taposBlockNum expiration if (preparingTransaction.getExpiration().isEmpty()) { - String strHeadBlockTime = getBlockInfoResponse.getTimestamp(); - long taposBlockTime; try { @@ -424,8 +485,7 @@ public void prepare(@NotNull List actions, @NotNull List context } // Restrict the refBlockNum to 32 bit unsigned value - BigInteger refBlockNum = getBlockInfoResponse.getBlockNum().and(BigInteger.valueOf(0xffff)); - BigInteger refBlockPrefix = getBlockInfoResponse.getRefBlockPrefix(); + BigInteger refBlockNum = blockNum.and(BigInteger.valueOf(0xffff)); preparingTransaction.setRefBlockNum(refBlockNum); preparingTransaction.setRefBlockPrefix(refBlockPrefix); diff --git a/eosiojava/src/test/java/one/block/eosiojava/session/NegativeTransactionProcessorTest.java b/eosiojava/src/test/java/one/block/eosiojava/session/NegativeTransactionProcessorTest.java index 2a88fe8..c4414c1 100644 --- a/eosiojava/src/test/java/one/block/eosiojava/session/NegativeTransactionProcessorTest.java +++ b/eosiojava/src/test/java/one/block/eosiojava/session/NegativeTransactionProcessorTest.java @@ -137,7 +137,7 @@ public void prepare_thenFailWithWrongDateFormat() throws TransactionPrepareError String weirdHeadBlockTime = "2019-04-01TGM22:08:40.000"; String mockedGetInfoResponseWithWeirdDateFormat = "{\n" - + " \"server_version\": \"1\",\n" + + " \"server_version\": \"2\",\n" + " \"chain_id\": \"sample chain id\",\n" + " \"head_block_num\": " + headBlockNum + ",\n" + " \"last_irreversible_block_num\": 1,\n" @@ -149,7 +149,7 @@ public void prepare_thenFailWithWrongDateFormat() throws TransactionPrepareError + " \"virtual_block_net_limit\": 1,\n" + " \"block_cpu_limit\": 1,\n" + " \"block_net_limit\": 1,\n" - + " \"server_version_string\": \"v1.3.0\"\n" + + " \"server_version_string\": \"v2.1.0\"\n" + "}"; String mockedGetBlockInfoResponseWithWeirdDateFormat = "{\n" @@ -595,7 +595,7 @@ private List defaultActions() { .and(BigInteger.valueOf(0xffff)); private static final String mockedGetInfoResponse = "{\n" - + " \"server_version\": \"1\",\n" + + " \"server_version\": \"2\",\n" + " \"chain_id\": \"sample chain id\",\n" + " \"head_block_num\": " + headBlockNum + ",\n" + " \"last_irreversible_block_num\": 1,\n" @@ -607,7 +607,7 @@ private List defaultActions() { + " \"virtual_block_net_limit\": 1,\n" + " \"block_cpu_limit\": 1,\n" + " \"block_net_limit\": 1,\n" - + " \"server_version_string\": \"v1.3.0\"\n" + + " \"server_version_string\": \"v2.1.0\"\n" + "}"; private static final String mockedGetBlockInfoResponse = "{\n" diff --git a/eosiojava/src/test/java/one/block/eosiojava/session/TransactionProcessorTest.java b/eosiojava/src/test/java/one/block/eosiojava/session/TransactionProcessorTest.java index 6fab0a8..123782e 100644 --- a/eosiojava/src/test/java/one/block/eosiojava/session/TransactionProcessorTest.java +++ b/eosiojava/src/test/java/one/block/eosiojava/session/TransactionProcessorTest.java @@ -7,14 +7,18 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import one.block.eosiojava.error.abiProvider.GetAbiError; import one.block.eosiojava.error.rpcProvider.GetBlockInfoRpcError; +import one.block.eosiojava.error.rpcProvider.GetBlockRpcError; import one.block.eosiojava.error.rpcProvider.GetInfoRpcError; import one.block.eosiojava.error.rpcProvider.GetRequiredKeysRpcError; import one.block.eosiojava.error.rpcProvider.SendTransactionRpcError; @@ -42,6 +46,7 @@ import one.block.eosiojava.models.rpcProvider.Transaction; import one.block.eosiojava.models.rpcProvider.TransactionConfig; import one.block.eosiojava.models.rpcProvider.request.GetBlockInfoRequest; +import one.block.eosiojava.models.rpcProvider.request.GetBlockRequest; import one.block.eosiojava.models.rpcProvider.request.GetRequiredKeysRequest; import one.block.eosiojava.models.rpcProvider.request.SendTransactionRequest; import one.block.eosiojava.models.rpcProvider.response.*; @@ -53,11 +58,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class TransactionProcessorTest { private IRPCProvider mockedRpcProvider = mock(IRPCProvider.class); @@ -66,6 +71,16 @@ public class TransactionProcessorTest { private ISerializationProvider mockedSerializationProvider = mock(ISerializationProvider.class); private TransactionSession session; + @Parameterized.Parameter(0) + public boolean runWithGetBlockInfo; + + // creates the test data + @Parameterized.Parameters(name = "{index}: Test with runWithGetBlockInfo={0} ") + public static Collection data() { + Object[][] data = new Object[][]{{true}, {false}}; + return Arrays.asList(data); + } + @Before public void setUp() { this.session = new TransactionSession(this.mockedSerializationProvider, this.mockedRpcProvider, this.mockedABIProvider, @@ -81,7 +96,7 @@ public void prepare() { this.mockRPC( Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetInfoResponse, GetInfoResponse.class), Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetBlockInfoResponse, GetBlockInfoResponse.class), - null, null); + null, null, null); // Apply List actions = this.defaultActions(); @@ -389,7 +404,8 @@ public void isAllowTransactionToBeModified() { Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetInfoResponse, GetInfoResponse.class), Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetBlockInfoResponse, GetBlockInfoResponse.class), Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetRequiredKeysResponse, GetRequiredKeysResponse.class), - Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(MOCKED_SENDTRANSACTION_RESPONE_JSON, SendTransactionResponse.class)); + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(MOCKED_SENDTRANSACTION_RESPONE_JSON, SendTransactionResponse.class), + null); this.mockAbiProvider(EOSIOTOKENABIJSON); this.mockSerializationProvider(MOCKED_ACTION_HEX, MOCKED_TRANSACTION_HEX, mockedDeserilizedTransaction); @@ -582,11 +598,21 @@ public void testContextFreeActionPrepareWithData() { } private void mockDefaultSuccessData() { - this.mockRPC( - Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetInfoResponse, GetInfoResponse.class), - Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetBlockInfoResponse, GetBlockInfoResponse.class), - Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetRequiredKeysResponse, GetRequiredKeysResponse.class), - Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(MOCKED_SENDTRANSACTION_RESPONE_JSON, SendTransactionResponse.class)); + if (runWithGetBlockInfo) { + this.mockRPC( + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetInfoResponse, GetInfoResponse.class), + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetBlockInfoResponse, GetBlockInfoResponse.class), + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetRequiredKeysResponse, GetRequiredKeysResponse.class), + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(MOCKED_SENDTRANSACTION_RESPONE_JSON, SendTransactionResponse.class), + null); + } else { + this.mockRPC( + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedOlderGetInfoResponse, GetInfoResponse.class), + null, + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetRequiredKeysResponse, GetRequiredKeysResponse.class), + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(MOCKED_SENDTRANSACTION_RESPONE_JSON, SendTransactionResponse.class), + Utils.getGson(DateFormatter.BACKEND_DATE_PATTERN).fromJson(mockedGetBlockResponse, GetBlockResponse.class)); + } this.mockAbiProvider(EOSIOTOKENABIJSON); this.mockSerializationProvider(MOCKED_ACTION_HEX, MOCKED_TRANSACTION_HEX, mockedDeserilizedTransaction); @@ -661,7 +687,8 @@ private void mockRPC( @Nullable GetInfoResponse getInfoResponse, @Nullable GetBlockInfoResponse getBlockInfoResponse, @Nullable GetRequiredKeysResponse getRequiredKeysResponse, - @Nullable SendTransactionResponse sendTransactionResponse) { + @Nullable SendTransactionResponse sendTransactionResponse, + @Nullable GetBlockResponse getBlockResponse) { if (getInfoResponse != null) { try { @@ -672,6 +699,15 @@ private void mockRPC( } } + if (getBlockResponse != null) { + try { + when(mockedRpcProvider.getBlock(any(GetBlockRequest.class))).thenReturn(getBlockResponse); + } catch (GetBlockRpcError getBlockRpcError) { + getBlockRpcError.printStackTrace(); + fail("Exception should not be thrown here for mocking getBlock"); + } + } + if (getBlockInfoResponse != null) { try { when(mockedRpcProvider.getBlockInfo(any(GetBlockInfoRequest.class))).thenReturn(getBlockInfoResponse); @@ -792,7 +828,23 @@ private void mockSignatureProvider(List mockedAvaialbleKeys, EosioTransa // Mock data for prepare private static final String mockedGetInfoResponse = "{\n" - + " \"server_version\": \"1\",\n" + + " \"server_version\": \"2\",\n" + + " \"chain_id\": \"sample chain id\",\n" + + " \"head_block_num\": " + headBlockNum + ",\n" + + " \"last_irreversible_block_num\": 1,\n" + + " \"last_irreversible_block_id\": \"1\",\n" + + " \"head_block_id\": \"1\",\n" + + " \"head_block_time\": \"" + headBlockTime + "\",\n" + + " \"head_block_producer\": \"bp\",\n" + + " \"virtual_block_cpu_limit\": 1,\n" + + " \"virtual_block_net_limit\": 1,\n" + + " \"block_cpu_limit\": 1,\n" + + " \"block_net_limit\": 1,\n" + + " \"server_version_string\": \"v2.1.0\"\n" + + "}"; + + private static final String mockedOlderGetInfoResponse = "{\n" + + " \"server_version\": \"2\",\n" + " \"chain_id\": \"sample chain id\",\n" + " \"head_block_num\": " + headBlockNum + ",\n" + " \"last_irreversible_block_num\": 1,\n" @@ -804,7 +856,7 @@ private void mockSignatureProvider(List mockedAvaialbleKeys, EosioTransa + " \"virtual_block_net_limit\": 1,\n" + " \"block_cpu_limit\": 1,\n" + " \"block_net_limit\": 1,\n" - + " \"server_version_string\": \"v1.3.0\"\n" + + " \"server_version_string\": \"v2.0.0\"\n" + "}"; private static final String mockedGetBlockInfoResponse = "{\n" @@ -821,6 +873,20 @@ private void mockSignatureProvider(List mockedAvaialbleKeys, EosioTransa + " \"ref_block_prefix\": " + refBlockPrefix + "\n" + "}"; + private static final String mockedGetBlockResponse = "{\n" + + " \"timestamp\": \"2019-04-01T22:08:38.500\",\n" + + " \"producer\": \"bp\",\n" + + " \"confirmed\": 0,\n" + + " \"previous\": \"1\",\n" + + " \"transaction_mroot\": \"0000000000000000000000000000000000000000000000000000000000000000\",\n" + + " \"action_mroot\": \"1\",\n" + + " \"schedule_version\": 3,\n" + + " \"producer_signature\": \"SIG\",\n" + + " \"id\": \"1\",\n" + + " \"block_num\": 31984399,\n" + + " \"ref_block_prefix\": " + refBlockPrefix + "\n" + + "}"; + private static final String mockedEosioTransactionSignatureResponseJSON = "{" + "\"serializedTransaction\": \"" + MOCKED_TRANSACTION_HEX + "\"," + "\"signatures\": [\"" + MOCKED_SIGNATURE + "\"]"