This repository has been archived by the owner on Sep 26, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 130
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PAN-2340] simple permissioning smart contract (#1035)
* replaced truffle pet shop tutorial with Simple Permissioning smart contract and tests
- Loading branch information
Showing
15 changed files
with
333 additions
and
254 deletions.
There are no files selected for viewing
File renamed without changes.
125 changes: 125 additions & 0 deletions
125
acceptance-tests/simple-permissioning-smart-contract/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
acceptance-tests/simple-permissioning-smart-contract/contracts/SimplePermissioning.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
File renamed without changes.
5 changes: 5 additions & 0 deletions
5
acceptance-tests/simple-permissioning-smart-contract/migrations/2_deploy_contracts.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
}; |
61 changes: 61 additions & 0 deletions
61
acceptance-tests/simple-permissioning-smart-contract/test/test-permissioning-ipv4.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | ||
}); | ||
|
||
}); | ||
}); |
63 changes: 63 additions & 0 deletions
63
acceptance-tests/simple-permissioning-smart-contract/test/test-permissioning-ipv6.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | ||
|
||
}); | ||
|
||
}); | ||
}); |
2 changes: 1 addition & 1 deletion
2
...ests/truffle-pet-shop-tutorial/truffle.js → ...e-permissioning-smart-contract/truffle.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.