7

I am using Web3j for interacting with my private blockchain network created in Azure.

I have created contracts using Remix and Metamask and was able to view that Contract from Java.

However I was not able to deploy or create contract from Java. I followed the instructions from the link https://github.com/web3j/web3j.

I keep getting the error Transaction receipt was not generated after 600 seconds for transaction caused by org.web3j.protocol.exceptions.TransactionTimeoutException

ContractRunner.java

    public static void main(String args[]) throws InterruptedException, ExecutionException, IOException, CipherException, TransactionTimeoutException {
        Web3j web3 = Web3j.build(new HttpService("http://xxxxxxxxx.westus.cloudapp.azure.com:8545/"));  // defaults to http://localhost:8545/
        Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().sendAsync().get();
        String clientVersion = web3ClientVersion.getWeb3ClientVersion();
        System.out.println(clientVersion);
        Credentials credentials = WalletUtils.loadCredentials("MyPassword", "C:\\Users\\adheep_m\\AppData\\Roaming\\Ethereum\\keystore\\UTC--2017-07-07T13-52-18.006069200Z--3b0d3fa08f0e0b3da8fe1f8ac0e05861bfdada25");
        System.out.println(credentials.getAddress());

        Token contract = Token.deploy(web3,credentials,BigInteger.valueOf(3000000),BigInteger.valueOf(3000000),BigInteger.valueOf(0)).get();
        System.out.println(contract.getContractAddress());
    }

Token.sol

pragma solidity ^0.4.0;

contract Token {
mapping (address => uint) public balances;

function Token() {
    balances[msg.sender] = 1000000;
}

function transfer(address _to, uint _amount) {
    if (balances[msg.sender] < _amount) {
        throw;
    }

    balances[msg.sender] -= _amount;
    balances[_to] += _amount;
}

}

Token.java (Generated from Web3j)

public final class Token extends Contract {
    private static final String BINARY = "6060604052341561000f57600080fd5b5b600160a060020a0333166000908152602081905260409020620f424090555b5b6101678061003f6000396000f300606060405263ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166327e235e38114610048578063a9059cbb14610086575b600080fd5b341561005357600080fd5b61007473ffffffffffffffffffffffffffffffffffffffff600435166100b7565b60405190815260200160405180910390f35b341561009157600080fd5b6100b573ffffffffffffffffffffffffffffffffffffffff600435166024356100c9565b005b60006020819052908152604090205481565b73ffffffffffffffffffffffffffffffffffffffff3316600090815260208190526040902054819010156100fc57600080fd5b73ffffffffffffffffffffffffffffffffffffffff338116600090815260208190526040808220805485900390559184168152208054820190555b50505600a165627a7a7230582081fd33c821a86127abf00c9fafe2e14e4db6279ab9dd788e3ad3597d2280b6cf0029";

    private Token(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    private Token(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }

    public Future<Uint256> balances(Address param0) {
        Function function = new Function("balances", 
                Arrays.<Type>asList(param0), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallSingleValueReturnAsync(function);
    }

    public Future<TransactionReceipt> transfer(Address _to, Uint256 _amount) {
        Function function = new Function("transfer", Arrays.<Type>asList(_to, _amount), Collections.<TypeReference<?>>emptyList());
        return executeTransactionAsync(function);
    }

    public static Future<Token> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, BigInteger initialWeiValue) {
        return deployAsync(Token.class, web3j, credentials, gasPrice, gasLimit, BINARY, "", initialWeiValue);
    }

    public static Future<Token> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, BigInteger initialWeiValue) {
        return deployAsync(Token.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, "", initialWeiValue);
    }

