Private Transactions

The Masa Protocol implements Tessera to enable private transactions. Tessera is a stateless Java system used to enable the encryption, decryption, and distribution of private transactions.

Masa achieves transaction privacy by:

  • Enabling transaction senders to create private transactions by marking who is privy to a transaction via the privateFor parameter.
  • Storing encrypted private data off-chain in a separate component called the private transaction manager. The private transaction manager encrypts private data, distributes the encrypted data to other parties that are privy to the transaction, and returns the decrypted payload to those parties.
  • Replacing the payload of a private transaction with a key for the location of the encrypted payload, such that the original payload isn’t visible to participants who aren’t privy to the transaction.



While Masa introduces the notion of “public transactions” and “private transactions,” it does not introduce new transaction types. Rather, it extends the Ethereum transaction model to include an optional privateFor parameter (the inclusion of which results in the Masa protocol treating a transaction as private) and the transaction type has a new IsPrivate method to identify private transactions.

Public transactions

Public transactions have payloads visible to all participants of the same network. These are created as standard Ethereum transactions.

Examples of public transactions include market data updates from a service provider or a reference data update such as a correction to a bond security definition.

Private transactions

Private transactions have payloads visible only to the network participants whose public keys are specified in the privateFor parameter of the transaction. privateFor can take multiple addresses in a comma-separated list.

When a Masa node encounters a transaction with a non-null privateFor value, it sets the v value of the transaction signature to 37 or 38 (as opposed to public transactions, whose v values are set according to EIP-155).

Public vs. private transaction handling

Public transactions are executed in the standard Ethereum way. If a public transaction is sent to an account that holds contract code, each participant executes the same code, and their state databases are updated accordingly.

Private transactions are executed differently: before the sender’s Masa node propagates the transaction to the rest of the network, the node substitutes the original transaction payload with a key for the location of the encrypted payload received from Tessera. Participants privy to the transaction can replace the hash with the original payload via their Tessera instance, while participants not privy only see the hash.

If a private transaction is sent to an account that holds contract code, participants not privy to the transaction skip the transaction and don’t execute the contract code. Participants privy to the transaction replace the hash and call the virtual machine for execution, and their state databases update accordingly.

As a result, these two sets of participants have different state databases and can’t reach consensus. To support this forking of contract state, Masa stores the state of public contracts in a public state trie that is globally synchronized and the state of private contracts in a private state trie not globally synchronized.

State verification

Block validation includes a check on the root of the public state trie to determine if the public state is synchronized across nodes. It also includes checking the global transaction hash, which is a hash of all public and private transactions in a block. This means that each node can validate that it has the same set of transactions as other nodes.

Synchronization of the public state root and private transaction inputs (through the global transaction hash) can imply synchronization of the private state across participating nodes.

To further validate that the private state change from a private transaction is the same across all participants, use eth_storageRoot, specifying the private smart contract address and block height. If the state is in sync across all participating nodes, they return the same root hash.


This model restricts the ability to change public state in private transactions. Since a common use case for a private contract is to read data from a public contract, the virtual machine changes to read-only mode for each call from a private contract to a public contract. If the virtual machine is in read-only mode, and the code tries to make a state change, the virtual machine stops execution and throws an exception.

Did this page help you?