Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

[PAN-2340] simple permissioning smart contract #1035

Merged
merged 20 commits into from
Mar 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions acceptance-tests/simple-permissioning-smart-contract/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
## Pre-requisites
* [Truffle](https://truffleframework.com/) installed
```
npm install -g truffle
```
* [Wallet](https://www.npmjs.com/package/truffle-hdwallet-provider) installed
```
npm install truffle-hdwallet-provider
```
## To run the tests:
```
cd acceptance-tests/simple-permissioning-smart-contract
```
* here you will find truffle.js which has network configurations for
* development (Ganache) and
* devwallet (points to localhost:8545)
* Note you need Ganache running if you want to run the tests against it (see below)
* Also this truffle.js uses address and private key generated by Ganache with default mnemonic "candy maple cake sugar pudding cream honey rich smooth crumble sweet treat"

* To run the Truffle example with Pantheon, you need Pantheon running
* [check out and build Pantheon](../../README.md)
* run Pantheon (either in IDE or via command line), with mining and RPC enabled.

* Run Truffle migrate against Ganache
```
truffle migrate
```
* Output should look something like:
```
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/SimplePermissioning.sol...
Writing artifacts to ./build/contracts

⚠️ Important ⚠️
If you're using an HDWalletProvider, it must be Web3 1.0 enabled or your migration will hang.


Starting migrations...
======================
> Network name: 'development'
> Network id: 5777
> Block gas limit: 6721975


1_initial_migration.js
======================

Deploying 'Migrations'
----------------------
> transaction hash: 0x346b51830819ac04aac4c10082ac3e2b534fee424fa702e37155a4f8eee12f61
> Blocks: 0 Seconds: 0
> contract address: 0xD7de17FB4DFB954535E35353dC82dBB6156a8078
> account: 0x627306090abaB3A6e1400e9345bC60c78a8BEf57
> balance: 96.53012304
> gas used: 284908
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00569816 ETH


> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.00569816 ETH


2_deploy_contracts.js
=====================

Deploying 'SimplePermissioning'
-------------------------------
> transaction hash: 0x0752d5683ecb210308bc4c387fd8d4bbfde4c05a335bdcf594b608c2e63abf5a
> Blocks: 0 Seconds: 0
> contract address: 0x1baf55be3D4b5f1911EB729EEa5A8d089Ee1162a
> account: 0x627306090abaB3A6e1400e9345bC60c78a8BEf57
> balance: 96.50582406
> gas used: 1172915
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.0234583 ETH


> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.0234583 ETH


Summary
=======
> Total deployments: 2
> Final cost: 0.02915646 ETH
```
If migrate works, try running the tests

```
cd acceptance-tests/simple-permissioning-smart-contract
truffle test
```
* Output should look something like:
```
Using network 'development'.

Compiling ./contracts/SimplePermissioning.sol...


Contract: Permissioning Ipv4
Function: permissioning Ipv4
✓ Should NOT permit any node when none have been added (75ms)
✓ Should compute key (71ms)
✓ Should add a node to the whitelist and then permit that node (223ms)
✓ Should allow a connection between 2 added nodes
✓ Should remove a node from the whitelist and then NOT permit that node (91ms)

Contract: Permissioning Ipv6
Function: permissioning Ipv6
✓ Should NOT permit any node when none have been added (79ms)
✓ Should compute key (66ms)
✓ Should add a node to the whitelist and then permit that node (165ms)
✓ Should allow a connection between 2 added nodes
✓ Should remove a node from the whitelist and then NOT permit that node (103ms)


10 passing (1s)
```
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
pragma solidity ^0.4.24;
pragma solidity ^0.5.0;

contract Migrations {
address public owner;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
pragma solidity >=0.4.0 <0.6.0;
// THIS CONTRACT IS FOR TESTING PURPOSES ONLY
// DO NOT USE THIS CONTRACT IN PRODUCTION APPLICATIONS

contract SimplePermissioning {
struct EnodeIpv6 {
bytes32 enodeHigh;
bytes32 enodeLow;
bytes16 enodeHost; // Ipv6
uint16 enodePort;
}
struct EnodeIpv4 {
bytes32 enodeHigh;
bytes32 enodeLow;
bytes4 enodeHost; // Ipv4
uint16 enodePort;
}
mapping(bytes => EnodeIpv6) private whitelistIpv6; // should there be a size for the whitelists?
mapping(bytes => EnodeIpv4) private whitelistIpv4;

function connectionAllowedIpv6(
bytes32 sourceEnodeHigh, bytes32 sourceEnodeLow, bytes16 sourceEnodeIpv6, uint16 sourceEnodePort,
bytes32 destinationEnodeHigh, bytes32 destinationEnodeLow, bytes16 destinationEnodeIpv6, uint16 destinationEnodePort)
public view returns (bool) {
return (enodeAllowedIpv6(sourceEnodeHigh, sourceEnodeLow, sourceEnodeIpv6, sourceEnodePort) &&
enodeAllowedIpv6(destinationEnodeHigh, destinationEnodeLow, destinationEnodeIpv6, destinationEnodePort));
}
function connectionAllowedIpv4(
bytes32 sourceEnodeHigh, bytes32 sourceEnodeLow, bytes4 sourceEnodeIpv4, uint16 sourceEnodePort,
bytes32 destinationEnodeHigh, bytes32 destinationEnodeLow, bytes4 destinationEnodeIpv4, uint16 destinationEnodePort)
public view returns (bool){
return (enodeAllowedIpv4(sourceEnodeHigh, sourceEnodeLow, sourceEnodeIpv4, sourceEnodePort) &&
enodeAllowedIpv4(destinationEnodeHigh, destinationEnodeLow, destinationEnodeIpv4, destinationEnodePort));
}
function enodeAllowedIpv6(bytes32 sourceEnodeHigh, bytes32 sourceEnodeLow, bytes16 sourceEnodeIpv6, uint16 sourceEnodePort)
public view returns (bool){
bytes memory key = computeKeyIpv6(sourceEnodeHigh, sourceEnodeLow, sourceEnodeIpv6, sourceEnodePort);
EnodeIpv6 storage whitelistSource = whitelistIpv6[key];
if (whitelistSource.enodeHost > 0) {
return true;
}
}
function enodeAllowedIpv4(bytes32 sourceEnodeHigh, bytes32 sourceEnodeLow, bytes4 sourceEnodeIpv4, uint16 sourceEnodePort)
public view returns (bool){
bytes memory key = computeKeyIpv4(sourceEnodeHigh, sourceEnodeLow, sourceEnodeIpv4, sourceEnodePort);
EnodeIpv4 storage whitelistSource = whitelistIpv4[key];
if (whitelistSource.enodeHost > 0) {
return true;
}
}
function addEnodeIpv6(bytes32 enodeHigh, bytes32 enodeLow, bytes16 enodeIpv6, uint16 enodePort) public {
EnodeIpv6 memory newEnode = EnodeIpv6(enodeHigh, enodeLow, enodeIpv6, enodePort);
bytes memory key = computeKeyIpv6(enodeHigh, enodeLow, enodeIpv6, enodePort);
whitelistIpv6[key] = newEnode;
}
function addEnodeIpv4(bytes32 enodeHigh, bytes32 enodeLow, bytes4 enodeIpv4, uint16 enodePort) public {
EnodeIpv4 memory newEnode = EnodeIpv4(enodeHigh, enodeLow, enodeIpv4, enodePort);
bytes memory key = computeKeyIpv4(enodeHigh, enodeLow, enodeIpv4, enodePort);
whitelistIpv4[key] = newEnode;
}
function removeEnodeIpv6(bytes32 enodeHigh, bytes32 enodeLow, bytes16 enodeIpv6, uint16 enodePort) public {
bytes memory key = computeKeyIpv6(enodeHigh, enodeLow, enodeIpv6, enodePort);
EnodeIpv6 memory zeros = EnodeIpv6(bytes32(0), bytes32(0), bytes16(0), 0);
whitelistIpv6[key] = zeros;
}
function removeEnodeIpv4(bytes32 enodeHigh, bytes32 enodeLow, bytes4 enodeIpv4, uint16 enodePort) public {
bytes memory key = computeKeyIpv4(enodeHigh, enodeLow, enodeIpv4, enodePort);
EnodeIpv4 memory zeros = EnodeIpv4(bytes32(0), bytes32(0), bytes4(0), 0);
whitelistIpv4[key] = zeros;
}
function computeKeyIpv6(bytes32 enodeHigh, bytes32 enodeLow, bytes16 enodeIpv6, uint16 enodePort) public pure returns (bytes memory) {
return abi.encode(enodeHigh, enodeLow, enodeIpv6, enodePort);
}
function computeKeyIpv4(bytes32 enodeHigh, bytes32 enodeLow, bytes4 enodeIpv4, uint16 enodePort) public pure returns (bytes memory) {
return abi.encode(enodeHigh, enodeLow, enodeIpv4, enodePort);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var SimplePermissioning = artifacts.require("SimplePermissioning");

module.exports = function(deployer) {
deployer.deploy(SimplePermissioning);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const TestPermissioning = artifacts.require('SimplePermissioning.sol');
var proxy;

var node1High = "0x9bd359fdc3a2ed5df436c3d8914b1532740128929892092b7fcb320c1b62f375";
var node1Low = "0x892092b7fcb320c1b62f3759bd359fdc3a2ed5df436c3d8914b1532740128929";
var node1Host = "0x9bd359fd";
var node1Port = 30303;

var node2High = "0x892092b7fcb320c1b62f3759bd359fdc3a2ed5df436c3d8914b1532740128929";
var node2Low = "0x892092b7fcb320c1b62f3759bd359fdc3a2ed5df436c3d8914b1532740128929";
var node2Host = "0x9bd359fd";
var node2Port = 30304;

contract('Permissioning Ipv4', () => {
describe('Function: permissioning Ipv4', () => {
it('Should NOT permit any node when none have been added', async () => {
proxy = await TestPermissioning.new();
let permitted = await proxy.enodeAllowedIpv4(node1High, node1Low, node1Host, node1Port);
assert.equal(permitted, false, 'expected node NOT permitted');
});

it('Should compute key', async () => {
let key1 = await proxy.computeKeyIpv4(node1High, node1Low, node1Host, node1Port);
let key2 = await proxy.computeKeyIpv4(node1High, node1Low, node1Host, node1Port);
assert.equal(key1, key2, "computed keys should be the same");

let key3 = await proxy.computeKeyIpv4(node1High, node1Low, node1Host, node2Port);
assert(key3 != key2, "keys for different ports should be different");
});

it('Should add a node to the whitelist and then permit that node', async () => {
await proxy.addEnodeIpv4(node1High, node1Low, node1Host, node1Port);
let permitted = await proxy.enodeAllowedIpv4(node1High, node1Low, node1Host, node1Port);
assert.equal(permitted, true, 'expected node added to be permitted');

// await another
await proxy.addEnodeIpv4(node2High, node2Low, node2Host, node2Port);
permitted = await proxy.enodeAllowedIpv4(node2High, node2Low, node2Host, node2Port);
assert.equal(permitted, true, 'expected node 2 added to be permitted');

// first one still permitted
permitted = await proxy.enodeAllowedIpv4(node1High, node1Low, node1Host, node1Port);
assert.equal(permitted, true, 'expected node 1 added to be permitted');
});

it('Should allow a connection between 2 added nodes', async () => {
let permitted = await proxy.connectionAllowedIpv4(node1High, node1Low, node1Host, node1Port, node2High, node2Low, node2Host, node2Port);
assert.equal(permitted, true, 'expected 2 added nodes to work as source <> destination');
});

it('Should remove a node from the whitelist and then NOT permit that node', async () => {
await proxy.removeEnodeIpv4(node1High, node1Low, node1Host, node1Port);
let permitted = await proxy.enodeAllowedIpv4(node1High, node1Low, node1Host, node1Port);
assert.equal(permitted, false, 'expected removed node NOT permitted');

permitted = await proxy.connectionAllowedIpv4(node1High, node1Low, node1Host, node1Port, node2High, node2Low, node2Host, node2Port);
assert.equal(permitted, false, 'expected source disallowed since it was removed');
});

});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const TestPermissioning = artifacts.require('SimplePermissioning.sol');
var proxy;

var node1High = "0x9bd359fdc3a2ed5df436c3d8914b1532740128929892092b7fcb320c1b62f375";
var node1Low = "0x892092b7fcb320c1b62f3759bd359fdc3a2ed5df436c3d8914b1532740128929";
var node1Host = "0x9bd359fdc3a2ed5df436c3d8914b1532";
var node1Port = 30303;

var node2High = "0x892092b7fcb320c1b62f3759bd359fdc3a2ed5df436c3d8914b1532740128929";
var node2Low = "0x892092b7fcb320c1b62f3759bd359fdc3a2ed5df436c3d8914b1532740128929";
var node2Host = "0x596c3d8914b1532fdc3a2ed5df439bd3";
var node2Port = 30304;

contract('Permissioning Ipv6', () => {
describe('Function: permissioning Ipv6', () => {

it('Should NOT permit any node when none have been added', async () => {
proxy = await TestPermissioning.new();
let permitted = await proxy.enodeAllowedIpv6(node1High, node1Low, node1Host, node1Port);
assert.equal(permitted, false, 'expected node NOT permitted');
});

it('Should compute key', async () => {
let key1 = await proxy.computeKeyIpv6(node1High, node1Low, node1Host, node1Port);
let key2 = await proxy.computeKeyIpv6(node1High, node1Low, node1Host, node1Port);
assert.equal(key1, key2, "computed keys should be the same");

let key3 = await proxy.computeKeyIpv6(node1High, node1Low, node1Host, node2Port);
assert(key3 != key2, "keys for different ports should be different");
});

it('Should add a node to the whitelist and then permit that node', async () => {
await proxy.addEnodeIpv6(node1High, node1Low, node1Host, node1Port);
let permitted = await proxy.enodeAllowedIpv6(node1High, node1Low, node1Host, node1Port);
assert.equal(permitted, true, 'expected node added to be permitted');

// await another
await proxy.addEnodeIpv6(node2High, node2Low, node2Host, node2Port);
permitted = await proxy.enodeAllowedIpv6(node2High, node2Low, node2Host, node2Port);
assert.equal(permitted, true, 'expected node 2 added to be permitted');

// first one still permitted
permitted = await proxy.enodeAllowedIpv6(node1High, node1Low, node1Host, node1Port);
assert.equal(permitted, true, 'expected node 1 added to be permitted');
});

it('Should allow a connection between 2 added nodes', async () => {
let permitted = await proxy.connectionAllowedIpv6(node1High, node1Low, node1Host, node1Port, node2High, node2Low, node2Host, node2Port);
assert.equal(permitted, true, 'expected 2 added nodes to work as source <> destination');
});

it('Should remove a node from the whitelist and then NOT permit that node', async () => {
await proxy.removeEnodeIpv6(node1High, node1Low, node1Host, node1Port);
let permitted = await proxy.enodeAllowedIpv6(node1High, node1Low, node1Host, node1Port);
assert.equal(permitted, false, 'expected removed node NOT permitted');

permitted = await proxy.connectionAllowedIpv6(node1High, node1Low, node1Host, node1Port, node2High, node2Low, node2Host, node2Port);
assert.equal(permitted, false, 'expected source disallowed since it was removed');

});

});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const PrivateKeyProvider = require('truffle-privatekey-provider');
const PrivateKeyProvider = require('truffle-hdwallet-provider');

// address 627306090abaB3A6e1400e9345bC60c78a8BEf57
const privateKey = 'c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3';
Expand Down
Loading