    public static Token load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        return new Token(contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    public static Token load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        return new Token(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }
}

I am not sure what is wrong with the code. Any help would be greatly appreciated. Thanks!

3
  • 1
    did you start Geth the miner ?
    – Jamal N
    Commented Jul 10, 2017 at 13:54
  • 1
    Thanks Jamal, No I don't think I have. I have installed Geth but how do I start it as a Miner?
    – Adheep
    Commented Jul 10, 2017 at 14:02
  • 1
    Also Can you explain how starting Geth as a miner would help? I need to mine on my private Blockchain in Azure
    – Adheep
    Commented Jul 10, 2017 at 14:15

2 Answers 2

3

I am not sure about how did you configure your Blockchain on Azure, i assume that you have created a mining node(s) while you are creating your private blockchain, if so, we need to connect to that node with SSH,, to do so, lookup for the mining node address,, you can find it in :

Deployments > Microsoft-azure-blockchain.azure-multi....

Now, copy the line in front of (SSH-TO-FIRST-TX-NODE) and past it on your local machine's CMD, type yes for the yes/no question, it will than ask you for a password, use the same one you used while creating your blockchain.

After connecting to the node,, type geth attach ,, this will open the geth console for you,, once it's opened type miner.start(1) ,, where the parameter 1 is the number of the threads the miner can excute,, you can passe a bigger number.

5
  • 1
    Yes I did configure with Miners when I created my Blockchain. I am trying to deploy a contract using Web3j(Java client). So do I still do the steps that you mentioned above?
    – Adheep
    Commented Jul 11, 2017 at 10:05
  • 1
    Thank you Jamal for your descriptive answer, Yes i verified by the steps you gave, the Miners are running. But still my Java Client is getting TransactionTimeoutException
    – Adheep
    Commented Jul 11, 2017 at 12:41
  • 1
    String clientVersion = web3ClientVersion.getWeb3ClientVersion(); System.out.println(clientVersion); returns Geth/xxxxxtify-tx0/v1.6.0-stable-facc47cb/linux-amd64/go1.8.1 which implies that my program is able to connect with the TX nodes right? Is it something with the GAS and GAS_PRICE?
    – Adheep
    Commented Jul 11, 2017 at 12:51
  • 1
    Special Thanks for your help. The Mining nodes were all working properly. As I suspected the value of the GAS_PRICE and GAS_LIMIT supplied to the transaction was low hence the miners was not mining my transaction and I was getting the TimeoutException. See below answer for more details
    – Adheep
    Commented Jul 12, 2017 at 7:43
  • 1
    You are welcome,, apparently alot of problems happens because of GAS_PRICE and GAS_LIMIT ,, good luck man.
    – Jamal N
    Commented Jul 13, 2017 at 2:58
3

I finally figured out what was wrong with my code. I debugged the Web3j codes and found that since Mining nodes were not accepting the transaction after 40 retries with Sleep duration of 15000 the TransactionTimeoutException is thrown and the TransactionReceipt is not generated. See below Web3j code from TransactionManager.java

Source of the Exception

private static final int SLEEP_DURATION = 15000;
private static final int ATTEMPTS = 40;

private TransactionReceipt getTransactionReceipt(
        String transactionHash, int sleepDuration, int attempts)
        throws IOException, InterruptedException, TransactionTimeoutException {

    Optional<TransactionReceipt> receiptOptional =
            sendTransactionReceiptRequest(transactionHash);
    for (int i = 0; i < attempts; i++) {
        if (!receiptOptional.isPresent()) {
            Thread.sleep(sleepDuration);
            receiptOptional = sendTransactionReceiptRequest(transactionHash);
        } else {
            return receiptOptional.get();
        }
    }

    throw new TransactionTimeoutException("Transaction receipt was not generated after " +
            ((sleepDuration * attempts) / 1000 +
                    " seconds for transaction: " + transactionHash));
}

Reason

After breaking my head I found out that the issues was with low GAS_PRICE and GAS_LIMIT. Because of low values the miners didn't mine my transaction

FIX

I updated my code to use the default GAS_PRICE and GAS_LIMIT from Web3j's Contract class. See updated code below

    BigInteger GAS = Contract.GAS_LIMIT;
    BigInteger GAS_PRICE = Contract.GAS_PRICE;

    Token contract = Token.deploy(web3,credentials,GAS_PRICE,GAS,ETHER);
    System.out.println("Deployed Contract at "+contract.getContractAddress());

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.