Parity - Private Transactions

Parity Ethereum's private transactions feature allows to store, modify and view encrypted data on the Ethereum blockchain. The solution is agnostic to the type of the chain. You can deploy it on any Ethereum based chain with any consensus algorithm.

To learn how to implement the private transactions feature, follow this tutorial.


Public contract: A specifically crafted smart contract deployed on Ethereum blockchain that wraps a private contract. See the source of the contract. The public contract stores the encrypted code and state variables of the private contract. The deployment transaction for the public contract has to be generated by the Parity Ethereum client.

Private contract: A smart contract stored encrypted inside a public contract. The state and code of a private contract is not publicly readable. Reading or modifying a private contract's state and code is only possible for the specific accounts, these accounts are specified during the public contract's deployment.

Validator: An account that can allow a private contract's state change. The list of validators is specified during the public contract's deployment. Any account can be set as a validator. There is no blockchain incentive defined for the validator account.

Private transaction: A specifically crafted message containing encrypted data and a modified private contract's state. It requires the signature of all the validators in order for the changes to be applied.

Public transaction: A regular transaction call to a public contract that results in changes being stored in a private contract.

System architecture

The system contains the following components: - Parity nodes. The system uses specifically crafted messages with encrypted data in order to communicate between nodes. - A public contract containing the encrypted code of a private contract (see terminology). - Secret Store nodes used to create and provide access to the encryption key. One key is associated with one public contract. This key is used to encrypt the state of the private contract and any message exchanged between the nodes (to gather validator's signatures for instance). The exact Secret Store URL is specified for every Parity node participating in a private transaction system (see Parity-flags). A permissioning contract may be used to describes which account has access to which contract's key. The availability of the Secret Store is crucial for the system to work flawlessly.

In the example below: Nodes A and C have access to the contract's key. Node B doesn't. Node C is specified as a validator for the system.


Account's rights overview

Type of account Can view private contract's data and code Can modify private contract data
Regular account (without access to the private contract's key) No No
Account with access to the private contract's key Yes Yes
Account specified in the system as Validator Yes Yes

Flow description

We use a trivial private contract as example: contract Test1 { bytes32 public x; function setX(bytes32 _x) { x = _x; } } In order to call setX method of the deployed private contract, the user needs to:

1) Compose a regular transaction calling the contract's corresponding methods, in this example SetX(42):

curl --data '{"method":"parity_composeTransaction","params":[{"from":"0xcf9e2287227c5cc5978e7bdbbdaf293fe4992a24","to":"0x52f5f1b8c785ab1c0e892b4c46b080fde9ad992b","data":"0xbc64b76d2a00000000000000000000000000000000000000000000000000000000000000"}],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8549

Where 0xbc64b76d2a...00000000 corresponds to the call of SetX() using an arbitrary parameter 42.

2) Sign the transaction. 3) Send the signed transaction using private_sendTransaction API method:

curl --data '{"method":"private_sendTransaction","params":["0xf88407...1137"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8549

Where 0xf88407...1137 is the signed transaction created previously.

The next steps of the flow are shown in the picture below:


Public/private contracts internals

Let's consider another example in order to understand in details the wrapping of a private contract into a public one. If we want to use the following voting contract as the private contract: source. The public contract wrapping the aforementioned private contract must be deployed using private_composeDeploymentTransaction API method. As explained before, this API call will prepare a transaction that once broadcasted will deploy a public contract storing the private contract's state and code (the deployed public contract's looks like this).

To call vote(1) from the private contract for instance, the system performs the following steps:


Current limitations:

Setup of the private network

The following steps need to be performed in order to setup a blockchain with private transactions using Parity client:

0) (Pre-requisite) Contracts registry must be deployed on the chain. 1) Deploy the Secret Store permissioning contract and add its address to the contracts registry under the name secretstore_acl_checker. A trivial example of the permissioning contract can be found here The only requirement for such a contract is to have the ABI:

function checkPermissions(address user, bytes32 document) constant returns (bool) {}

It's up to the network's administrator to define the logic for providing access to the keys inside this contract.

2) Deploy the private contract. In the following example the same trivial private contract is used: contract Test1 { bytes32 public x; function setX(bytes32 _x) { x = _x; } } In order to deploy the private contract:

2.1) Composed and sign a regular transaction with the private contract's code Example:

curl --data '{"method":"parity_composeTransaction","params":[{"from":"0xcf9e2287227c5cc5978e7bdbbdaf293fe4992a24","data":"0x6060604052341561000f57600080fd5b60d88061001d6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630c55699c146046578063bc64b76d14607457600080fd5b3415605057600080fd5b60566098565b60405180826000191660001916815260200191505060405180910390f35b3415607e57600080fd5b6096600480803560001916906020019091905050609e565b005b60005481565b8060008160001916905550505600a165627a7a723058206acbdf4b15ca4c2d43e1b1879b830451a34f1e9d02ff1f2f394d8d857e79d2080029"}],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8549

Where 0x606060405234...9d2080029 is the private contract's code. The resulting transaction must then be signed.

2.2) Generate the transaction for the specifically crafted public contract using the private API. Example:

curl --data '{"method":"private_composeDeploymentTransaction","params":["pending", "0xf9014203...ba4a30127e29774d15b1e12be", ["0x7ffbe3512782069be388f41be4d8eb350672d3a5"], "0x0"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8549`

Where 0xf9014203...ba4a30127e29774d15b1e12be is the signed transaction from the previous step. This method returns a transaction, which should be signed as well. See JSON-RPC api methods for more details.

2.3) The transaction containing the specifically crafted public contract should be broadcasted using eth_sendRawTransaction method, resulting in the public contract being deployed on the blockchain.

3) Specify the private contract key permissions: In order to obtain the key id associated with the contract, use the private_contractKey private API method (that can be called locally). Example:

curl --data '{"method":"private_contractKey","params":["0x52f5f1b8c785ab1c0e892b4c46b080fde9ad992b"],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8549

Where 0x52f5f1b...d992b is the public contract's address returned at step 2.2 (JSON-RPC api methods for more details). The permissions for this key id now need to get set in the Secret Store permissioning contract. You can do so by calling the method addKey(address[] users, bytes32 key) from the the sample contract with key id and the address list of the nodes allowed to use the key.


To use the private transactions functionality, Parity client must be launched with specifc private flags. Find more information on Private Transactions Options and in the Private transactions tutorial.