0

I am struggling to enforce privacy using Quorum's privateFor option.

I have provisioned a consortium in Azure blockchian service with 3 nodes. I deploy a smart contract from node2 privateFor node1 using the below code, but node3 can see the contract and execute functions as well(in remix for example). I can't figure out what i am doing wrong.

const Web3 = require('web3')
const rpcURL = "https://node2.blockchain.azure.com:3200/<AccessKey>"
const web3 = new Web3(rpcURL)
const EthereumTx = require('ethereumjs-tx').Transaction
const account = '<myAccountAddress>'
const privateKey = Buffer.from('<myPrivateKey>', 'hex')

const contractByteCode = '<contractbByteCode>'

const Common = require('ethereumjs-common').default

const customCommon = Common.forCustomChain(
    'mainnet',
    {
        name: 'my-network',
        chainId: <myChainId>, //from genesis
    },
    'constantinople',
);

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

        const txObject = {
            nonce: web3.utils.toHex(txCount),
            gasLimit: web3.utils.toHex(3000000),
            gasPrice: web3.utils.toHex(web3.utils.toWei('0', 'gWei')),
            data: contractByteCode,
            privateFor: ['<node1publickey>']
        }

        const tx = new EthereumTx(txObject,{common: customCommon})

        tx.sign(privateKey)

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

        web3.eth.sendSignedTransaction(raw)
        .on('transactionHash',(hash) => {
            console.log('txHash:', hash)
        })
        .on('receipt',(receipt) => {
            console.log('receipt', receipt)
        })
        .on('error', console.error)
    }

})

The Azure Blockchain service overview page looks like below. I do not see any mention of transaction member or constellation or Tessera : enter image description here

2 Answers 2

3

Your code is a good example of sending a public txn that is externally signed, but it is not a private txn, thus the contract is available on all nodes of the chain.

Sending a private txn is a bit more complicated and involves an additional set of keys and servers -- these belong to Private Transaction Manager (Tessera) on your network. We do have a set of examples here: https://github.com/jpmorganchase/quorum.js/tree/master/7nodes-test and you can read https://github.com/jpmorganchase/quorum.js to understand what we do if you wish to avoid using quorum.js.

3
  • i did go through the quorum.js page, but it mentions EnclaveOptions with an ipcpath, public and private URLs. I don't understand what these are referring to. There is no such thing provided on the Azure portal. After talking to the some folks, i was led to believe all i need to do is set the PrivateFor parameter in the transaction object. But looks like that is not enough. Would you happen to know where i can get these transaction manager values from in the Azure blockchain service?
    – faizal
    Commented Feb 5, 2020 at 17:17
  • Right, so this could be a tad confusing. EnclaveOptions is the connectivity string to the PTM. On Azure, PTM is Tessera and its address should be somewhere in the overview section (I don't have Azure MB running, but thats as much as I remember). This is where you'd copy the connection string and also the spot you'll find the public key for your node -- you will need to ask other members of the consortium for their public key -- this is the privateFor key
    – fixanoid
    Commented Feb 5, 2020 at 18:53
  • I have added a screenshot of the overview page in my question. I do not see any PTM/Tessera address. Yes, the public key is there on the transaction nodes page and that is what i used in the PrivateFor parameter in my code.
    – faizal
    Commented Feb 6, 2020 at 6:01
1

Adding to the answer by @fixanoid,

I got the following reply from the Azure blockchain service team "Currently we don’t support sending signed private transactions as we have not exposed tessera port for sending private transaction so web3.sendRawPrivateTransaction will not work. To send private transaction you have to use web3 sendTransaction function not sendSignedTransaction which is for public transactions."

I have tried it and it works perfectly. I used the default account that was created by the Azure blockchain service on the transaction node. I created a new account on the node, that also worked. The code is simpler as the complexity around explicitly signing using a private key and using the ethereumjs-common library to define a custom chain is gone.

const Web3 = require('web3')
const rpcURL = "https://node2.blockchain.azure.com:3200/<AccessKey>"
const web3 = new Web3(rpcURL)
const account = '<myAccount>'
const accountPassword = '<myPassword>'

const contractByteCode = '<contractByteCode>'

web3.eth.personal.unlockAccount(account, accountPassword, 60)

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

        const txObject = {
            from: account,
            nonce: web3.utils.toHex(txCount),
            gas: web3.utils.toHex(3000000),
            gasPrice: web3.utils.toHex(web3.utils.toWei('0', 'gWei')),
            data: contractByteCode,
            privateFor: ['<nodepublickey>']
        }

        web3.eth.sendTransaction(txObject)
        .on('transactionHash',(hash) => {
            console.log('txHash:', hash)
        })
        .on('receipt',(receipt) => {
            console.log('receipt', receipt)
        })
        .on('error', console.error)
    }

})

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.