3

I have setup a private Quorum network and successfully deployed contracts and executed contract functions using Visual Studio Code and remix.

When i try to deploy the exact same contract manually using Web3.js using a newly created account, i am seeing weird behaviour. Running the deployment code(pasted at end) does not show any error in node, in fact it returns the Transaction hash as expected. If i check the TransactionReceipt for the hash, it shows the contractAddress as well(screenshot below). enter image description here

Problems

  1. When i give that contract address in the "Quorum network" extension in remix, it shows an error saying the contract does not exist(screenshot below). enter image description here

  2. When i give that contract address in the "Deploy & Run Transactions" extension in remix, it does not give any error and successfully runs get functions returning nothing. But it asks me for a passphrase when i try a set function(screenshot below). I do not know what this passphrase is.. i tried the same private key i used to sign the transaction when deploying, but it did not work. enter image description here

  3. If i try deploying the contract again, it gives me a "nonce too low" error(screenshot below). enter image description here

  4. I have only one RPC, so there is no chance of me using the wrong RPC by mistake. I am not hardcoding the nonce, so no risk there. web3.eth.getTransactionCount still gives me 0, which indicates no transaction has yet been sent from that account. But that does not make sense because i can see the TransactionReceipt for the first transaction i sent. I do notice that the TransactionReceipt shows a "from" address that i do not recognize.. it is not the account whose private key i used to sign the transaction. This mysterious "from" address has a transactionCountof 1 : enter image description here

I am beyond my depth here.. if some one can give me some ideas as to how did this mysterious address come into existence or whether the contract actually got deployed or for any of the other points.. please do.

Code

const Web3 = require('web3')

const rpcURL = "https://<myRPCURL>"

const web3 = new Web3(rpcURL)

const EthereumTx = require('ethereumjs-tx').Transaction

const account = '0x841Be8B07475dDE4e67b247Cf8F6dc59Ab71C93b'

const privateKey = Buffer.from('<myPivateKey>', 'hex')

var accountNonce

web3.eth.getTransactionCount(account, (err, txCount) => {
    if (err!=null) {console.log('err: ', err)}
    console.log(txCount)
    accountNonce = txCount
})

const contractByteCode = '0x608060405234801561001057600080fd5b50610970806100206000396000f3fe60806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063144f9ac71461007257806346428adc146101025780638eb5234c1461028b578063e319990c14610306578063f56228c814610396575b600080fd5b34801561007e57600080fd5b50610087610499565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100c75780820151818401526020810190506100ac565b50505050905090810190601f1680156100f45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561010e57600080fd5b506102896004803603608081101561012557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561016c57600080fd5b82018360208201111561017e57600080fd5b803590602001918460018302840111640100000000831117156101a057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561020357600080fd5b82018360208201111561021557600080fd5b8035906020019184600183028401116401000000008311171561023757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061053b565b005b34801561029757600080fd5b506102c4600480360360208110156102ae57600080fd5b810190808035906020019092919050505061067b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561031257600080fd5b5061031b6106b9565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561035b578082015181840152602081019050610340565b50505050905090810190601f1680156103885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103a257600080fd5b506103ab610757565b604051808481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156103f55780820151818401526020810190506103da565b50505050905090810190601f1680156104225780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b8381101561045b578082015181840152602081019050610440565b50505050905090810190601f1680156104885780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b606060058054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105315780601f1061050657610100808354040283529160200191610531565b820191906000526020600020905b81548152906001019060200180831161051457829003601f168201915b5050505050905090565b816005908051906020019061055192919061089f565b5060008060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050838160000181905550828160010190805190602001906105b592919061089f565b50818160020190805190602001906105ce92919061089f565b508360026000018190555082600260010190805190602001906105f292919061089f565b508160028001908051906020019061060b92919061089f565b506001808690806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050505050565b60018181548110151561068a57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60058054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561074f5780601f106107245761010080835404028352916020019161074f565b820191906000526020600020905b81548152906001019060200180831161073257829003601f168201915b505050505081565b6002806000015490806001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107f75780601f106107cc576101008083540402835291602001916107f7565b820191906000526020600020905b8154815290600101906020018083116107da57829003601f168201915b505050505090806002018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108955780601f1061086a57610100808354040283529160200191610895565b820191906000526020600020905b81548152906001019060200180831161087857829003601f168201915b5050505050905083565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106108e057805160ff191683800117855561090e565b8280016001018555821561090e579182015b8281111561090d5782518255916020019190600101906108f2565b5b50905061091b919061091f565b5090565b61094191905b8082111561093d576000816000905550600101610925565b5090565b9056fea165627a7a72305820845c427085709af3cb79b879eac302fec884aed75e0f8515afbbdbfac1a9f8990029'

const txObject = {
    nonce: web3.utils.toHex(accountNonce),
    gasLimit: web3.utils.toHex(1000000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('0', 'gWei')),
    data: contractByteCode
}

const tx = new EthereumTx(txObject)
tx.sign(privateKey)

const serializedTransaction = tx.serialize()
const raw = '0x' + serializedTransaction.toString('hex')

web3.eth.sendSignedTransaction(raw,(err, txHash) => {
    if (err!=null) {console.log('err: ', err)}
    console.log('txHash:', txHash)
})

