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

Commit

Permalink
[PAN-2340] simple permissioning smart contract (#1035)
Browse files Browse the repository at this point in the history
* replaced truffle pet shop tutorial with Simple Permissioning smart contract and tests
  • Loading branch information
macfarla authored Mar 5, 2019
1 parent e388b1a commit 89b78c6
Show file tree
Hide file tree
Showing 15 changed files with 333 additions and 254 deletions.
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

0 comments on commit 89b78c6

Please sign in to comment.