Skip to content

Commit

Permalink
Fix for RPC key usage (#3362)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesSmartCell authored Feb 20, 2024
1 parent 9f8938e commit c5b66bb
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public AAATokenScriptCertificateTest()
fail("Please config seed phrase and wallet address for this API level first.");
}

web3j = EthUtils.buildWeb3j(GANACHE_URL);
web3j = EthUtils.buildWeb3j(GANACHE_URL, 2L);

String privateKey = array[0];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void setUp()
contractOwnerCredentials = Credentials.create(contractOwnerPk);

super.setUp();
web3j = EthUtils.buildWeb3j(GANACHE_URL);
web3j = EthUtils.buildWeb3j(GANACHE_URL, 2L);
deployTestTokenOnGanache();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
*/
public abstract class EthUtils
{
public static Web3j buildWeb3j(String url)
public static Web3j buildWeb3j(String url, long chainId)
{
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(C.CONNECT_TIMEOUT, TimeUnit.SECONDS)
Expand All @@ -41,7 +41,7 @@ public static Web3j buildWeb3j(String url)
.retryOnConnectionFailure(true)
.build();

AWHttpService svs = new AWHttpService(url, url, client, false);
AWHttpService svs = new AWHttpService(url, url, chainId, client,null, null, null, false);
return Web3j.build(svs);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
import java.util.concurrent.ConcurrentHashMap;

import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;

/**
Expand Down Expand Up @@ -958,7 +959,8 @@ else if (attr.function == null) // static attribute from tokenId (eg city mappi
.map(transactionResult -> addParseResultIfValid(token, useTokenId, attr, transactionResult))// only cache live transaction result
.map(result -> restoreFromDBIfRequired(result, cachedResult)) // If network unavailable restore value from cache
.map(txResult -> attrIf.storeAuxData(walletAddress, txResult)) // store new data
.map(result -> parseFunctionResult(result, attr)); // write returned data into attribute
.map(result -> parseFunctionResult(result, attr))
.subscribeOn(Schedulers.io()); // write returned data into attribute
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,8 @@ public TokenRepository(

private void buildWeb3jClient(NetworkInfo networkInfo)
{
AWHttpService publicNodeService = new AWHttpService(networkInfo.rpcServerUrl, networkInfo.backupNodeUrl, okClient, false);
HttpServiceHelper.addRequiredCredentials(networkInfo.chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(),
KeyProviderFactory.get().getInfuraSecret(), EthereumNetworkBase.usesProductionKey);
AWHttpService publicNodeService = new AWHttpService(networkInfo.rpcServerUrl, networkInfo.backupNodeUrl, networkInfo.chainId, okClient, KeyProviderFactory.get().getInfuraKey(),
KeyProviderFactory.get().getInfuraSecret(), KeyProviderFactory.get().getKlaytnKey(), false);
web3jNodeServers.put(networkInfo.chainId, Web3j.build(publicNodeService));
}

Expand Down Expand Up @@ -1317,9 +1316,8 @@ public static Web3j getWeb3jServiceForEvents(long chainId)
secondaryNode = EthereumNetworkRepository.getNodeURLByNetworkId(chainId);
}

AWHttpService publicNodeService = new AWHttpService(nodeUrl, secondaryNode, okClient, false);
HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(),
KeyProviderFactory.get().getInfuraSecret(), EthereumNetworkBase.usesProductionKey);
AWHttpService publicNodeService = new AWHttpService(nodeUrl, secondaryNode, chainId, okClient, KeyProviderFactory.get().getInfuraKey(),
KeyProviderFactory.get().getInfuraSecret(), KeyProviderFactory.get().getKlaytnKey(), false);
return Web3j.build(publicNodeService);
}

Expand All @@ -1332,9 +1330,8 @@ public static Web3j getWeb3jService(long chainId)
.retryOnConnectionFailure(true)
.build();

AWHttpService publicNodeService = new AWHttpService(EthereumNetworkRepository.getNodeURLByNetworkId(chainId), EthereumNetworkRepository.getSecondaryNodeURL(chainId), okClient, false);
HttpServiceHelper.addRequiredCredentials(chainId, publicNodeService, KeyProviderFactory.get().getKlaytnKey(),
KeyProviderFactory.get().getInfuraSecret(), EthereumNetworkBase.usesProductionKey);
AWHttpService publicNodeService = new AWHttpService(EthereumNetworkRepository.getNodeURLByNetworkId(chainId), EthereumNetworkRepository.getSecondaryNodeURL(chainId), chainId, okClient, KeyProviderFactory.get().getInfuraKey(),
KeyProviderFactory.get().getInfuraSecret(), KeyProviderFactory.get().getKlaytnKey(), false);
return Web3j.build(publicNodeService);
}

Expand Down
60 changes: 49 additions & 11 deletions app/src/main/java/com/alphawallet/app/service/AWHttpService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
*
*/

import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_BAOBAB_ID;
import static com.alphawallet.ethereum.EthereumNetworkBase.KLAYTN_ID;
import static okhttp3.ConnectionSpec.CLEARTEXT;

import android.text.TextUtils;

import com.google.gson.JsonParseException;

import org.slf4j.Logger;
Expand Down Expand Up @@ -38,7 +42,6 @@
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import timber.log.Timber;

/** HTTP implementation of our services API. */
public class AWHttpService extends HttpService
Expand Down Expand Up @@ -101,15 +104,23 @@ public class AWHttpService extends HttpService
private final String secondaryUrl;

private final boolean includeRawResponse;
private final String infuraSecret;
private final String infuraKey;
private final String klaytnKey;
private final long chainId;

private final HashMap<String, String> headers = new HashMap<>();

public AWHttpService(String url, String secondaryUrl, OkHttpClient httpClient, boolean includeRawResponses) {
public AWHttpService(String url, String secondaryUrl, long chainId, OkHttpClient httpClient, String infuraKey, String infuraSecret, String klaytnKey, boolean includeRawResponses) {
super(includeRawResponses);
this.url = url;
this.httpClient = httpClient;
this.includeRawResponse = includeRawResponses;
this.secondaryUrl = secondaryUrl;
this.infuraKey = infuraKey;
this.infuraSecret = infuraSecret;
this.klaytnKey = klaytnKey;
this.chainId = chainId;
}

@Override
Expand All @@ -125,6 +136,8 @@ protected InputStream performIO(String request) throws IOException
requestBody = RequestBody.create("", MEDIA_TYPE_TEXT);
}

addRequiredSecrets(url);

okhttp3.Request httpRequest =
new okhttp3.Request.Builder()
.url(url)
Expand All @@ -138,20 +151,31 @@ protected InputStream performIO(String request) throws IOException
//try primary node
response = httpClient.newCall(httpRequest).execute();
}
catch (SocketTimeoutException e) //seamlessly attempt a call to secondary node if primary timed out
catch (SocketTimeoutException e)
{
if (secondaryUrl != null) //only if we have a secondary node
{
return trySecondaryNode(request);
}
}
catch (java.io.InterruptedIOException e) //interrupted exception should be thrown back
{
throw e;
}
catch (Exception e) //seamlessly attempt a call to secondary node if primary node has some error
{
if (secondaryUrl != null) //only if we have a secondary node
{
return trySecondaryNode(request);
}
else
{
throw new SocketTimeoutException();
throw e; //throw the error back up the stack
}
}
//TODO: Also check java.io.InterruptedIOException

if (response.code() / 100 == 4) //rate limited
if (response.code() / 100 != 2)
{
response.close();
return trySecondaryNode(request);
Expand All @@ -162,16 +186,17 @@ protected InputStream performIO(String request) throws IOException

private InputStream trySecondaryNode(String request) throws IOException
{
Timber.d("trySecondaryNode: ");
RequestBody requestBody = RequestBody.create(request, JSON_MEDIA_TYPE);

okhttp3.Request httpRequest =
new okhttp3.Request.Builder().url(secondaryUrl).post(requestBody).build();

okhttp3.Response response;
addRequiredSecrets(secondaryUrl);

response = httpClient.newCall(httpRequest).execute();
okhttp3.Request httpRequest =
new okhttp3.Request.Builder()
.url(secondaryUrl)
.headers(buildHeaders())
.post(requestBody).build();

okhttp3.Response response = httpClient.newCall(httpRequest).execute();
return processNodeResponse(response, request, true);
}

Expand Down Expand Up @@ -244,6 +269,19 @@ private InputStream buildInputStream(Response response) throws IOException {
}
}

private void addRequiredSecrets(String url)
{
if (!TextUtils.isEmpty(infuraKey) && url.endsWith(infuraKey) && !TextUtils.isEmpty(infuraSecret)) //primary InfuraKey has secret
{
addHeader("Authorization", "Basic " + infuraSecret);
}
else if (!TextUtils.isEmpty(klaytnKey) && (chainId == KLAYTN_BAOBAB_ID || chainId == KLAYTN_ID))
{
addHeader("x-chain-id", Long.toString(chainId));
addHeader("Authorization", "Basic " + klaytnKey);
}
}

private Headers buildHeaders() {
return Headers.of(headers);
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/test/java/com/alphawallet/app/ENSTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static AWHttpService getWeb3jService()
.writeTimeout(C.LONG_WRITE_TIMEOUT, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build();
return new AWHttpService("https://mainnet.infura.io/v3/" + TextUtils.rot(Inf), "https://rpc.ankr.com/eth", okClient, false);
return new AWHttpService("https://mainnet.infura.io/v3/" + TextUtils.rot(Inf), "https://rpc.ankr.com/eth", 1, okClient, null, null, null, false);
}

public static Web3j getWeb3j(AWHttpService service)
Expand Down

0 comments on commit c5b66bb

Please sign in to comment.