admin.nodeInfo.protocols enter image description here

  • 1
    Hi, this is pretty indepth, so id suggest getting on our slack to solicit help: bit.ly/quorum-slack – fixanoid Jan 20 at 4:49
  • 1
    Have your tried a different version of solc? I once got similar weird issues that were resolved by changing the solc compiler version from 0.5.x to 0.4.25. For example in release 0.5.14 they changed the default evm version. github.com/ethereum/solidity/releases – toothleth_byte Jan 20 at 6:46
  • @toothleth_byte Interesting! i changed the compiler in remix to 0.4.25, compiled it and then tried a set function in the "Deploy & Run Transactions" plugin in remix. This seems to have worked.. the transaction was successful.. i got a transaction hash and the receipt shows the status as true. But when i do a get function, it still returns blank. This indicates the set function did not really work? The Quorum network plugin still says the contract does not exist. – faizal Jan 20 at 8:58
  • Yes, in the same 0.5.x context, Log-Events where not generated or Retrievable. Yes, the get-Functions with multiple return values also seem do not work. Only when you use the natural generated getter from solc, e.g. functions wich are "public". Some search on GitHub suggests enabling "eip145Transition": block "eip1014Transition": block "eip1052Transition": block This Issue refers to Alastria, a Quorum Based Chain: github.com/alastria/alastria-node/issues/550 – toothleth_byte Jan 20 at 9:47
  • The problem seems to be something to do with sending signed transactions. Deploying the contract with an unlocked account using contract.deploy.send works perfectly. – faizal Jan 20 at 11:06
1

I am pasting the solution here that i got as a response from the slack channel, almost verbatim.

By default, EthereumJS-Tx signs for the Ethereum Mainnet. Transactions made for custom networks have some of their values changes, and this needs to be taken into account when signing the transactions. What has happened here is we have signed the transaction using some wrong values, and so when recovering the signers address (the from field), we get a different value. In order to sign transactions (at least, public transactions, which seems to be what you're doing here), then we need to set these values to what they should be. I've taken the following code from your snippet and from the instructions given by EthereumJS-Tx for custom chains, with one slight tweak as their instructions seem to assume using ES Modules in Node.js, which I wasn't doing.

const Web3 = require('web3');
const rpcURL = "http://localhost:22000";
const web3 = new Web3(rpcURL);
const EthereumTx = require('ethereumjs-tx').Transaction;
const account = '0x841Be8B07475dDE4e67b247Cf8F6dc59Ab71C93b';
const privateKey = Buffer.from('<privateKey>', 'hex');
var accountNonce;
web3.eth.getTransactionCount(account, (err, txCount) => {
    if (err != null) {
        console.log('err: ', err)
    }
    console.log(txCount);
    accountNonce = txCount
});
const contractByteCode = '0x6060604052341561000f57600080fd5b604051602080610149833981016040528080519060200190919050505b806000819055505b505b610104806100456000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632a1afcd914605157806360fe47b11460775780636d4ce63c146097575b600080fd5b3415605b57600080fd5b606160bd565b6040518082815260200191505060405180910390f35b3415608157600080fd5b6095600480803590602001909190505060c3565b005b341560a157600080fd5b60a760ce565b6040518082815260200191505060405180910390f35b60005481565b806000819055505b50565b6000805490505b905600a165627a7a72305820d5851baab720bba574474de3d09dbeaabc674a15f4dd93b974908476542c23f00029';
const txObject = {
    nonce: web3.utils.toHex(accountNonce),
    gasLimit: web3.utils.toHex(1000000),
    gasPrice: web3.utils.toHex(web3.utils.toWei('0', 'gWei')),
    data: contractByteCode
};
const Common = require('ethereumjs-common').default;
const customCommon = Common.forCustomChain(
    'mainnet',
    {
        name: 'my-network',
        chainId: 10,
    },
    'constantinople',
);
const tx = new EthereumTx(txObject, { common: customCommon });
tx.sign(privateKey);
const serializedTransaction = tx.serialize();
const raw = '0x' + serializedTransaction.toString('hex');
web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    if (err != null) {
        console.log('err: ', err)
    }
    console.log('txHash:', txHash)
});

The main difference being that we have defined a variable called customCommon and passing that into the EthereumTx constructor, so it knows what parameters to use when signing. My network has a chainId of 10, but you should change it to your value, which is 2226 - visible in the admin.node.protocols command in geth.

Secondly, a quick note on Javascript and Promises/Callbacks. I see you are fetching the account nonce and then assigning it into a global variable for use later. This won't work, because the callback is executed at some undetermined time later. This means the rest of the code executes before the callback returns, and this the account nonce is always set to 0 when you create the txObject variable. Hence, you are getting the nonce too low errors, as the nonce of your transaction is also 0, which is taken. There are 3 solutions here:

  1. put the rest of the code inside the callback function passed to getTransactionCount. This means you won't need the global variable, you can use the one passed into the callback.
  2. Use promises - actually just callbacks but using a different syntax, very popular
  3. Use async/await functions, this means you can wait for the function to return the value instead of executing a callback. Each of the 3 options is general Javascript learning points, not related to Quorum directly, so I will leave you to look up what they entail!
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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