├── .travis.yml ├── README.md ├── approvedList ├── dna │ ├── approvedList │ │ ├── addressArray.json │ │ └── approvedList.js │ ├── dna.json │ └── properties_schema.json ├── test │ ├── addressArray.json │ └── benchmark │ │ ├── _config.json │ │ ├── reader.json │ │ └── writer.json └── whitelist │ ├── .babelrc │ ├── .gitignore │ ├── contracts │ ├── HoloWhitelist.sol │ └── Migrations.sol │ ├── migrations │ └── 1_initial_migration.js │ ├── package.json │ ├── test │ ├── holo_whitelist.js │ └── testHelper.js │ ├── truffle-config.js │ └── truffle.js ├── bench.pl ├── benchmark.pl ├── clutter ├── dna │ ├── clutter │ │ ├── anchor.json │ │ ├── clutter.js │ │ └── post.json │ ├── dna.json │ └── properties_schema.json ├── test │ ├── benchmark │ │ ├── _config.json │ │ ├── jane.json │ │ └── joe.json │ ├── follow.json │ ├── handles.json │ ├── posts.json │ ├── properties.json │ └── scaling │ │ ├── _config.json │ │ └── clone.json └── ui │ ├── cat-eating-bird-circle.png │ ├── cats.jpg │ ├── clutter.js │ ├── favicon.png │ ├── hc.js │ ├── index.html │ └── style.css ├── dao ├── README.md ├── dao.sol ├── dna │ ├── congress │ │ ├── completion.json │ │ ├── congress.js │ │ ├── member.json │ │ ├── proposal.json │ │ ├── rules.json │ │ └── vote.json │ ├── dna.json │ ├── owned │ │ └── owned.js │ ├── properties_schema.json │ ├── readme.md │ └── transactions │ │ ├── preauth.json │ │ ├── transaction.json │ │ └── transactions.js ├── ethdao │ ├── .babelrc │ ├── .gitignore │ ├── contracts │ │ ├── Migrations.sol │ │ └── dao.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── package.json │ ├── test │ │ ├── congress.js │ │ └── testHelper.js │ ├── truffle-config.js │ └── truffle.js ├── test │ ├── benchmark │ │ ├── _config.json │ │ ├── implementer.json │ │ ├── owner.json │ │ ├── partya.json │ │ ├── partyb.json │ │ └── readme.md │ ├── member.json │ ├── owned.json │ ├── proposal.json │ ├── rules.json │ └── transaction.json └── ui │ ├── hc.js │ └── index.html └── sorting ├── dna ├── dna.json ├── properties_schema.json └── sortArray │ ├── sortArray.js │ └── sortArray.json ├── ethsort ├── .babelrc ├── .gitignore ├── README.md ├── contracts │ ├── Client.sol │ ├── InsertionSorter.sol │ ├── Migrations.sol │ ├── QuickSorter.sol │ ├── Sorter.sol │ └── WIP.sol ├── migrations │ ├── 1_initial_migration.js │ └── 2_deploy_contracts.js ├── package.json ├── scripts │ └── test.sh ├── test │ ├── sorter.js │ └── testHelper.js └── truffle.js └── test ├── benchmark ├── _config.json ├── reader.json └── sorter.json └── sortArray.json /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: node_js 3 | node_js: 4 | - '8' 5 | services: 6 | - docker 7 | script: 8 | - cd approvedList 9 | - docker run --rm -v "$(pwd):/approvedList" holochain/holochain-proto:develop bash -c "cd /approvedList; hcdev test" 10 | - docker run --rm -v "$(pwd):/approvedList" holochain/holochain-proto:develop bash -c "cd /approvedList; hcdev scenario benchmark" 11 | - cd .. 12 | - cd clutter 13 | - docker run --rm -v "$(pwd):/clutter" holochain/holochain-proto:develop bash -c "cd /clutter; hcdev test" 14 | - docker run --rm -v "$(pwd):/clutter" holochain/holochain-proto:develop bash -c "cd /clutter; hcdev scenario benchmark" 15 | - cd .. 16 | - cd dao 17 | - docker run --rm -v "$(pwd):/dao" holochain/holochain-proto:develop bash -c "cd /dao; hcdev test" 18 | - docker run --rm -v "$(pwd):/dao" holochain/holochain-proto:develop bash -c "cd /dao; hcdev scenario benchmark" 19 | - cd .. 20 | - cd sorting 21 | - docker run --rm -v "$(pwd):/sorting" holochain/holochain-proto:develop bash -c "cd /sorting; hcdev test" 22 | - docker run --rm -v "$(pwd):/sorting" holochain/holochain-proto:develop bash -c "cd /sorting; hcdev scenario benchmark" 23 | -------------------------------------------------------------------------------- /approvedList/dna/approvedList/addressArray.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "addressArray Schema", 3 | "type": "object", 4 | "properties": { 5 | "addresses": { 6 | "type": "object" 7 | } 8 | }, 9 | "required": [ 10 | "addresses" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /approvedList/dna/approvedList/approvedList.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // ----------------------------------------------------------------- 4 | // This stub Zome code file was auto-generated by hc-scaffold 5 | // ----------------------------------------------------------------- 6 | 7 | /** 8 | * Called only when your source chain is generated 9 | * @return {boolean} success 10 | */ 11 | function genesis () { 12 | // any genesis code here 13 | return true; 14 | } 15 | 16 | // ----------------------------------------------------------------- 17 | // validation functions for every DHT entry change 18 | // ----------------------------------------------------------------- 19 | 20 | function validateNewEntry(entryName, entry, header, pkg, sources) { 21 | switch (entryName) { 22 | case "addressArray": 23 | // validation code here 24 | return true; 25 | case "array_links": 26 | return true; 27 | default: 28 | // invalid entry name!! 29 | return false; 30 | } 31 | } 32 | 33 | /** 34 | * Called to validate any changes to the DHT 35 | * @param {string} entryName - the name of entry being modified 36 | * @param {*} entry - the entry data to be set 37 | * @param {?} header - ? 38 | * @param {?} pkg - ? 39 | * @param {?} sources - ? 40 | * @return {boolean} is valid? 41 | */ 42 | function validateCommit (entryName, entry, header, pkg, sources) { 43 | return validateNewEntry(entryName, entry, header, pkg, sources); 44 | } 45 | 46 | /** 47 | * Called to validate any changes to the DHT 48 | * @param {string} entryName - the name of entry being modified 49 | * @param {*} entry - the entry data to be set 50 | * @param {?} header - ? 51 | * @param {?} pkg - ? 52 | * @param {?} sources - ? 53 | * @return {boolean} is valid? 54 | */ 55 | function validatePut (entryName, entry, header, pkg, sources) { 56 | return validateNewEntry(entryName, entry, header, pkg, sources); 57 | } 58 | 59 | /** 60 | * Called to validate any changes to the DHT 61 | * @param {string} entryName - the name of entry being modified 62 | * @param {*} entry - the entry data to be set 63 | * @param {?} header - ? 64 | * @param {*} replaces - the old entry data 65 | * @param {?} pkg - ? 66 | * @param {?} sources - ? 67 | * @return {boolean} is valid? 68 | */ 69 | function validateMod (entryName, entry, header, replaces, pkg, sources) { 70 | switch (entryName) { 71 | case "addressArray": 72 | // validation code here 73 | return false; 74 | default: 75 | // invalid entry name!! 76 | return false; 77 | } 78 | } 79 | 80 | /** 81 | * Called to validate any changes to the DHT 82 | * @param {string} entryName - the name of entry being modified 83 | * @param {string} hash - the hash of the entry to remove 84 | * @param {?} pkg - ? 85 | * @param {?} sources - ? 86 | * @return {boolean} is valid? 87 | */ 88 | function validateDel (entryName, hash, pkg, sources) { 89 | switch (entryName) { 90 | case "addressArray": 91 | // validation code here 92 | return false; 93 | default: 94 | // invalid entry name!! 95 | return false; 96 | } 97 | } 98 | 99 | /** 100 | * Called to validate any changes to the DHT 101 | * @param {?} pkg - ? 102 | * @param {?} sources - ? 103 | * @return {boolean} is valid? 104 | */ 105 | function validateLink (linkEntryType, baseHash, links, pkg, sources) { 106 | switch (linkEntryType) { 107 | case "array_links": 108 | // validation code here 109 | return true; 110 | default: 111 | // invalid entry name!! 112 | return false; 113 | } 114 | } 115 | 116 | /** 117 | * Called to get the data needed to validate 118 | * @param {string} entryName - the name of entry to validate 119 | * @return {*} the data required for validation 120 | */ 121 | function validatePutPkg (entryName) { 122 | return null; 123 | } 124 | 125 | /** 126 | * Called to get the data needed to validate 127 | * @param {string} entryName - the name of entry to validate 128 | * @return {*} the data required for validation 129 | */ 130 | function validateModPkg (entryName) { 131 | return null; 132 | } 133 | 134 | /** 135 | * Called to get the data needed to validate 136 | * @param {string} entryName - the name of entry to validate 137 | * @return {*} the data required for validation 138 | */ 139 | function validateDelPkg (entryName) { 140 | return null; 141 | } 142 | 143 | 144 | // ----------------------------------------------------------------- 145 | // public exposed functions 146 | // ----------------------------------------------------------------- 147 | 148 | /** 149 | * Called to create an addressArray 150 | * @param {mapping} array - the approved address list along with the number of tokens approved 151 | * @return {string} the hash of the new entry 152 | */ 153 | function addressArrayCreate (mapping) { 154 | var hash = commit("addressArray",mapping); 155 | if (!isErr(hash)) { 156 | commit("array_links",{Links:[{Base:App.DNA.Hash,Link:hash,Tag:"array"}]}); 157 | } 158 | return hash; 159 | } 160 | 161 | 162 | /** 163 | * Called to read an addressArray mapping 164 | * @param {hash} string - the particular stored addressArray 165 | * @return {array} the mapping 166 | */ 167 | function addressArrayRead (hash) { 168 | return get(hash); 169 | } 170 | 171 | /** 172 | * Called to get the hash of the first created array 173 | * @return {array} the hash 174 | */ 175 | function getArray() { 176 | var lks = getLinks(App.DNA.Hash,"array"); 177 | if (isErr(lks) || lks.length == 0) { 178 | return ""; 179 | } 180 | return lks[0].Hash; 181 | } 182 | -------------------------------------------------------------------------------- /approvedList/dna/dna.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 1, 3 | "UUID": "570d654d-ad49-49b1-8c02-c2c66c30ff91", 4 | "Name": "approvedList", 5 | "Properties": { 6 | "description": "example approved list for allowing address for an ICO", 7 | "language": "en" 8 | }, 9 | "PropertiesSchemaFile": "properties_schema.json", 10 | "Zomes": [ 11 | { 12 | "Name": "approvedList", 13 | "Description": "", 14 | "Config":{"ErrorHandling":"returnErrorValue"}, 15 | "CodeFile": "approvedList.js", 16 | "Entries": [ 17 | { 18 | "Name": "addressArray", 19 | "DataFormat": "json", 20 | "Schema": "", 21 | "SchemaFile": "addressArray.json", 22 | "Sharing": "public" 23 | }, 24 | { 25 | "Name": "array_links", 26 | "DataFormat": "links" 27 | } 28 | 29 | ], 30 | "RibosomeType": "js", 31 | "Functions": [ 32 | { 33 | "Name": "addressArrayCreate", 34 | "CallingType": "json", 35 | "Exposure": "public" 36 | }, 37 | { 38 | "Name": "addressArrayRead", 39 | "CallingType": "json", 40 | "Exposure": "public" 41 | }, 42 | { 43 | "Name": "addressArrayUpdate", 44 | "CallingType": "json", 45 | "Exposure": "public" 46 | }, 47 | { 48 | "Name": "getArray", 49 | "CallingType": "json", 50 | "Exposure": "public" 51 | } 52 | ], 53 | "BridgeFuncs": null, 54 | "BridgeTo": "" 55 | } 56 | ], 57 | "RequiresVersion": 20, 58 | "DHTConfig": { 59 | "HashType": "sha2-256", 60 | "NeighborhoodSize": 0 61 | }, 62 | "Progenitor": { 63 | "Identity": "", 64 | "PubKey": null 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /approvedList/dna/properties_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Properties Schema", 3 | "type": "object", 4 | "properties": { 5 | "description": { 6 | "type": "string" 7 | }, 8 | "language": { 9 | "type": "string" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /approvedList/test/addressArray.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tests": [ 3 | { 4 | "Convey": "it creates an address array", 5 | "Zome": "approvedList", 6 | "FnName": "addressArrayCreate", 7 | "Input": {"addresses":{ 8 | "xyz":2.5, 9 | "abc":110.3, 10 | "def":99.0 11 | }}, 12 | "Output": "%h1%", 13 | "Exposure": "public" 14 | }, 15 | { 16 | "Convey": "you can read an address array", 17 | "Zome": "approvedList", 18 | "FnName": "addressArrayRead", 19 | "Input": "%h1%", 20 | "Output": {"addresses":{ 21 | "xyz":2.5, 22 | "abc":110.3, 23 | "def":99.0 24 | }}, 25 | "Exposure": "public" 26 | }, 27 | { 28 | "Convey": "and get the address from the DNA", 29 | "Zome": "approvedList", 30 | "FnName": "getArray", 31 | "Input": "", 32 | "Output": "%h1%", 33 | "Exposure": "public" 34 | }, 35 | { 36 | "Convey": "create a 10k sized address array", 37 | "Zome": "approvedList", 38 | "Raw": true, 39 | "Input": "var i=0;var a={};for(i=0;i<10000;i++) {a[makeHash('addressArray',i)]=i+.01};addrs={addresses:a};addressArrayCreate(addrs)", 40 | "Output": "%h1%", 41 | "Benchmark":true 42 | }, 43 | { 44 | "Convey": "check the large array", 45 | "Zome": "approvedList", 46 | "Raw": true, 47 | "Input": "var addrs=addressArrayRead('%h1%');Object.keys(addrs.addresses).length", 48 | "Output": 10000, 49 | "Exposure": "public" 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /approvedList/test/benchmark/_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "GossipInterval": 300, 3 | "Duration": 5, 4 | "Clone": [{ "Role":"reader", "Number":10 }] 5 | } 6 | -------------------------------------------------------------------------------- /approvedList/test/benchmark/reader.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tests": [ 3 | { 4 | "Time":4500, 5 | "Convey": "check the large array", 6 | "Zome": "approvedList", 7 | "Raw": true, 8 | "Input": "var hash=getArray();var addrs=addressArrayRead(hash);Object.keys(addrs.addresses).length", 9 | "Output": 10000, 10 | "Exposure": "public" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /approvedList/test/benchmark/writer.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tests": [ 3 | { 4 | "Convey": "create a 10k sized address array", 5 | "Zome": "approvedList", 6 | "Raw": true, 7 | "Input": "var i=0;var a={};for(i=0;i<10000;i++) {a[makeHash('addressArray',i)]=i+.01};addrs={addresses:a};addressArrayCreate(addrs)", 8 | "Output": "%h1%" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /approvedList/whitelist/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2", "node6"], 3 | "plugins": ["transform-es2015-destructuring"] 4 | } 5 | -------------------------------------------------------------------------------- /approvedList/whitelist/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | build 4 | -------------------------------------------------------------------------------- /approvedList/whitelist/contracts/HoloWhitelist.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | import "zeppelin-solidity/contracts/ownership/Ownable.sol"; 3 | 4 | // This contract holds a mapping of known funders with: 5 | // * a boolean flag for whitelist status 6 | // * number of reserved tokens for each day 7 | contract HoloWhitelist is Ownable { 8 | address public updater; 9 | 10 | struct KnownFunder { 11 | bool whitelisted; 12 | mapping(uint => uint256) reservedTokensPerDay; 13 | } 14 | 15 | mapping(address => KnownFunder) public knownFunders; 16 | 17 | modifier onlyUpdater { 18 | require(msg.sender == updater); 19 | _; 20 | } 21 | 22 | function HoloWhitelist() public { 23 | updater = msg.sender; 24 | } 25 | 26 | function setUpdater(address new_updater) external onlyOwner { 27 | updater = new_updater; 28 | } 29 | 30 | // Adds funders to the whitelist in batches. 31 | function whitelist(address[] funders) external onlyUpdater { 32 | for (uint i = 0; i < funders.length; i++) { 33 | knownFunders[funders[i]].whitelisted = true; 34 | } 35 | } 36 | 37 | // Removes funders from the whitelist in batches. 38 | function unwhitelist(address[] funders) external onlyUpdater { 39 | for (uint i = 0; i < funders.length; i++) { 40 | knownFunders[funders[i]].whitelisted = false; 41 | } 42 | } 43 | 44 | // Stores reserved tokens for several funders in a batch 45 | // but all for the same day. 46 | // * day is 0-based 47 | function setReservedTokens(uint day, address[] funders, uint256[] reservedTokens) external onlyUpdater { 48 | for (uint i = 0; i < funders.length; i++) { 49 | knownFunders[funders[i]].reservedTokensPerDay[day] = reservedTokens[i]; 50 | } 51 | } 52 | 53 | // Used in HoloSale to check if funder is allowed 54 | function isWhitelisted(address funder) external view returns (bool) { 55 | return knownFunders[funder].whitelisted; 56 | } 57 | 58 | // Used in HoloSale to get reserved tokens per funder 59 | // and per day. 60 | // * day is 0-based 61 | function reservedTokens(address funder, uint day) external view returns (uint256) { 62 | return knownFunders[funder].reservedTokensPerDay[day]; 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /approvedList/whitelist/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /approvedList/whitelist/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /approvedList/whitelist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DAO", 3 | "version": "0.0.0", 4 | "description": "Ethereum DAO contracts", 5 | "author": "", 6 | "requires": true, 7 | "lockfileVersion": 1, 8 | "devDependencies": { 9 | "babel-cli": "^6.26.0", 10 | "babel-eslint": "^7.2.3", 11 | "babel-plugin-transform-es2015-destructuring": "^6.23.0", 12 | "babel-preset-es2015": "^6.24.1", 13 | "babel-preset-node6": "^11.0.0", 14 | "babel-preset-stage-2": "^6.24.1", 15 | "babel-register": "^6.24.1", 16 | "bignumber.js": "^4.1.0", 17 | "bluebird": "^3.5.0", 18 | "chai": "^4.1.2", 19 | "chai-http": "^3.0.0", 20 | "coffee-script": "^1.12.7", 21 | "lightsaber": "^0.6.10", 22 | "mocha": "^3.5.2", 23 | "shelljs": "^0.7.8" 24 | }, 25 | "dependencies": { 26 | "zeppelin-solidity": "^1.4.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /approvedList/whitelist/test/holo_whitelist.js: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai' 2 | 3 | const HoloWhitelist = artifacts.require('./HoloWhitelist.sol'); 4 | const debug = false; 5 | 6 | import { 7 | contractShouldThrow, 8 | firstEvent 9 | } from './testHelper' 10 | let a; 11 | 12 | contract('HoloWhitelist', (accounts) => { 13 | a = accounts; 14 | let owner = accounts[0] 15 | let updater = accounts[1] 16 | let funder1 = accounts[2] 17 | let funder2 = accounts[3] 18 | let funder3 = accounts[4] 19 | let funder4 = accounts[5] 20 | let funder5 = accounts[6] 21 | let funder6 = accounts[7] 22 | 23 | let totalGas = 0; 24 | let inc = (receipt) => {if (debug) console.log("gas used: "+receipt.gasUsed);totalGas += receipt.gasUsed;}; 25 | 26 | let instance; 27 | 28 | beforeEach(async () => { 29 | instance = await HoloWhitelist.new(); 30 | 31 | // instance = await HoloWhitelist.deployed() 32 | }); 33 | 34 | describe("benchmarking", () => { 35 | let x; 36 | it('calculate gas costs for per address addition to the whitelist', async() => { 37 | x = await instance.setUpdater(updater); 38 | if (debug) console.log("\nsetUpdater: ",x); 39 | inc(x.receipt); 40 | 41 | let addresses = genAddrs(1); 42 | x = await instance.whitelist(addresses, {from: updater}); 43 | if (debug) console.log("\nwhitelist1: ",x); 44 | inc(x.receipt); 45 | 46 | addresses = genAddrs(2); 47 | let y = await instance.whitelist(addresses, {from: updater}); 48 | if (debug) console.log("\nwhitelist2: ",x); 49 | inc(y.receipt); 50 | 51 | let perAddrGas = y.receipt.gasUsed - x.receipt.gasUsed; 52 | 53 | addresses = genAddrs(3); 54 | x = await instance.whitelist(addresses, {from: updater}); 55 | if (debug) console.log("\nwhitelist3: ",x); 56 | inc(x.receipt); 57 | 58 | let perAddrGas2 = x.receipt.gasUsed - y.receipt.gasUsed; 59 | 60 | console.log("perAddrGas1:",perAddrGas,"perAddrGas2:",perAddrGas2,"(these should be the same)"); 61 | console.log("extrapolated cost of 10k whitelist update:",perAddrGas*10000); 62 | 63 | }); 64 | it('find max number of addresses before block gas limit reached', async() => { 65 | x = await instance.setUpdater(updater); 66 | let addresses = genAddrs(315); 67 | x = await instance.whitelist(addresses, {from: updater}); 68 | if (debug) console.log("\nwhitelist315: ",x); 69 | console.log("\n\nGas Used:"+parseInt(x.receipt.gasUsed)); 70 | }); 71 | contractShouldThrow("on 316 addresses", async () => { 72 | await instance.setUpdater(updater); 73 | let addresses = genAddrs(316); 74 | await instance.whitelist(addresses); 75 | }); 76 | }); 77 | 78 | 79 | 80 | }) 81 | 82 | function genAddr() { 83 | var output = ''; 84 | for (var i = 0; i < 20; i++) { 85 | output += Math.floor(Math.random()*16).toString(16); 86 | } 87 | return "0x"+output; 88 | } 89 | 90 | function genAddrs(n) { 91 | var output = []; 92 | for (var i = 0; i < n; i++) { 93 | output.push(genAddr()); 94 | } 95 | return output; 96 | } 97 | -------------------------------------------------------------------------------- /approvedList/whitelist/test/testHelper.js: -------------------------------------------------------------------------------- 1 | import Promise from 'bluebird' 2 | require('coffee-script/register') 3 | process.env.NODE_ENV = 'test' 4 | 5 | global.Promise = Promise 6 | 7 | export const contractShouldThrow = (description, functionToCall, options, expectedErrorMessage = null) => { 8 | contractIt(description, (done) => { 9 | Promise.resolve().then(functionToCall 10 | ).then(() => { 11 | throw new Error('Expected solidity error to be thrown from contract, but was not') 12 | }).catch((error) => { 13 | expectedErrorMessage = expectedErrorMessage || /VM Exception while processing transaction: revert|VM Exception while processing transaction: invalid opcode/ 14 | if (!error.message || error.message.search(expectedErrorMessage) < 0) throw error 15 | }).then(done).catch(done) 16 | }, options) 17 | } 18 | 19 | export const contractShouldThrowOnly = (description, functionToCall) => { 20 | contractShouldThrow(description, functionToCall, {only: true}) 21 | } 22 | 23 | export const contractShouldThrowIfEtherSent = (functionToCall, opts) => { 24 | contractShouldThrow('should throw an error if ether is sent', functionToCall, opts, 25 | /Cannot send value to non-payable function|VM Exception while processing transaction: invalid opcode|VM Exception while processing transaction: revert/) 26 | } 27 | 28 | export const contractShouldThrowIfEtherSentOnly = (functionToCall) => { 29 | contractShouldThrowIfEtherSent(functionToCall, {only: true}) 30 | } 31 | 32 | export const contractShouldThrowForNonOwner = (functionToCall, opts) => { 33 | contractShouldThrow('should throw an error for non-owner', () => { 34 | return functionToCall() 35 | }, opts) 36 | } 37 | 38 | export const contractShouldThrowForNonOwnerOnly = (functionToCall) => { 39 | contractShouldThrowForNonOwner(functionToCall, {only: true}) 40 | } 41 | 42 | export const contractItOnly = (name, func) => { 43 | contractIt(name, func, {only: true}) 44 | } 45 | 46 | export const contractIt = (name, func, options) => { 47 | options = options || {} 48 | contract('', () => { 49 | describe('Contract:', function() { 50 | this.timeout(3000) 51 | if (options.only) { 52 | it.only(name, func) 53 | } else if (options.pending) { 54 | xit(name, func) 55 | } else { 56 | it(name, func) 57 | } 58 | }) 59 | }) 60 | } 61 | 62 | export const firstEvent = (events) => { 63 | return new Promise((resolve, reject) => { 64 | events.watch((error, log) => { 65 | if (error) { 66 | reject(error) 67 | } else { 68 | events.stopWatching() 69 | resolve(log) 70 | } 71 | }) 72 | }) 73 | } 74 | -------------------------------------------------------------------------------- /approvedList/whitelist/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // See 3 | // to customize your Truffle configuration! 4 | }; 5 | -------------------------------------------------------------------------------- /approvedList/whitelist/truffle.js: -------------------------------------------------------------------------------- 1 | require('babel-register'); 2 | require('babel-polyfill'); 3 | 4 | module.exports = { 5 | // See 6 | // to customize your Truffle configuration! 7 | }; 8 | -------------------------------------------------------------------------------- /bench.pl: -------------------------------------------------------------------------------- 1 | =begin comment 2 | This is a script to sum up benchmark stats reported by different agents via 3 | example usage: 4 | $ cd approvedList 5 | $ hcdev -mdns=true -no-nat-upnp scenario -benchmarks benchmark | perl ../bench.pl 6 | Total chain: 556.23 7 | Total DHT: 6340.86 8 | Total Bytes Sent: 6306.16 9 | Total CPU: 3700 10 | 11 | =end comment 12 | =cut 13 | 14 | 15 | $| = 1; 16 | my $chain = 0.0; 17 | my $dht = 0.0; 18 | my $net = 0.0; 19 | my $gossip = 0.0; 20 | my $cpu = 0.0; 21 | foreach $line ( ) { 22 | # print $line; 23 | chomp( $line ); 24 | 25 | $chain += $1 if $line =~ /Chain growth: ([0-9.]+)K/; 26 | $dht += $1 if $line =~ /DHT growth: ([0-9.]+)K/; 27 | $net += $1 if $line =~ /BytesSent: ([0-9.]+)K/; 28 | $gossip += $1 if $line =~ /GossipSent: ([0-9.]+)K/; 29 | $cpu += $1 if $line =~ /CPU: ([0-9.]+)ms/; 30 | } 31 | 32 | print "Total chain: ${chain}K\n"; 33 | print "Total DHT: ${dht}K\n"; 34 | print "Total Bytes Sent: ${net}K\n"; 35 | print "Total Gossip Sent: ${gossip}K\n"; 36 | print "Total CPU: ${cpu}ms\n"; 37 | -------------------------------------------------------------------------------- /benchmark.pl: -------------------------------------------------------------------------------- 1 | =begin comment 2 | This is a script to run the benchmark a number of times and average the results 3 | example usage: 4 | $ cd approvedList 5 | $ perl ../bench.pl 6 | Total chain: 556.23 7 | Total DHT: 6340.86 8 | Total Bytes Sent: 6306.16 9 | Total CPU: 3700 10 | 11 | =end comment 12 | =cut 13 | 14 | 15 | sub run { 16 | 17 | my $x = `hcdev -mdns=true -no-nat-upnp scenario -benchmarks benchmark`; 18 | 19 | my @lines = split /\n/,$x; 20 | my $chain = 0.0; 21 | my $dht = 0.0; 22 | my $net = 0.0; 23 | my $gossip = 0.0; 24 | my $cpu = 0.0; 25 | foreach $line (@lines) { 26 | # print $line; 27 | # chomp( $line ); 28 | 29 | $chain += $1 if $line =~ /Chain growth: ([0-9.]+)K/; 30 | $dht += $1 if $line =~ /DHT growth: ([0-9.]+)K/; 31 | $net += $1 if $line =~ /BytesSent: ([0-9.]+)K/; 32 | $gossip += $1 if $line =~ /GossipSent: ([0-9.]+)K/; 33 | $cpu += $1 if $line =~ /CPU: ([0-9.]+)ms/; 34 | } 35 | my %values; 36 | $values{'chain'} = $chain; 37 | $values{'dht'} = $dht; 38 | $values{'net'} = $net; 39 | $values{'gossip'} = $gossip; 40 | $values{'cpu'} = $cpu; 41 | return \%values; 42 | } 43 | 44 | my $count = 10; 45 | my @runs; 46 | foreach my $i (0..$count-1) { 47 | $runs[$i] = &run(); 48 | } 49 | 50 | my $chain = 0.0; 51 | my $dht = 0.0; 52 | my $net = 0.0; 53 | my $gossip = 0.0; 54 | my $cpu = 0.0; 55 | 56 | foreach my $i (0..$count-1) { 57 | my $values = $runs[$i]; 58 | $chain += $values->{'chain'}; 59 | $dht += $values->{'dht'}; 60 | $net += $values->{'net'}; 61 | $gossip += $values->{'gossip'}; 62 | $cpu += $values->{'cpu'}; 63 | } 64 | 65 | $chain /= $count; 66 | $dht /= $count; 67 | $net /= $count; 68 | $gossip /= $count; 69 | $cpu /= $count; 70 | 71 | print "Total chain: ${chain}K\n"; 72 | print "Total DHT: ${dht}K\n"; 73 | print "Total Bytes Sent: ${net}K\n"; 74 | print "Total Gossip Sent: ${gossip}K\n"; 75 | print "Total CPU: ${cpu}ms\n"; 76 | -------------------------------------------------------------------------------- /clutter/dna/clutter/anchor.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Anchor Schema", 3 | "type": "object", 4 | "properties": { 5 | "type": { 6 | "type": "string" 7 | }, 8 | "value": { 9 | "type": "string" 10 | } 11 | }, 12 | "required": ["type","value"] 13 | } 14 | -------------------------------------------------------------------------------- /clutter/dna/clutter/clutter.js: -------------------------------------------------------------------------------- 1 | // ============================================================================== 2 | // EXPOSED Functions: visible to the UI, can be called via localhost, web browser, or socket 3 | // =============================================================================== 4 | 5 | function getProperty(name) { // The definition of the function you intend to expose 6 | return property(name); // Retrieves a property of the holochain from the DNA (e.g., Name, Language 7 | } 8 | 9 | 10 | function appProperty(name) { // The definition of the function you intend to expose 11 | if (name == "App_Agent_Hash") {return App.Agent.Hash;} 12 | if (name == "App_Agent_String") {return App.Agent.String;} 13 | if (name == "App_Key_Hash") {return App.Key.Hash;} 14 | if (name == "App_DNA_Hash") {return App.DNA.Hash;} 15 | return "Error: No App Property with name: " + name; 16 | } 17 | 18 | function follow(userAddress) { 19 | // Expects a userAddress hash of the person you want to follow 20 | var me = getMe(); // Looks up my hash address and assign it to 'me' 21 | 22 | // Commits a new follow entry to my source chain 23 | // On the DHT, puts a link on their hash to my hash as a "follower" 24 | // On the DHT, puts a link on my hash to their hash as a "following" 25 | return commit("follow", 26 | {Links:[ 27 | {Base:userAddress,Link:me,Tag:"follower"}, 28 | {Base:me,Link:userAddress,Tag:"following"} 29 | ]}); 30 | } 31 | 32 | function unfollow(userAddress){ 33 | var me = getMe(); 34 | return commit("unfollow", // On my source chain, commits the unfollow entry 35 | {Links:[ 36 | {Base:userAddress,Link:me,Tag:"follower",LinkAction:HC.LinkAction.Del}, 37 | {Base:me,Link:userAddress,Tag:"following",LinkAction:HC.LinkAction.Del} 38 | ]}); 39 | } 40 | 41 | function post(post) { 42 | var key = commit("post",post); // Commits the post block to my source chain, assigns resulting hash to 'key' 43 | var me = getMe(); // Looks up my hash address and assign it to 'me' 44 | // which DHT nodes will use to request validation info from my source chain 45 | 46 | // On the DHT, puts a link on my hash to the new post 47 | commit("post_links",{Links:[{Base:me,Link:key,Tag:"post"}]}); 48 | 49 | debug("meta: "+JSON.stringify(getLinks(me,"post",{Load:true}))); 50 | debug(key); 51 | return key; // Returns the hash key of the new post to the calling function 52 | } 53 | 54 | function postMod(params) { 55 | var hash = params.hash; 56 | var post = params.post; 57 | // TODO, update the original link too? 58 | return update("post",post,hash); 59 | } 60 | 61 | function getPost(params) { 62 | var post, rawPost = get(params.postHash, {GetMask:HC.GetMask.All}); 63 | if (isErr(rawPost) || rawPost === HC.HashNotFound || rawPost.EntryType != "post") { 64 | return null; 65 | } 66 | 67 | post = { 68 | post: rawPost.Entry, 69 | author: rawPost.Sources[0], 70 | H: params.postHash 71 | }; 72 | return post; 73 | } 74 | 75 | // TODO add "last 10" or "since timestamp" when query info is supported 76 | function getPostsBy(userAddresses) { 77 | // From the DHT, gets all "post" metadata entries linked from this userAddress 78 | var posts = []; 79 | for (var i=0;i= 0) { 112 | var oldKey = handles[n]; 113 | var key = update("handle",handle,oldKey); 114 | 115 | debug("new handle: "+handle+" is "+key); 116 | debug("old handle: was "+oldKey); 117 | commit("handle_links", 118 | {Links:[ 119 | {Base:me,Link:oldKey,Tag:"handle",LinkAction:HC.LinkAction.Del}, 120 | {Base:me,Link:key,Tag:"handle"} 121 | ]}); 122 | commit("directory_links", 123 | {Links:[ 124 | {Base:directory,Link:oldKey,Tag:"handle",LinkAction:HC.LinkAction.Del}, 125 | {Base:directory,Link:key,Tag:"handle"} 126 | ]}); 127 | return key; 128 | } 129 | return addHandle(handle); 130 | } 131 | 132 | // returns the handle of an agent by looking it up on the user's DHT entry, the last handle will be the current one? 133 | function getHandle(userHash) { 134 | var handles = doGetLinkLoad(userHash,"handle"); 135 | var n = handles.length -1; 136 | var h = handles[n]; 137 | return (n >= 0) ? h.handle : ""; 138 | } 139 | 140 | // returns the agent associated agent by converting the handle to a hash 141 | // and getting that hash's source from the DHT 142 | function getAgent(handle) { 143 | var directory = getDirectory(); 144 | var handleHash = makeHash("handle",handle); 145 | var sources = get(handleHash,{GetMask:HC.GetMask.Sources}); 146 | if (isErr(sources)) {debug(sources);sources = [];} 147 | if (sources != undefined) { 148 | var n = sources.length -1; 149 | return (n >= 0) ? sources[n] : ""; 150 | } 151 | return ""; 152 | } 153 | 154 | // ============================================================================== 155 | // HELPERS: unexposed functions 156 | // ============================================================================== 157 | 158 | 159 | // helper function to resolve which has will be used as "me" 160 | function getMe() {return App.Key.Hash;} 161 | 162 | // helper function to resolve which hash will be used as the base for the directory 163 | // currently we just use the DNA hash as our entry for linking the directory to 164 | // TODO commit an anchor entry explicitly for this purpose. 165 | function getDirectory() {return App.DNA.Hash;} 166 | 167 | 168 | // helper function to actually commit a handle and its links on the directory 169 | // this function gets called at genesis time only because all other times handle gets 170 | // updated using newHandle 171 | function addHandle(handle) { 172 | // TODO confirm no collision 173 | var key = commit("handle",handle); // On my source chain, commits a new handle entry 174 | var me = getMe(); 175 | var directory = getDirectory(); 176 | 177 | debug(handle+" is "+key); 178 | 179 | commit("handle_links", {Links:[{Base:me,Link:key,Tag:"handle"}]}); 180 | commit("directory_links", {Links:[{Base:directory,Link:key,Tag:"handle"}]}); 181 | 182 | return key; 183 | } 184 | 185 | // helper function to do getLinks call, handle the no-link error case, and copy the returned entry values into a nicer array 186 | function doGetLinkLoad(base, tag) { 187 | // get the tag from the base in the DHT 188 | var links = getLinks(base, tag,{Load:true}); 189 | if (isErr(links)) { 190 | return links; 191 | } else { 192 | links = links; 193 | } 194 | var links_filled = []; 195 | for (var i=0;i ' 227 | // =============================================================================== 228 | function genesis() { // 'hc gen chain' calls the genesis function in every zome file for the app 229 | 230 | // use the agent string (usually email) used with 'hc init' to identify myself and create a new handle 231 | //addHandle(App.Agent.String); 232 | //commit("anchor",{type:"sys",value:"directory"}); 233 | return true; 234 | } 235 | 236 | // =============================================================================== 237 | // VALIDATION functions for *EVERY* change made to DHT entry - 238 | // Every DHT node uses their own copy of these functions to validate 239 | // any and all changes requested before accepting. put / mod / del & metas 240 | // =============================================================================== 241 | 242 | function validateCommit(entry_type,entry,header,pkg,sources) { 243 | debug("validate commit: "+entry_type); 244 | return validate(entry_type,entry,header,sources); 245 | } 246 | 247 | function validatePut(entry_type,entry,header,pkg,sources) { 248 | debug("validate put: "+entry_type); 249 | return validate(entry_type,entry,header,sources); 250 | } 251 | 252 | function validate(entry_type,entry,header,sources) { 253 | if (entry_type=="post") { 254 | var l = entry.message.length; 255 | if (l>0 && l<256) {return true;} 256 | return false; 257 | } 258 | if (entry_type=="handle") { 259 | return true; 260 | } 261 | if (entry_type=="follow") { 262 | return true; 263 | } 264 | return true; 265 | } 266 | 267 | // Are there types of tags that you need special permission to add links? 268 | // Examples: 269 | // - Only Bob should be able to make Bob a "follower" of Alice 270 | // - Only Bob should be able to list Alice in his people he is "following" 271 | function validateLink(linkEntryType,baseHash,links,pkg,sources){ 272 | // debug("validate link: "+linkEntryType); 273 | if (linkEntryType=="handle_links") { 274 | var length = links.length; 275 | // a valid handle is when: 276 | 277 | // there should just be one or two links only 278 | if (length==2) { 279 | // if this is a modify it will have two links the first of which 280 | // will be the del and the second the new link. 281 | if (links[0].LinkAction != HC.LinkAction.Del) return false; 282 | if (links[1].LinkAction != HC.LinkAction.Add) return false; 283 | } else if (length==1) { 284 | // if this is a new handle, there will just be one Add link 285 | if (links[0].LinkAction != HC.LinkAction.Add) return false; 286 | } else {return false;} 287 | 288 | for (var i=0;i img\").toggleClass(\"spin\", true);","successPreResult":"Clutter.noOp=true;","successPostResult":"$(\".logo > img\").toggleClass(\"spin\", false);"}, 11 | "manual":{"clearUI":"$(\".spinner\").toggleClass(\"show\", false);","normalUI":"$(\".spinner\").toggleClass(\"show\", false);"}, 12 | "getHandle":{"preSendHook":"$(\"#changeHandleButton\").toggleClass(\"colorCycle\", true);","successPreResult":"Clutter.noOp=true;","successPostResult":"$(\"#changeHandleButton\").toggleClass(\"colorCycle\", false);"}, 13 | "getFollow":{"preSendHook":"$('#followButton').toggleClass('colorCycle', true);","successPreResult":"Clutter.noOp=true;","successPostResult":"$('#followButton').toggleClass('colorCycle', false);"}, 14 | 15 | }, 16 | "getHook": 17 | (functionName, hookName) => 18 | { if (!Clutter.functionSpecDict.hasOwnProperty(functionName)) 19 | { Clutter.functionSpecDict[functionName] = {}; 20 | } 21 | if (!Clutter.functionSpecDict[functionName].hasOwnProperty(hookName)) 22 | { Clutter.functionSpecDict[functionName][hookName] = ""; 23 | } 24 | return Clutter.functionSpecDict[functionName][hookName]; 25 | }, 26 | }; 27 | console.log("type 'Clutter.debug=true' into the console to see messages back and forth to the server. 'Clutter.debug=false' to stop"); 28 | 29 | var App = {posts:{},users:{},handles:{},follows:{},handle:"",me:""}; 30 | 31 | function getHandle(who,callbackFn) { 32 | send("getHandle",who,function(handle) { 33 | cacheUser({handle:handle,hash:who}); 34 | if (callbackFn!=undefined) { 35 | callbackFn(who,handle); 36 | } 37 | }); 38 | } 39 | 40 | function getMyHandle(callbackFn) { 41 | getHandle(App.me,function(hash,handle){ 42 | if (handle != "") { 43 | App.handle = handle; 44 | $("#handle").html(handle); 45 | if (callbackFn!=undefined) { 46 | callbackFn(); 47 | } 48 | } else { 49 | openSetHandle(); 50 | } 51 | }); 52 | } 53 | 54 | function getFollow(who,type,callbackFn) { 55 | send("getFollow",JSON.stringify({from:who,type:type}),function(data) { 56 | var j = JSON.parse(data); 57 | var following = j.result; 58 | if (following != undefined) { 59 | var len = following.length; 60 | for (var i = 0; i < len; i++) { 61 | cacheFollow(following[i]); 62 | } 63 | if (callbackFn!=undefined) { 64 | callbackFn(); 65 | } 66 | } 67 | }); 68 | } 69 | 70 | function getProfile() { 71 | send("appProperty","App_Key_Hash", function(me) { 72 | App.me = me; 73 | getMyHandle(); 74 | getFollow(me,"following",getMyFeed); 75 | }); 76 | } 77 | 78 | function addPost() { 79 | var now = new(Date); 80 | var post = { 81 | message:$('#meow').val(), 82 | stamp: now.valueOf() 83 | }; 84 | message:$('#meow').val('') 85 | send("post",JSON.stringify(post),function(data) { 86 | post.key = JSON.parse(data); // save the key of our post to the post 87 | post.author = App.me; 88 | var id = cachePost(post); 89 | $("#meows").prepend(makePostHTML(id,post,App.handle)); 90 | }); 91 | } 92 | 93 | function doEditPost() { 94 | var now = new(Date); 95 | var id = $('#postID').val(); 96 | var post = { 97 | message:$('#editedMessage').val(), 98 | stamp: now.valueOf() 99 | }; 100 | $('#editPostDialog').modal('hide'); 101 | send("postMod",JSON.stringify({hash:App.posts[id].key,post:post}),function(data) { 102 | post.key = JSON.parse(data); // save the key of our post to the post 103 | post.author = App.me; 104 | $("#"+id).remove(); 105 | id = cachePost(post); 106 | $("#meows").prepend(makePostHTML(id,post,App.handle)); 107 | }); 108 | } 109 | 110 | function follow(w) { 111 | send("follow",w,function(data) { 112 | cacheFollow(w); 113 | }); 114 | } 115 | 116 | function getUserHandle(user) { 117 | var author = App.handles[user]; 118 | var handle; 119 | if (author == undefined) { 120 | handle = user; 121 | } else { 122 | handle = author.handle; 123 | } 124 | return handle; 125 | } 126 | 127 | function makePostHTML(id,post) { 128 | var d = new Date(post.stamp); 129 | var handle = getUserHandle(post.author); 130 | return '
edit
'+d+'
'+handle+'
'+post.message+'
'; 131 | } 132 | 133 | function makeUserHTML(user) { 134 | return '
'+user.handle+'
'; 135 | } 136 | 137 | function makeResultHTML(result) { 138 | var id; 139 | return '
'+result.handle+'
'; 140 | } 141 | 142 | function getUserPosts(user) { 143 | getPosts([user]); 144 | } 145 | 146 | function getMyFeed() { 147 | var users = Object.keys(App.follows); 148 | if (!users.includes(App.me)) { 149 | users.push(App.me); 150 | } 151 | getPosts(users); 152 | } 153 | 154 | function getPosts(by) { 155 | 156 | // check to see if we have the author's handles 157 | for (var i=0;i 0) { 170 | for (var i = 0; i < len; i++) { 171 | var post = arr[i].post; 172 | post.author = arr[i].author; 173 | var id = cachePost(post); 174 | } 175 | } 176 | displayPosts(); 177 | }, 178 | true); 179 | } 180 | 181 | function cachePost(p) { 182 | //console.log("Caching:"+JSON.stringify(p)); 183 | var id = p.stamp; 184 | App.posts[id] = p; 185 | return id; 186 | } 187 | 188 | function cacheUser(u) { 189 | App.users[u.handle] = u; 190 | App.handles[u.hash] = u; 191 | } 192 | 193 | function cacheFollow(f) { 194 | console.log("caching: "+f); 195 | App.follows[f] = true; 196 | } 197 | 198 | function uncacheFollow(f) { 199 | console.log("uncaching: "+f); 200 | delete App.follows[f]; 201 | } 202 | 203 | function makeFollowingHTML(handle) { 204 | return "
"+handle+'
'; 205 | } 206 | 207 | function displayFollowing() { 208 | var handles = []; 209 | var following = Object.keys(App.follows); 210 | var len = following.length; 211 | for (var i = 0; i < len; i++) { 212 | var user = App.handles[following[i]]; 213 | if (user != undefined) { 214 | handles.push(user.handle); 215 | } 216 | } 217 | handles.sort(); 218 | $("#following").html(""); 219 | len = handles.length; 220 | for (i = 0; i < len; i++) { 221 | $("#following").append(makeFollowingHTML(handles[i])); 222 | } 223 | } 224 | 225 | function displayPosts(filter) { 226 | var keys = [], 227 | k, i, len; 228 | 229 | for (k in App.posts) { 230 | if (filter != undefined) { 231 | if (filter.includes(App.posts[k].handle)) { 232 | keys.push(k); 233 | } 234 | } else { 235 | keys.push(k); 236 | } 237 | } 238 | 239 | keys.sort().reverse(); 240 | 241 | len = keys.length; 242 | 243 | $("#meows").html(""); 244 | for (i = 0; i < len; i++) { 245 | k = keys[i]; 246 | var post = App.posts[k]; 247 | $("#meows").append(makePostHTML(k,post)); 248 | } 249 | } 250 | 251 | function doFollow() { 252 | var handle = $("#followHandle").val(); 253 | 254 | send("getAgent",handle,function(data) { 255 | if (data != "") { 256 | follow(data); 257 | } 258 | else { 259 | alert(handle+" not found"); 260 | } 261 | $('#followDialog').modal('hide'); 262 | eval(Clutter.getHook("manual", "normalUI")); 263 | }); 264 | } 265 | 266 | function doSearch() { 267 | $('#search-results').fadeIn(); 268 | $("#people-results").html(""); 269 | $("#people-results").append(makeResultHTML({handle:"Bob Smith!"})); 270 | } 271 | 272 | function hideSearchResults() { 273 | $('#search-results').fadeOut(); 274 | } 275 | 276 | function searchTab(tab) { 277 | var tabs = $('.search-results-data'); 278 | var len = tabs.length; 279 | for (i = 0; i < len; i++) { 280 | var t= tabs[i]; 281 | var tj = $(t); 282 | var cur = t.id.split("-")[0]; 283 | var tabj = $("#"+cur+"-tab"); 284 | if (tab == cur) { 285 | tj.slideToggle(); 286 | tabj.addClass('active-tab'); 287 | } 288 | else { 289 | tj.slideToggle(); 290 | tabj.removeClass('active-tab'); 291 | } 292 | } 293 | } 294 | 295 | function doSetHandle() { 296 | var handle = $("#myHandle").val(); 297 | 298 | send("newHandle",handle,function(data) { 299 | if (data != "") { 300 | getMyHandle(); 301 | } 302 | $('#setHandleDialog').modal('hide'); 303 | $(".spinner").toggleClass("show", false); 304 | }); 305 | } 306 | 307 | function openFollow() { 308 | $("#followHandle").val(""); 309 | displayFollowing(); 310 | $('#followDialog').modal('show'); 311 | } 312 | 313 | function openSetHandle() { 314 | $('#myHandle').text(App.handle) 315 | $('#setHandleDialog').modal('show'); 316 | } 317 | 318 | function openEditPost(id) { 319 | $("#editedMessage").val(App.posts[id].message); 320 | $('#postID').val(id); 321 | $('#editPostDialog').modal('show'); 322 | } 323 | 324 | function unfollow(button) { 325 | // pull the handle out from the HTML 326 | var handle = $(button).parent().find('.handle')[0].innerHTML; 327 | var user = App.users[handle].hash; 328 | send("unfollow",user,function(data) { 329 | uncacheFollow(user); 330 | $('#followDialog').modal('hide'); 331 | }); 332 | } 333 | 334 | function showUser(user) { 335 | $('#meow-form').fadeOut(); 336 | $('#user-header').html(getUserHandle(user)); 337 | $('#user-header').fadeIn(); 338 | App.posts={}; 339 | getPosts([user]); 340 | } 341 | 342 | function showFeed() { 343 | $('#meow-form').fadeIn(); 344 | $('#user-header').fadeOut(); 345 | App.posts={}; 346 | getMyFeed(); 347 | } 348 | 349 | $(window).ready(function() { 350 | $("#submitFollow").click(doFollow); 351 | $('#followButton').click(openFollow); 352 | $("#handle").on("click", "", openSetHandle); 353 | $("#changeHandleButton").on("click", "", openSetHandle); 354 | $('#setHandleButton').click(doSetHandle); 355 | $('#search-results.closer').click(hideSearchResults); 356 | $('#user-header').click(showFeed); 357 | $('#editPostButton').click(doEditPost); 358 | 359 | $("#myHandle").on('keyup', function (e) { 360 | if (e.keyCode == 13) { 361 | doSetHandle() 362 | } 363 | }) 364 | 365 | $("#followHandle").on('keyup', function (e) { 366 | if (e.keyCode == 13) { 367 | doFollow(); 368 | } 369 | }) 370 | 371 | getProfile(); 372 | setInterval(getMyFeed, 1000) 373 | 374 | }); 375 | -------------------------------------------------------------------------------- /clutter/ui/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/holochain/benchmarks/a11811dafe5f9f95b5457186788865f2a28307d8/clutter/ui/favicon.png -------------------------------------------------------------------------------- /clutter/ui/hc.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2013-2017, The MetaCurrency Project (Eric Harris-Braun & Arthur Brock) 2 | // Use of this source code is governed by GPLv3 found in the LICENSE file 3 | //--------------------------------------------------------------------------------------- 4 | 5 | // Holochain UI library 6 | 7 | // use send to make an ajax call to your exposed functions 8 | function send(fn,data,resultFn) { 9 | if (Clutter.debug) console.log("calling: " + fn+" with "+JSON.stringify(data)); 10 | 11 | eval(Clutter.getHook(fn, "preSendHook")); 12 | $.post( 13 | "/fn/clutter/"+fn, 14 | data, 15 | function(response) { 16 | if (Clutter.debug) console.log("response: " + response); 17 | eval(Clutter.getHook(fn, "successPreResult")); 18 | resultFn(response); 19 | eval(Clutter.getHook(fn, "successPostResult")); 20 | } 21 | ).error(function(response) { 22 | console.log("response failed: " + response.responseText); 23 | $(".error").html("" + response.responseText + "").toggleClass("show", true) 24 | setTimeout 25 | ( () => 26 | { $(".error") .toggleClass("show", false); 27 | eval(Clutter.getHook(fn, "errorTimeoutComplete")); 28 | }, 29 | 2000 30 | ); 31 | }) 32 | ; 33 | }; 34 | -------------------------------------------------------------------------------- /clutter/ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Clutter 15 | 16 | 17 |
18 |
19 |
20 |
21 | 24 |
25 |
26 |
27 |
28 | 29 | 30 |
31 | 32 | 35 |
36 | 37 |
38 | 39 | 40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 49 | 53 | 54 | 63 | 64 |
65 |

What is Clutter?

66 |

A clutter is a flock of cats.

67 |

Clutter is a fully decentralized alternative to Twitter.

68 |

Impossible to censor or control.

69 |

Join the mewvolution on holochain.org.

70 |
71 |
72 |
73 |
74 | 75 | 76 | 99 | 100 | 119 | 120 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /clutter/ui/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | } 3 | 4 | @font-face { 5 | font-family: Palatino; 6 | src: local("Palatino"); 7 | src: url("pala.ttf"); 8 | } 9 | 10 | body { 11 | /* font-family: 'Share Tech Mono', fixed; 12 | font-size: 0.9em;*/ 13 | line-height: 1.3em; 14 | height: 100%;/ 15 | background-color: black; 16 | background-image: url("cats.jpg"); 17 | background-size: 100% auto; 18 | width: calc(100vw - 34px); /* Prevent jump from scrollbar appearing on only some pages */ 19 | padding-left: 9px; /* Recenter page from scrollbar width adjustment */ 20 | } 21 | 22 | .row { 23 | margin-top: 1em; 24 | } 25 | #container { 26 | margin: 0; 27 | width: 100%; 28 | padding: 0; 29 | } 30 | 31 | #changeHandleButton { 32 | float: left; 33 | margin: 8px; 34 | } 35 | 36 | #followButton { 37 | float: right; 38 | margin: 8px; 39 | } 40 | 41 | #meow { 42 | margin: 10px; 43 | } 44 | 45 | p { 46 | margin-top: 0; 47 | } 48 | 49 | h1 { 50 | font-family: "Play"; 51 | font-size: 1.6em; 52 | margin-top: 0; 53 | text-align: center; 54 | } 55 | 56 | h2 { 57 | font-family: "Play"; 58 | font-size: 1.25em; 59 | margin-bottom: 0.75em; 60 | margin-top: 0.9em; 61 | text-align: center; 62 | } 63 | 64 | h3 { 65 | margin-top: 0; 66 | font-size: 1.15em; 67 | margin-bottom: 0.5em; 68 | clear: none; 69 | } 70 | 71 | h4 { 72 | font-size: 1.05em; 73 | margin-top: 0em; 74 | padding:0; 75 | margin-bottom: 0.25em; 76 | font-family: "Play"; 77 | } 78 | 79 | a:link { 80 | color: #a35f1a; 81 | } 82 | 83 | a:visited { 84 | color: #a35f1a; 85 | } 86 | 87 | ul { 88 | margin-top: -0.25em; 89 | } 90 | 91 | ul li { 92 | text-indent: -1.25em; 93 | padding-left: 1.25em; 94 | } 95 | 96 | #header { 97 | height: 1.36em; 98 | padding: 0.8em; 99 | } 100 | 101 | #banner { 102 | padding-right: 1em; 103 | padding-left: 1em; 104 | padding-top: 0.4em; 105 | width: auto; 106 | /* text-shadow: -3px 5px 8px #000000; */ 107 | margin: 0 0em 0.18em 0em; 108 | font-family: "Griffy"; 109 | font-size: 3.7em; 110 | text-align: center; 111 | line-height: 1.1em; 112 | display: block; 113 | color: white; 114 | background: url("calico2.png") no-repeat no-repeat stretch; 115 | -webkit-background-clip: text; 116 | } 117 | 118 | .alphabox { 119 | padding: 1em; 120 | border-radius: 8px; 121 | background-color: rgba(0, 0, 0, 0.6); 122 | } 123 | 124 | .logo { 125 | margin-bottom: 1em; 126 | text-align: center; 127 | } 128 | 129 | #about { 130 | color: white; 131 | } 132 | 133 | a#handle { 134 | display:block; 135 | //background-color: rgba(0, 0, 0, 0.6); 136 | text-align:center; 137 | color:white; 138 | } 139 | 140 | .subtitle { 141 | font-size: 0.3em; 142 | font-style: italic; 143 | padding-top: 0em; 144 | padding-bottom: 0.5em; 145 | margin-bottom: 0.5em; 146 | text-align: center; 147 | letter-spacing: 0.25px; 148 | line-height: normal; 149 | color: #ccc; 150 | font-family: Palatino; 151 | } 152 | 153 | .current { 154 | color: #4E99FF; 155 | text-decoration: none; 156 | background-color: rgba(80, 50, 255, 0.30); 157 | padding-top: 2em; 158 | text-shadow: 2px 2px 4px #000; 159 | } 160 | 161 | #footer { 162 | text-align: center; 163 | font-size: 1em; 164 | margin-top: 0.5em; 165 | } 166 | 167 | .rightcolumn { 168 | font-size: 1.2em; 169 | line-height: 1.4; 170 | min-width: 10em; 171 | } 172 | 173 | #leftfloat { 174 | float: left; 175 | width: 16em; 176 | line-height: 1.6em; 177 | font-size: 1.25em; 178 | margin: 1em 1em 1em 3em; 179 | } 180 | 181 | #leftfloat p { 182 | text-align: justify; 183 | text-indent: 15px; 184 | } 185 | 186 | .contentcontainer { 187 | border-radius: 18px; 188 | background-color: rgba(0, 0, 0, 0.6); 189 | margin-bottom: 1em; 190 | 191 | } 192 | 193 | #content { 194 | font-size: 1.15em; 195 | line-height: 1.4; 196 | overflow: hidden; 197 | } 198 | 199 | #content p { 200 | text-indent: 2.4em; 201 | margin-bottom: 1.25em; 202 | } 203 | 204 | blockquote { 205 | font-style: italic; 206 | margin: 0em 25px 1em 25px; 207 | padding: 1em; 208 | border-radius: 15px; 209 | background-color: rgba(40, 40, 40, 0.5); 210 | } 211 | 212 | #content blockquote p { 213 | margin-bottom: 0; 214 | } 215 | 216 | .right { 217 | float: right; 218 | } 219 | 220 | 221 | 222 | /* GO FULL WIDTH BELOW 480 PIXELS */ 223 | @media only screen and (max-width: 480px) { 224 | .col { margin: 1% 0 1% 0%; } 225 | 226 | .span_1_of_12, .span_2_of_12, .span_3_of_12, .span_4_of_12, .span_5_of_12, .span_6_of_12, .span_7_of_12, .span_8_of_12, .span_9_of_12, .span_10_of_12, .span_11_of_12, .span_12_of_12 { 227 | width: 100%; 228 | } 229 | } 230 | 231 | .meow { 232 | margin: 1em; 233 | padding: 0.75em; 234 | background-color: rgba(0, 0, 0, 0.6); 235 | border-radius: 10px; 236 | color: wheat; 237 | } 238 | .meow-edit { 239 | display: none; 240 | } 241 | .closer { 242 | float:right; 243 | } 244 | .results-tab { 245 | display:inline-block; 246 | background-color:green; 247 | } 248 | .active-tab { 249 | background-color:white; 250 | color:green; 251 | } 252 | 253 | .search-results-data { 254 | background-color: lightgray; 255 | color: black; 256 | padding: 4px; 257 | } 258 | 259 | #user-header { 260 | color:white; 261 | } 262 | 263 | .meow-edit { 264 | float:right; 265 | } 266 | 267 | 268 | .spinner 269 | { display: none; 270 | 271 | position: absolute; 272 | 273 | width: 100%; 274 | height: 100%; 275 | 276 | z-index: 314159; 277 | 278 | background-color: rgba(0,0,0,0.4); 279 | } 280 | .error 281 | { display: none; 282 | 283 | position: absolute; 284 | 285 | width: 30%; 286 | height: 30%; 287 | 288 | z-index: 3141592; 289 | 290 | background-color: rgba(128,0,0,0.3); 291 | } 292 | 293 | /* 294 | TOOLS 295 | */ 296 | .transition500 297 | { transition: all 0.5s ease; 298 | } 299 | 300 | .show 301 | { display: block; 302 | } 303 | .spin 304 | { animation-name: spin; 305 | animation-duration: 4000ms; 306 | animation-iteration-count: infinite; 307 | animation-timing-function: linear; 308 | } 309 | @keyframes spin { 310 | from { 311 | transform: rotate(0deg); 312 | } to { 313 | transform: rotate(360deg); 314 | } 315 | } 316 | 317 | .colorCycle 318 | { animation: color_change 1s infinite alternate; 319 | } 320 | @keyframes color_change { 321 | 0% { background-color: blue; } 322 | 25% { background-color: orange; } 323 | 50% { background-color: yellow; } 324 | 75% { background-color: black; } 325 | 100% { background-color: red; } 326 | } 327 | -------------------------------------------------------------------------------- /dao/README.md: -------------------------------------------------------------------------------- 1 | # HoloDAO 2 | 3 | [![Code Status](https://img.shields.io/badge/Code-Pre--Alpha-orange.svg)](https://github.com/Holochain/dao) 4 | [![In Progress](https://img.shields.io/waffle/label/Holochain/dao/in%20progress.svg)](http://waffle.io/Holochain/dao) 5 | [![Gitter](https://badges.gitter.im/metacurrency/holochain.svg)](https://gitter.im/metacurrency/holochain?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) 6 | [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) 7 | 8 | **A Holochain implementation of the Ethereum example DAO contract** 9 | As part of our benchmarking for [Holo](http://holo.host) we have built a Holochain version of the sample [DAO contract](https://github.com/Holochain/dao/blob/master/dao.sol) from the Ethereum.org website. Comparing Holochain apps to Ethereum smart contracts is a bit like comparing apples and pineapples. Though they are both distributed computing platforms, because of their different starting assumptions, the results are quite difficult to compare. For example, Ethereum comes with a built in transactional layer, which Holochain does not. So in this app we hand-coded a mutual-credit transaction zome to emulate that functionality. 10 | 11 | **[Code Status:](https://github.com/metacurrency/holochain/milestones?direction=asc&sort=completeness&state=all)** Pre-alpha. Not for production use. This application has not been audited for any security validation. 12 | 13 | ## Installation 14 | 15 | Prerequiste: [Install holochain](https://github.com/metacurrency/holochain/#installation) on your machine. 16 | You can install HoloDAO very simply with this: 17 | 18 | ``` shell 19 | hcdev init -cloneExample=dao 20 | 21 | ``` 22 | 23 | ## Usage 24 | 25 | This example has no UI, it's only useful to run from tests. 26 | 27 | ### Tests 28 | To run all the stand alone tests: 29 | 30 | ``` shell 31 | hcdev test 32 | ``` 33 | 34 | Currently there is one scenario test: 35 | 36 | #### benchmark 37 | This scenario spins up an owner node, an implementer node and a bunch of member nodes which create and vote on a bunch of proposals. Finally at the end the implementer executes the proposals. 38 | 39 | ``` shell 40 | hcdev -mdns=true -no-nat-upnp scenario -benchmarks benchmark 41 | 42 | ``` 43 | This will output the detailed benchmark tests including the benchmark data for each node. To see the aggregate benchmark data you can pass the output through the `bench.pl` script like this: 44 | 45 | ``` shell 46 | hcdev -mdns=true -no-nat-upnp scenario -benchmarks benchmark | perl bench.pl 47 | 48 | ``` 49 | Which should result in some output something like: 50 | ``` 51 | Total chain: 45.22 52 | Total DHT: 1287.27 53 | Total Bytes Sent: 7394.64 54 | Total CPU: 20840 55 | ``` 56 | 57 | This repo contains a dao ethereum scenario built as a truffle test to calculate how much gas is used to do a similar amount of computation. To install and run this scenario: 58 | 59 | ``` shell 60 | npm install -g truffle 61 | cd ethdao 62 | npm install 63 | truffle develop 64 | ``` 65 | Then from the truffle command line: 66 | ``` 67 | migrate 68 | test 69 | ``` 70 | This should produce output that ends with the line something like: 71 | 72 | ``` shell 73 | Total Gas Used:6224448 74 | ``` 75 | 76 | ## Contribute 77 | We welcome pull requests and issue tickets. Find us on [gitter](https://gitter.im/metacurrency/holochain) to chat. 78 | 79 | Contributors to this project are expected to follow our [development protocols & practices](https://github.com/metacurrency/holochain/wiki/Development-Protocols). 80 | 81 | ## License 82 | [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) 83 | 84 | Copyright (C) 2017, The MetaCurrency Project (Eric Harris-Braun, Arthur Brock, et. al.) 85 | 86 | This program is free software: you can redistribute it and/or modify it under the terms of the license provided in the LICENSE file (GPLv3). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 87 | 88 | **Note:** We are considering other 'looser' licensing options (like MIT license) but at this stage are using GPL while we're getting the matter sorted out. 89 | -------------------------------------------------------------------------------- /dao/dao.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.16; 2 | 3 | contract owned { 4 | address public owner; 5 | 6 | function owned() public { 7 | owner = msg.sender; 8 | } 9 | 10 | modifier onlyOwner { 11 | require(msg.sender == owner); 12 | _; 13 | } 14 | 15 | function transferOwnership(address newOwner) onlyOwner public { 16 | owner = newOwner; 17 | } 18 | } 19 | 20 | contract tokenRecipient { 21 | event receivedEther(address sender, uint amount); 22 | event receivedTokens(address _from, uint256 _value, address _token, bytes _extraData); 23 | 24 | function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public { 25 | Token t = Token(_token); 26 | require(t.transferFrom(_from, this, _value)); 27 | receivedTokens(_from, _value, _token, _extraData); 28 | } 29 | 30 | function () payable public { 31 | receivedEther(msg.sender, msg.value); 32 | } 33 | } 34 | 35 | interface Token { 36 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); 37 | } 38 | 39 | contract Congress is owned, tokenRecipient { 40 | // Contract Variables and events 41 | uint public minimumQuorum; 42 | uint public debatingPeriodInMinutes; 43 | int public majorityMargin; 44 | Proposal[] public proposals; 45 | uint public numProposals; 46 | mapping (address => uint) public memberId; 47 | Member[] public members; 48 | 49 | event ProposalAdded(uint proposalID, address recipient, uint amount, string description); 50 | event Voted(uint proposalID, bool position, address voter, string justification); 51 | event ProposalTallied(uint proposalID, int result, uint quorum, bool active); 52 | event MembershipChanged(address member, bool isMember); 53 | event ChangeOfRules(uint newMinimumQuorum, uint newDebatingPeriodInMinutes, int newMajorityMargin); 54 | 55 | struct Proposal { 56 | address recipient; 57 | uint amount; 58 | string description; 59 | uint votingDeadline; 60 | bool executed; 61 | bool proposalPassed; 62 | uint numberOfVotes; 63 | int currentResult; 64 | bytes32 proposalHash; 65 | Vote[] votes; 66 | mapping (address => bool) voted; 67 | } 68 | 69 | struct Member { 70 | address member; 71 | string name; 72 | uint memberSince; 73 | } 74 | 75 | struct Vote { 76 | bool inSupport; 77 | address voter; 78 | string justification; 79 | } 80 | 81 | // Modifier that allows only shareholders to vote and create new proposals 82 | modifier onlyMembers { 83 | require(memberId[msg.sender] != 0); 84 | _; 85 | } 86 | 87 | /** 88 | * Constructor function 89 | */ 90 | function Congress ( 91 | uint minimumQuorumForProposals, 92 | uint minutesForDebate, 93 | int marginOfVotesForMajority 94 | ) payable public { 95 | changeVotingRules(minimumQuorumForProposals, minutesForDebate, marginOfVotesForMajority); 96 | // It’s necessary to add an empty first member 97 | addMember(0, ""); 98 | // and let's add the founder, to save a step later 99 | addMember(owner, 'founder'); 100 | } 101 | 102 | /** 103 | * Add member 104 | * 105 | * Make `targetMember` a member named `memberName` 106 | * 107 | * @param targetMember ethereum address to be added 108 | * @param memberName public name for that member 109 | */ 110 | function addMember(address targetMember, string memberName) onlyOwner public { 111 | uint id = memberId[targetMember]; 112 | if (id == 0) { 113 | memberId[targetMember] = members.length; 114 | id = members.length++; 115 | } 116 | 117 | members[id] = Member({member: targetMember, memberSince: now, name: memberName}); 118 | MembershipChanged(targetMember, true); 119 | } 120 | 121 | /** 122 | * Remove member 123 | * 124 | * @notice Remove membership from `targetMember` 125 | * 126 | * @param targetMember ethereum address to be removed 127 | */ 128 | function removeMember(address targetMember) onlyOwner public { 129 | require(memberId[targetMember] != 0); 130 | 131 | for (uint i = memberId[targetMember]; i p.votingDeadline // If it is past the voting deadline 283 | && !p.executed // and it has not already been executed 284 | && p.proposalHash == keccak256(p.recipient, p.amount, transactionBytecode) // and the supplied code matches the proposal 285 | && p.numberOfVotes >= minimumQuorum); // and a minimum quorum has been reached... 286 | 287 | // ...then execute result 288 | 289 | if (p.currentResult > majorityMargin) { 290 | // Proposal passed; execute the transaction 291 | 292 | p.executed = true; // Avoid recursive calling 293 | require(p.recipient.call.value(p.amount)(transactionBytecode)); 294 | 295 | p.proposalPassed = true; 296 | } else { 297 | // Proposal failed 298 | p.proposalPassed = false; 299 | } 300 | 301 | // Fire Events 302 | ProposalTallied(proposalNumber, p.currentResult, p.numberOfVotes, p.proposalPassed); 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /dao/dna/congress/completion.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "completion Schema", 3 | "type": "object", 4 | "properties": { 5 | "proposal": { 6 | "type": "string" 7 | }, 8 | "passed": { 9 | "type": "boolean" 10 | } 11 | }, 12 | "required": ["proposal","passed"] 13 | } 14 | -------------------------------------------------------------------------------- /dao/dna/congress/member.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "member Schema", 3 | "type": "object", 4 | "properties": { 5 | "address": { 6 | "type": "string" 7 | }, 8 | "name": { 9 | "type": "string" 10 | }, 11 | "memberSince": { 12 | "type": "string", 13 | "format": "date-time" 14 | } 15 | }, 16 | "required": ["address", "name", "memberSince"] 17 | } 18 | -------------------------------------------------------------------------------- /dao/dna/congress/proposal.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "proposal Schema", 3 | "type": "object", 4 | "properties": { 5 | "description": { 6 | "type": "string" 7 | }, 8 | "recipient": { 9 | "type": "string" 10 | }, 11 | "amount": { 12 | "type": "integer" 13 | }, 14 | "votingDeadline": { 15 | "type": "string", 16 | "format": "date-time" 17 | } 18 | }, 19 | "required": ["description","recipient","amount","votingDeadline"] 20 | } 21 | -------------------------------------------------------------------------------- /dao/dna/congress/rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "rules Schema", 3 | "type": "object", 4 | "properties": { 5 | "minimumQuorum": { 6 | "type": "integer", 7 | "minimum": 1 8 | }, 9 | "debatingPeriodInMinutes": { 10 | "type": "integer", 11 | "minimum": 0 12 | }, 13 | "majorityMargin": { 14 | "type": "integer", 15 | "minimum": 0 16 | } 17 | }, 18 | "required": ["minimumQuorum", "debatingPeriodInMinutes","majorityMargin"] 19 | } 20 | -------------------------------------------------------------------------------- /dao/dna/congress/vote.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "vote Schema", 3 | "type": "object", 4 | "properties": { 5 | "inSupport": { 6 | "type": "boolean" 7 | }, 8 | "proposal": { 9 | "type": "string" 10 | }, 11 | "justification": { 12 | "type": "string" 13 | }, 14 | "voter": { 15 | "type": "string" 16 | } 17 | }, 18 | "required": ["inSupport", "proposal","justification","voter"] 19 | } 20 | -------------------------------------------------------------------------------- /dao/dna/dna.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 1, 3 | "UUID": "1b4400ce-df71-11e7-8f0e-54ee75d2f20c", 4 | "Name": "holodao", 5 | "RequiresVersion": 21, 6 | "DHTConfig": { 7 | "HashType": "sha2-256" 8 | }, 9 | "Properties": { 10 | "description": "holochain equivalent of the Ethereum dao contract", 11 | "language": "en", 12 | "progenitorHash":"QmQXSJoGkwdF2R7Xgc5cJXhKoRRdUKPHLLtTu3VqfGdqoV", 13 | "progenitorIdentity":"the progenitor", 14 | "creditLimit":"500" 15 | }, 16 | "Progenitor": { 17 | "Identity": "the progentior", 18 | "PubKey": [8, 1, 18, 32, 193, 43, 31, 148, 23, 249, 163, 154, 128, 25, 237, 167, 253, 63, 214, 220, 206, 131, 217, 74, 168, 30, 215, 237, 231, 160, 69, 89, 48, 17, 104, 210] 19 | }, 20 | "PropertiesSchemaFile": "properties_schema.json", 21 | "Zomes": [ 22 | { 23 | "Name": "owned", 24 | "Description": "port of owned contract", 25 | "Config":{"ErrorHandling":"returnErrorValue"}, 26 | "CodeFile": "owned.js", 27 | "Entries": [ 28 | { 29 | "Name": "owner_links", 30 | "DataFormat": "links" 31 | } 32 | ], 33 | "RibosomeType": "js", 34 | "Functions": [ 35 | { 36 | "Name": "transferOwnership", 37 | "CallingType": "json", 38 | "Exposure": "public" 39 | }, 40 | { 41 | "Name": "getOwner", 42 | "CallingType": "json", 43 | "Exposure": "public" 44 | } 45 | ] 46 | }, 47 | { 48 | "Name": "congress", 49 | "Description": "port of congress contract", 50 | "Config":{"ErrorHandling":"returnErrorValue"}, 51 | "CodeFile": "congress.js", 52 | "RibosomeType": "js", 53 | "Entries": [ 54 | { 55 | "Name": "proposal", 56 | "DataFormat": "json", 57 | "Sharing": "public", 58 | "SchemaFile": "proposal.json" 59 | }, 60 | { 61 | "Name": "completion", 62 | "DataFormat": "json", 63 | "Sharing": "public", 64 | "SchemaFile": "completion.json" 65 | }, 66 | { 67 | "Name": "member", 68 | "DataFormat": "json", 69 | "Sharing": "public", 70 | "SchemaFile": "member.json" 71 | }, 72 | { 73 | "Name": "vote", 74 | "DataFormat": "json", 75 | "Sharing": "public", 76 | "SchemaFile": "vote.json" 77 | }, 78 | { 79 | "Name": "rules", 80 | "DataFormat": "json", 81 | "Sharing": "public", 82 | "SchemaFile": "rules.json" 83 | }, 84 | { 85 | "Name": "member_links", 86 | "DataFormat": "links" 87 | }, 88 | { 89 | "Name": "proposal_links", 90 | "DataFormat": "links" 91 | }, 92 | { 93 | "Name": "completion_links", 94 | "DataFormat": "links" 95 | }, 96 | { 97 | "Name": "vote_links", 98 | "DataFormat": "links" 99 | }, 100 | { 101 | "Name": "rules_links", 102 | "DataFormat": "links" 103 | }, 104 | { 105 | "Name": "funding_links", 106 | "DataFormat": "links" 107 | } 108 | ], 109 | "Functions": [ 110 | { 111 | "Name": "isMember", 112 | "CallingType": "json", 113 | "Exposure": "public" 114 | }, 115 | { 116 | "Name": "addMember", 117 | "CallingType": "json", 118 | "Exposure": "public" 119 | }, 120 | { 121 | "Name": "getMembers", 122 | "CallingType": "json", 123 | "Exposure": "public" 124 | }, 125 | { 126 | "Name": "removeMember", 127 | "CallingType": "json", 128 | "Exposure": "public" 129 | }, 130 | { 131 | "Name": "newProposal", 132 | "CallingType": "json", 133 | "Exposure": "public" 134 | }, 135 | { 136 | "Name": "getProposals", 137 | "CallingType": "json", 138 | "Exposure": "public" 139 | }, 140 | { 141 | "Name": "changeVotingRules", 142 | "CallingType": "json", 143 | "Exposure": "public" 144 | }, 145 | { 146 | "Name": "getVotingRules", 147 | "CallingType": "json", 148 | "Exposure": "public" 149 | }, 150 | { 151 | "Name": "vote", 152 | "CallingType": "json", 153 | "Exposure": "public" 154 | }, 155 | { 156 | "Name": "getVotes", 157 | "CallingType": "json", 158 | "Exposure": "public" 159 | }, 160 | { 161 | "Name": "votingStatus", 162 | "CallingType": "json", 163 | "Exposure": "public" 164 | }, 165 | { 166 | "Name": "fundProposal", 167 | "CallingType": "json", 168 | "Exposure": "public" 169 | }, 170 | { 171 | "Name": "executeProposal", 172 | "CallingType": "json", 173 | "Exposure": "public" 174 | }, 175 | { 176 | "Name": "proposalExists", 177 | "CallingType": "string", 178 | "Exposure": "public" 179 | }, 180 | { 181 | "Name": "completionExists", 182 | "CallingType": "string", 183 | "Exposure": "public" 184 | } 185 | ] 186 | }, 187 | { 188 | "Name": "transactions", 189 | "Description": "Execution and validation of mutual credit transactions", 190 | "Config":{"ErrorHandling":"returnErrorValue"}, 191 | "CodeFile": "transactions.js", 192 | "Entries": [ 193 | { 194 | "Name": "transaction", 195 | "DataFormat": "json", 196 | "Schema": "", 197 | "SchemaFile": "transaction.json", 198 | "Sharing": "public" 199 | }, 200 | { 201 | "Name": "preauth", 202 | "DataFormat": "json", 203 | "Schema": "", 204 | "SchemaFile": "preauth.json", 205 | "Sharing": "public" 206 | } 207 | ], 208 | "RibosomeType": "js", 209 | "Functions": [ 210 | { 211 | "Name": "transactionCreate", 212 | "CallingType": "json", 213 | "Exposure": "public" 214 | }, 215 | { 216 | "Name": "transactionRead", 217 | "CallingType": "json", 218 | "Exposure": "public" 219 | }, 220 | { 221 | "Name": "getBalance", 222 | "CallingType": "json", 223 | "Exposure": "public" 224 | }, 225 | { 226 | "Name": "preauthCreate", 227 | "CallingType": "json", 228 | "Exposure": "public" 229 | }, 230 | { 231 | "Name": "preauthCancel", 232 | "CallingType": "json", 233 | "Exposure": "public" 234 | } 235 | ] 236 | } 237 | ] 238 | } 239 | -------------------------------------------------------------------------------- /dao/dna/owned/owned.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // ----------------------------------------------------------------- 4 | // This stub Zome code file was auto-generated 5 | // ----------------------------------------------------------------- 6 | 7 | /** 8 | * Called only when your source chain is generated 9 | * @return {boolean} success 10 | */ 11 | function genesis() { 12 | // any genesis code here 13 | return true; 14 | } 15 | 16 | // ----------------------------------------------------------------- 17 | // validation functions for every DHT entry change 18 | // ----------------------------------------------------------------- 19 | 20 | /** 21 | * Called to validate any changes to the DHT 22 | * @param {string} entryName - the name of entry being modified 23 | * @param {*} entry - the entry data to be set 24 | * @param {?} header - ? 25 | * @param {?} pkg - ? 26 | * @param {?} sources - ? 27 | * @return {boolean} is valid? 28 | */ 29 | function validateCommit (entryName, entry, header, pkg, sources) { 30 | switch (entryName) { 31 | case "owner_links": 32 | return validateOwnerLinks(entry.Links,sources); 33 | // validation code here 34 | default: 35 | // invalid entry name!! 36 | return false; 37 | } 38 | } 39 | 40 | /** 41 | * Called to validate any changes to the DHT 42 | * @param {string} entryName - the name of entry being modified 43 | * @param {*}entry - the entry data to be set 44 | * @param {?} header - ? 45 | * @param {?} pkg - ? 46 | * @param {?} sources - ? 47 | * @return {boolean} is valid? 48 | */ 49 | function validatePut (entryName, entry, header, pkg, sources) { 50 | switch (entryName) { 51 | case "sampleEntry": 52 | // validation code here 53 | return false; 54 | default: 55 | // invalid entry name!! 56 | return false; 57 | } 58 | } 59 | 60 | /** 61 | * Called to validate any changes to the DHT 62 | * @param {string} entryName - the name of entry being modified 63 | * @param {*} entry- the entry data to be set 64 | * @param {?} header - ? 65 | * @param {*} replaces - the old entry data 66 | * @param {?} pkg - ? 67 | * @param {?} sources - ? 68 | * @return {boolean} is valid? 69 | */ 70 | function validateMod (entryName, entry, header, replaces, pkg, sources) { 71 | switch (entryName) { 72 | case "sampleEntry": 73 | // validation code here 74 | return false; 75 | default: 76 | // invalid entry name!! 77 | return false; 78 | } 79 | } 80 | 81 | /** 82 | * Called to validate any changes to the DHT 83 | * @param {string} entryName - the name of entry being modified 84 | * @param {string} hash - the hash of the entry to remove 85 | * @param {?} pkg - ? 86 | * @param {?} sources - ? 87 | * @return {boolean} is valid? 88 | */ 89 | function validateDel (entryName,hash, pkg, sources) { 90 | switch (entryName) { 91 | case "sampleEntry": 92 | // validation code here 93 | return false; 94 | default: 95 | // invalid entry name!! 96 | return false; 97 | } 98 | } 99 | 100 | 101 | function validateOwnerLinks(links,sources) { 102 | 103 | // the source is the current owner 104 | var ownerHash = getOwner(); 105 | if (sources[0] != ownerHash) { 106 | return false; 107 | } 108 | 109 | var length = links.length; 110 | // there should just be one or two links only 111 | if (length==2) { 112 | // if this is a modify it will have two links the first of which 113 | // will be the del and the second the new link. 114 | if (links[0].LinkAction != HC.LinkAction.Del) return false; 115 | if ((links[1].LinkAction != HC.LinkAction.Add)/* TODO: test for undefined only until fixed in core */&&(links[1].LinkAction !=undefined)) return false; 116 | } else if (length==1) { 117 | // if this is a new handle, there will just be one Add link 118 | if ((links[0].LinkAction != HC.LinkAction.Add)/* TODO: test for undefined only until fixed in core */&&(links[0].LinkAction != undefined)) return false; 119 | } else {return false;} 120 | var ownerBaseHash = ownerBase(); 121 | for (var i=0;i uint) public memberId; 47 | Member[] public members; 48 | 49 | event ProposalAdded(uint proposalID, address recipient, uint amount, string description); 50 | event Voted(uint proposalID, bool position, address voter, string justification); 51 | event ProposalTallied(uint proposalID, int result, uint quorum, bool active); 52 | event MembershipChanged(address member, bool isMember); 53 | event ChangeOfRules(uint newMinimumQuorum, uint newDebatingPeriodInMinutes, int newMajorityMargin); 54 | 55 | struct Proposal { 56 | address recipient; 57 | uint amount; 58 | string description; 59 | uint votingDeadline; 60 | bool executed; 61 | bool proposalPassed; 62 | uint numberOfVotes; 63 | int currentResult; 64 | bytes32 proposalHash; 65 | Vote[] votes; 66 | mapping (address => bool) voted; 67 | } 68 | 69 | struct Member { 70 | address member; 71 | string name; 72 | uint memberSince; 73 | } 74 | 75 | struct Vote { 76 | bool inSupport; 77 | address voter; 78 | string justification; 79 | } 80 | 81 | // Modifier that allows only shareholders to vote and create new proposals 82 | modifier onlyMembers { 83 | require(memberId[msg.sender] != 0); 84 | _; 85 | } 86 | 87 | /** 88 | * Constructor function 89 | */ 90 | function Congress ( 91 | uint minimumQuorumForProposals, 92 | uint minutesForDebate, 93 | int marginOfVotesForMajority 94 | ) payable public { 95 | changeVotingRules(minimumQuorumForProposals, minutesForDebate, marginOfVotesForMajority); 96 | // It’s necessary to add an empty first member 97 | addMember(0, ""); 98 | // and let's add the founder, to save a step later 99 | addMember(owner, 'founder'); 100 | } 101 | 102 | /** 103 | * Add member 104 | * 105 | * Make `targetMember` a member named `memberName` 106 | * 107 | * @param targetMember ethereum address to be added 108 | * @param memberName public name for that member 109 | */ 110 | function addMember(address targetMember, string memberName) onlyOwner public { 111 | uint id = memberId[targetMember]; 112 | if (id == 0) { 113 | memberId[targetMember] = members.length; 114 | id = members.length++; 115 | } 116 | 117 | members[id] = Member({member: targetMember, memberSince: now, name: memberName}); 118 | MembershipChanged(targetMember, true); 119 | } 120 | 121 | /** 122 | * Remove member 123 | * 124 | * @notice Remove membership from `targetMember` 125 | * 126 | * @param targetMember ethereum address to be removed 127 | */ 128 | function removeMember(address targetMember) onlyOwner public { 129 | require(memberId[targetMember] != 0); 130 | 131 | for (uint i = memberId[targetMember]; i p.votingDeadline // If it is past the voting deadline 283 | && !p.executed // and it has not already been executed 284 | && p.proposalHash == keccak256(p.recipient, p.amount, transactionBytecode) // and the supplied code matches the proposal 285 | && p.numberOfVotes >= minimumQuorum); // and a minimum quorum has been reached... 286 | 287 | // ...then execute result 288 | 289 | if (p.currentResult > majorityMargin) { 290 | // Proposal passed; execute the transaction 291 | 292 | p.executed = true; // Avoid recursive calling 293 | require(p.recipient.call.value(p.amount)(transactionBytecode)); 294 | 295 | p.proposalPassed = true; 296 | } else { 297 | // Proposal failed 298 | p.proposalPassed = false; 299 | } 300 | 301 | // Fire Events 302 | ProposalTallied(proposalNumber, p.currentResult, p.numberOfVotes, p.proposalPassed); 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /dao/ethdao/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /dao/ethdao/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var Congress = artifacts.require("Congress"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Congress); 5 | }; 6 | -------------------------------------------------------------------------------- /dao/ethdao/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DAO", 3 | "version": "0.0.0", 4 | "description": "Ethereum DAO contracts", 5 | "author": "", 6 | "requires": true, 7 | "lockfileVersion": 1, 8 | "devDependencies": { 9 | "babel-cli": "^6.26.0", 10 | "babel-eslint": "^7.2.3", 11 | "babel-plugin-transform-es2015-destructuring": "^6.23.0", 12 | "babel-preset-es2015": "^6.24.1", 13 | "babel-preset-node6": "^11.0.0", 14 | "babel-preset-stage-2": "^6.24.1", 15 | "babel-register": "^6.24.1", 16 | "bignumber.js": "^4.1.0", 17 | "bluebird": "^3.5.0", 18 | "chai": "^4.1.2", 19 | "chai-http": "^3.0.0", 20 | "coffee-script": "^1.12.7", 21 | "lightsaber": "^0.6.10", 22 | "mocha": "^3.5.2", 23 | "shelljs": "^0.7.8" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dao/ethdao/test/congress.js: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | const Congress = artifacts.require('./Congress.sol'); 3 | const debug = false; 4 | contract('Congress', (accounts) => { 5 | let owner = accounts[0]; 6 | let congress; 7 | let totalGas = 0; 8 | let inc = (receipt) => {if (debug) console.log("gas used: "+receipt.gasUsed);totalGas += receipt.gasUsed;}; 9 | let implementer = accounts[9]; 10 | 11 | beforeEach(async () => { 12 | console.log("owner balance:",web3.eth.getBalance(owner)); 13 | }); 14 | 15 | describe('benchmark dao scenario', () => { 16 | it('should run the benchmarks', async() => { 17 | 18 | congress = await Congress.new(20, 120, 10); 19 | 20 | // get the gas for the contract deploy 21 | let x = web3.eth.getTransactionReceipt(congress.transactionHash); 22 | if (debug) console.log("congress create: ",x); 23 | inc(x); 24 | 25 | 26 | let minimumQuorumForProposals = 2; 27 | let minutesForDebate = 0; 28 | let marginOfVotesForMajority = 0; 29 | 30 | x = await congress.changeVotingRules(minimumQuorumForProposals, minutesForDebate, marginOfVotesForMajority); 31 | if (debug) console.log("\nchangeVotingRules:",x); 32 | inc(x.receipt); 33 | 34 | let partyaMembers = 4; 35 | let partybMembers = 3; 36 | 37 | // add party a members 38 | for(let i=1;i<=partyaMembers;i++) { 39 | let x = await congress.addMember(accounts[i],"partyaMember"+parseInt(i)); 40 | if (debug) console.log("\naddMember a: ",x); 41 | inc(x.receipt); 42 | } 43 | 44 | // add party b members 45 | for(let i=1;i<=partybMembers;i++) { 46 | let x = await congress.addMember(accounts[partyaMembers+i],"partybMember"+parseInt(i)); 47 | if (debug) console.log("\naddMember b: ",x); 48 | inc(x.receipt); 49 | } 50 | 51 | let proposalSizeKBytes = 0; 52 | let proposalTxt = ""; 53 | for(let i=1;i<=1024*proposalSizeKBytes;i++) { 54 | proposalTxt += "0"; 55 | 56 | } 57 | 58 | // all members of party a make a proposal and fund it 59 | for(let i=1;i<=partyaMembers;i++) { 60 | let x = await congress.newProposal(implementer,1234,proposalTxt,[],{from:accounts[i]}); 61 | if (debug) console.log("\nnewProposal: ",x); 62 | inc(x.receipt); 63 | 64 | console.log("congress balance:",web3.eth.getBalance(congress.address)); 65 | x = await congress.send(1234,{from:accounts[i]}); 66 | inc(x.receipt); 67 | console.log("congress balance:",web3.eth.getBalance(congress.address)); 68 | } 69 | 70 | // party a members vote in favor of all the partya proposals 71 | for(let i=0;i { 8 | contractIt(description, (done) => { 9 | Promise.resolve().then(functionToCall 10 | ).then(() => { 11 | throw new Error('Expected solidity error to be thrown from contract, but was not') 12 | }).catch((error) => { 13 | expectedErrorMessage = expectedErrorMessage || /VM Exception while processing transaction: revert|VM Exception while processing transaction: invalid opcode/ 14 | if (!error.message || error.message.search(expectedErrorMessage) < 0) throw error 15 | }).then(done).catch(done) 16 | }, options) 17 | } 18 | 19 | export const contractShouldThrowOnly = (description, functionToCall) => { 20 | contractShouldThrow(description, functionToCall, {only: true}) 21 | } 22 | 23 | export const contractShouldThrowIfEtherSent = (functionToCall, opts) => { 24 | contractShouldThrow('should throw an error if ether is sent', functionToCall, opts, 25 | /Cannot send value to non-payable function|VM Exception while processing transaction: invalid opcode|VM Exception while processing transaction: revert/) 26 | } 27 | 28 | export const contractShouldThrowIfEtherSentOnly = (functionToCall) => { 29 | contractShouldThrowIfEtherSent(functionToCall, {only: true}) 30 | } 31 | 32 | export const contractShouldThrowForNonOwner = (functionToCall, opts) => { 33 | contractShouldThrow('should throw an error for non-owner', () => { 34 | return functionToCall() 35 | }, opts) 36 | } 37 | 38 | export const contractShouldThrowForNonOwnerOnly = (functionToCall) => { 39 | contractShouldThrowForNonOwner(functionToCall, {only: true}) 40 | } 41 | 42 | export const contractItOnly = (name, func) => { 43 | contractIt(name, func, {only: true}) 44 | } 45 | 46 | export const contractIt = (name, func, options) => { 47 | options = options || {} 48 | contract('', () => { 49 | describe('Contract:', function() { 50 | this.timeout(3000) 51 | if (options.only) { 52 | it.only(name, func) 53 | } else if (options.pending) { 54 | xit(name, func) 55 | } else { 56 | it(name, func) 57 | } 58 | }) 59 | }) 60 | } 61 | 62 | export const firstEvent = (events) => { 63 | return new Promise((resolve, reject) => { 64 | events.watch((error, log) => { 65 | if (error) { 66 | reject(error) 67 | } else { 68 | events.stopWatching() 69 | resolve(log) 70 | } 71 | }) 72 | }) 73 | } 74 | -------------------------------------------------------------------------------- /dao/ethdao/truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // See 3 | // to customize your Truffle configuration! 4 | }; 5 | -------------------------------------------------------------------------------- /dao/ethdao/truffle.js: -------------------------------------------------------------------------------- 1 | require('babel-register'); 2 | require('babel-polyfill'); 3 | 4 | module.exports = { 5 | // See 6 | // to customize your Truffle configuration! 7 | }; 8 | -------------------------------------------------------------------------------- /dao/test/benchmark/_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "GossipInterval": 300, 3 | "Duration": 20, 4 | "Clone": [{ "Role":"partya", "Number":4 },{ "Role":"partyb", "Number":3 }] 5 | } 6 | -------------------------------------------------------------------------------- /dao/test/benchmark/implementer.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tests": 3 | [ 4 | { 5 | "Convey":"implementer's balance at the start should be 0", 6 | "Zome": "transactions", 7 | "FnName": "getBalance", 8 | "Output": 0, 9 | "Exposure":"public" 10 | }, 11 | { 12 | "Time": 20000, 13 | "Convey": "implementer executes proposals should succeed", 14 | "Zome": "congress", 15 | "Raw": true, 16 | "Input": "var results=[];var proposals = getProposals('');for (var i=0;iYour UI here! -------------------------------------------------------------------------------- /sorting/dna/dna.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 1, 3 | "UUID": "570d654d-ad49-49b1-8c02-c2c66c30ff91", 4 | "Name": "sortArray", 5 | "Properties": { 6 | "description": "somewhat contrived example of a list sorting application", 7 | "language": "en" 8 | }, 9 | "PropertiesSchemaFile": "properties_schema.json", 10 | 11 | "Zomes": [ 12 | { 13 | "Name": "sortArray", 14 | "Description": "", 15 | "Config":{"ErrorHandling":"returnErrorValue"}, 16 | "CodeFile": "sortArray.js", 17 | "Entries": [ 18 | { 19 | "Name": "sortArray", 20 | "DataFormat": "json", 21 | "SchemaFile": "sortArray.json", 22 | "Sharing": "public" 23 | }, 24 | { 25 | "Name": "array_links", 26 | "DataFormat": "links" 27 | } 28 | 29 | ], 30 | "RibosomeType": "js", 31 | "Functions": [ 32 | { 33 | "Name": "sortArrayCreate", 34 | "CallingType": "json", 35 | "Exposure": "public" 36 | }, 37 | { 38 | "Name": "sortArrayRead", 39 | "CallingType": "json", 40 | "Exposure": "public" 41 | }, 42 | { 43 | "Name": "sortArray", 44 | "CallingType": "json", 45 | "Exposure": "public" 46 | }, 47 | { 48 | "Name": "getArray", 49 | "CallingType": "json", 50 | "Exposure": "public" 51 | } 52 | ], 53 | "BridgeFuncs": null, 54 | "BridgeTo": "" 55 | } 56 | ], 57 | "RequiresVersion": 20, 58 | "DHTConfig": { 59 | "HashType": "sha2-256", 60 | "NeighborhoodSize": 0 61 | }, 62 | "Progenitor": { 63 | "Identity": "", 64 | "PubKey": null 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /sorting/dna/properties_schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Properties Schema", 3 | "type": "object", 4 | "properties": { 5 | "description": { 6 | "type": "string" 7 | }, 8 | "language": { 9 | "type": "string" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /sorting/dna/sortArray/sortArray.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // ----------------------------------------------------------------- 4 | // This stub Zome code file was auto-generated by hc-scaffold 5 | // ----------------------------------------------------------------- 6 | 7 | /** 8 | * Called only when your source chain is generated 9 | * @return {boolean} success 10 | */ 11 | function genesis () { 12 | // any genesis code here 13 | return true; 14 | } 15 | 16 | // ----------------------------------------------------------------- 17 | // validation functions for every DHT entry change 18 | // ----------------------------------------------------------------- 19 | 20 | function validateNewEntry(entryName, entry, header, pkg, sources) { 21 | switch (entryName) { 22 | case "sortArray": 23 | var array = entry; 24 | var val = array[0]; 25 | for (var i=1;i array[i]) return false; 27 | val = array[i]; 28 | } 29 | // validation code here 30 | return true; 31 | case "array_links": 32 | return true; 33 | default: 34 | // invalid entry name!! 35 | return false; 36 | } 37 | } 38 | 39 | /** 40 | * Called to validate any changes to the DHT 41 | * @param {string} entryName - the name of entry being modified 42 | * @param {*} entry - the entry data to be set 43 | * @param {?} header - ? 44 | * @param {?} pkg - ? 45 | * @param {?} sources - ? 46 | * @return {boolean} is valid? 47 | */ 48 | function validateCommit (entryName, entry, header, pkg, sources) { 49 | return validateNewEntry(entryName, entry, header, pkg, sources); 50 | } 51 | 52 | /** 53 | * Called to validate any changes to the DHT 54 | * @param {string} entryName - the name of entry being modified 55 | * @param {*} entry - the entry data to be set 56 | * @param {?} header - ? 57 | * @param {?} pkg - ? 58 | * @param {?} sources - ? 59 | * @return {boolean} is valid? 60 | */ 61 | function validatePut (entryName, entry, header, pkg, sources) { 62 | return validateNewEntry(entryName, entry, header, pkg, sources); 63 | } 64 | 65 | /** 66 | * Called to validate any changes to the DHT 67 | * @param {string} entryName - the name of entry being modified 68 | * @param {*} entry - the entry data to be set 69 | * @param {?} header - ? 70 | * @param {*} replaces - the old entry data 71 | * @param {?} pkg - ? 72 | * @param {?} sources - ? 73 | * @return {boolean} is valid? 74 | */ 75 | function validateMod (entryName, entry, header, replaces, pkg, sources) { 76 | switch (entryName) { 77 | case "sortArray": 78 | // validation code here 79 | return false; 80 | default: 81 | // invalid entry name!! 82 | return false; 83 | } 84 | } 85 | 86 | /** 87 | * Called to validate any changes to the DHT 88 | * @param {string} entryName - the name of entry being modified 89 | * @param {string} hash - the hash of the entry to remove 90 | * @param {?} pkg - ? 91 | * @param {?} sources - ? 92 | * @return {boolean} is valid? 93 | */ 94 | function validateDel (entryName, hash, pkg, sources) { 95 | switch (entryName) { 96 | case "sortArray": 97 | // validation code here 98 | return false; 99 | default: 100 | // invalid entry name!! 101 | return false; 102 | } 103 | } 104 | 105 | /** 106 | * Called to validate any changes to the DHT 107 | * @param {?} pkg - ? 108 | * @param {?} sources - ? 109 | * @return {boolean} is valid? 110 | */ 111 | function validateLink (linkEntryType, baseHash, links, pkg, sources) { 112 | switch (linkEntryType) { 113 | case "array_links": 114 | // validation code here 115 | return true; 116 | default: 117 | // invalid entry name!! 118 | return false; 119 | } 120 | } 121 | 122 | /** 123 | * Called to get the data needed to validate 124 | * @param {string} entryName - the name of entry to validate 125 | * @return {*} the data required for validation 126 | */ 127 | function validatePutPkg (entryName) { 128 | return null; 129 | } 130 | 131 | /** 132 | * Called to get the data needed to validate 133 | * @param {string} entryName - the name of entry to validate 134 | * @return {*} the data required for validation 135 | */ 136 | function validateModPkg (entryName) { 137 | return null; 138 | } 139 | 140 | /** 141 | * Called to get the data needed to validate 142 | * @param {string} entryName - the name of entry to validate 143 | * @return {*} the data required for validation 144 | */ 145 | function validateDelPkg (entryName) { 146 | return null; 147 | } 148 | 149 | 150 | // ----------------------------------------------------------------- 151 | // public exposed functions 152 | // ----------------------------------------------------------------- 153 | 154 | /** 155 | * Called to create an sortArray 156 | * @param {array} array - the array that will be sorted 157 | * @return {string} the hash of the new entry 158 | */ 159 | function sortArrayCreate (array) { 160 | array = array.sort(sortNumber); 161 | 162 | var hash = commit("sortArray",array); 163 | 164 | if (!isErr(hash)) { 165 | commit("array_links",{Links:[{Base:App.DNA.Hash,Link:hash,Tag:"array"}]}); 166 | } 167 | return hash; 168 | } 169 | 170 | 171 | /** 172 | * Called to read an sortArray value 173 | * @param {hash} string - the particular stored sortArray 174 | * @return {array} the array 175 | */ 176 | function sortArrayRead (hash) { 177 | return get(hash); 178 | } 179 | 180 | /** 181 | * Called to get the hash of the first created array 182 | * @return {array} the hash 183 | */ 184 | function getArray() { 185 | var lks = getLinks(App.DNA.Hash,"array"); 186 | if (isErr(lks) || lks.length==0) { 187 | return ""; 188 | } 189 | 190 | return lks[0].Hash; 191 | } 192 | 193 | // utilities 194 | 195 | function sortNumber(a,b) { 196 | return a - b; 197 | } 198 | -------------------------------------------------------------------------------- /sorting/dna/sortArray/sortArray.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "sortArray Schema", 3 | "type": "array", 4 | "id": "http://example.com/whitelist/addressarray.json" 5 | } 6 | -------------------------------------------------------------------------------- /sorting/ethsort/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2", "node6"], 3 | "plugins": ["transform-es2015-destructuring"] 4 | } 5 | -------------------------------------------------------------------------------- /sorting/ethsort/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | node_modules 3 | 4 | # Generated files 5 | build 6 | environments 7 | package-lock.json 8 | 9 | # IDE 10 | .idea 11 | -------------------------------------------------------------------------------- /sorting/ethsort/README.md: -------------------------------------------------------------------------------- 1 | # Sorting tests 2 | 3 | These sorting tests are taken from a project called Alice Smart Contracts. 4 | 5 | Here is the [original repo](https://github.com/alice-si/array-booster) 6 | 7 | ### Installation 8 | This project requires [node-js](https://github.com/nodejs/node) runtime and uses [truffle](https://github.com/trufflesuite/truffle) Ethereum smart contracts development framework. In order to run it, install truffle first: 9 | 10 | npm install -g truffle 11 | 12 | Then install all of the node-js dependencies 13 | 14 | npm install 15 | 16 | ### Running tests 17 | 18 | truffle develop 19 | test 20 | 21 | ## License 22 | 23 | MIT License 24 | 25 | Copyright (c) 2017 Alice Ltd. (Jakub Wojciechowski jakub@alice.si) 26 | 27 | Permission is hereby granted, free of charge, to any person obtaining a copy 28 | of this software and associated documentation files (the "Software"), to deal 29 | in the Software without restriction, including without limitation the rights 30 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31 | copies of the Software, and to permit persons to whom the Software is 32 | furnished to do so, subject to the following conditions: 33 | 34 | The above copyright notice and this permission notice shall be included in all 35 | copies or substantial portions of the Software. 36 | 37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 43 | SOFTWARE. 44 | -------------------------------------------------------------------------------- /sorting/ethsort/contracts/Client.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import "./Sorter.sol"; 4 | 5 | contract Client { 6 | 7 | uint[] private data; 8 | 9 | function setData(uint[] _data) external { 10 | data = _data; 11 | } 12 | 13 | function getElement(uint index) returns(uint) { 14 | return data[index]; 15 | } 16 | 17 | function sort() { 18 | Sorter.sort(data); 19 | } 20 | 21 | 22 | } -------------------------------------------------------------------------------- /sorting/ethsort/contracts/InsertionSorter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | library InsertionSorter { 4 | 5 | 6 | function sort(uint[] storage data) { 7 | 8 | uint n = data.length; 9 | uint[] memory arr = new uint[](n); 10 | uint i; 11 | 12 | for(i=0; i 0 && arr[j-1] > key; j-- ) { 23 | arr[j] = arr[j-1]; 24 | } 25 | 26 | arr[j] = key; 27 | } 28 | 29 | for(i=0; i 0) { 26 | 27 | uint h = stack[top]; 28 | top = top - 1; 29 | uint l = stack[top]; 30 | top = top - 1; 31 | 32 | i = l; 33 | uint x = arr[h]; 34 | 35 | for(uint j=l; j l + 1) { 47 | top = top + 1; 48 | stack[top] = l; 49 | top = top + 1; 50 | stack[top] = p - 1; 51 | } 52 | 53 | //Push right side to stack 54 | if (p+1 < h) { 55 | top = top + 1; 56 | stack[top] = p + 1; 57 | top = top + 1; 58 | stack[top] = h; 59 | } 60 | } 61 | 62 | for(i=0; i data[largest]) { 40 | // largest = left; 41 | // } 42 | // 43 | // if (right < length && data[right] > data[largest]) { 44 | // largest = right; 45 | // } 46 | // 47 | // if (i == largest) { 48 | // break; 49 | // } 50 | // 51 | // swap(i, largest); 52 | // i = largest; 53 | // } 54 | // } 55 | // 56 | // function heapify(uint length) { 57 | // uint i = length/2; 58 | // while (true) { 59 | // max_heapify(i, length); 60 | // if (i == 0) break; 61 | // i--; 62 | // } 63 | // } 64 | // 65 | // function heapSort() { 66 | // heapify(data.length); 67 | // var i = data.length-1; 68 | // while(i > 0) { 69 | // swap(i, 0); 70 | // max_heapify(0, i-1); 71 | // i--; 72 | // } 73 | // } 74 | 75 | } -------------------------------------------------------------------------------- /sorting/ethsort/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /sorting/ethsort/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var InsertionSorter = artifacts.require("./InsertionSorter.sol"); 2 | var QuickSorter = artifacts.require("./QuickSorter.sol"); 3 | 4 | module.exports = function(deployer) { 5 | deployer.deploy(InsertionSorter); 6 | deployer.deploy(QuickSorter); 7 | }; 8 | -------------------------------------------------------------------------------- /sorting/ethsort/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "array-booster", 3 | "version": "0.0.1", 4 | "description": "Tools for manipulating arrays in Solidity", 5 | "main": "truffle.js", 6 | "scripts": { 7 | "test": "scripts/test.sh" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/alice-si/array-booster.git" 12 | }, 13 | "keywords": [ 14 | "solidity", 15 | "ethereum", 16 | "smart", 17 | "contracts", 18 | "sorting", 19 | "algorithms" 20 | ], 21 | "author": "Jakub Wojciechowski ", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/alice-si/array-booster/issues" 25 | }, 26 | "homepage": "https://github.com/alice-si/array-booster", 27 | "dependencies": { 28 | "truffle-hdwallet-provider": "0.0.3", 29 | "underscore": "^1.8.3" 30 | }, 31 | "devDependencies": { 32 | "babel-preset-es2015": "^6.18.0", 33 | "babel-preset-node6": "^11.0.0", 34 | "babel-preset-stage-2": "^6.18.0", 35 | "babel-preset-stage-3": "^6.17.0", 36 | "babel-register": "^6.23.0", 37 | "chai": "^4.0.2", 38 | "chai-as-promised": "^7.0.0", 39 | "chai-bignumber": "^2.0.0", 40 | "ethereumjs-testrpc": "^3.0.2", 41 | "mocha-lcov-reporter": "^1.3.0", 42 | "moment": "^2.18.1", 43 | "truffle": "3.2.2", 44 | "coffee-script": "^1.12.7", 45 | "lightsaber": "^0.6.10", 46 | "bluebird": "^3.5.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sorting/ethsort/scripts/test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | output=$(nc -z localhost 8545; echo $?) 4 | [ $output -eq "0" ] && trpc_running=true 5 | if [ ! $trpc_running ]; then 6 | echo "Starting our own testrpc node instance" 7 | # we give each account 1M ether, needed for high-value tests 8 | testrpc > /dev/null & trpc_pid=$! 9 | fi 10 | ./node_modules/truffle/cli.js test "$@" 11 | if [ ! $trpc_running ]; then 12 | kill -9 $trpc_pid 13 | fi -------------------------------------------------------------------------------- /sorting/ethsort/test/sorter.js: -------------------------------------------------------------------------------- 1 | var _ = require("underscore"); 2 | import { 3 | contractShouldThrow 4 | } from './testHelper' 5 | 6 | var InsertionSorter = artifacts.require("./InsertionSorter.sol"); 7 | var QuickSorter = artifacts.require("./QuickSorter.sol"); 8 | var Client = artifacts.require("./Client.sol"); 9 | 10 | const DATA = { 11 | 10: [3, 7, 4, 2, 1, 9, 8, 6, 5, 0], 12 | 25: [39, 51, 29, 14, 3, 11, 69, 93, 82, 36, 8, 72, 20, 24, 24, 42, 86, 48, 21, 52, 14, 83, 36, 6, 74], 13 | 50: [64, 61, 48, 59, 100, 23, 64, 94, 25, 37, 81, 46, 28, 96, 46, 75, 98, 97, 91, 83, 46, 11, 30, 15, 71, 38, 83, 64, 11, 96, 94, 89, 99, 22, 46, 41, 14, 81, 68, 10, 63, 4, 44, 30, 90, 84, 25, 10, 55, 93], 14 | 100: [47, 6, 31, 33, 51, 100, 7, 26, 94, 76, 11, 57, 40, 37, 45, 62, 56, 98, 98, 40, 1, 23, 17, 97, 13, 72, 56, 97, 20, 16, 79, 13, 17, 62, 55, 86, 34, 18, 2, 60, 66, 30, 100, 39, 25, 23, 58, 1, 55, 46, 25, 6, 82, 64, 73, 74, 84, 29, 38, 19, 75, 89, 62, 21, 3, 96, 21, 64, 82, 2, 46, 59, 31, 37, 76, 47, 77, 83, 7, 11, 26, 30, 88, 69, 32, 2, 48, 77, 61, 10, 60, 27, 7, 30, 93, 50, 56, 36, 77, 34], 15 | 200: [936, 345, 292, 7, 637, 52, 437, 784, 694, 3, 366, 681, 58, 355, 602, 144, 328, 593, 681, 872, 555, 65, 565, 833, 416, 582, 371, 408, 267, 906, 678, 678, 760, 105, 827, 401, 747, 869, 434, 521, 388, 891, 450, 725, 411, 91, 102, 166, 606, 534, 311, 243, 900, 961, 823, 483, 972, 412, 241, 820, 184, 378, 987, 484, 495, 185, 554, 822, 585, 536, 597, 798, 295, 81, 507, 609, 747, 535, 747, 131, 872, 332, 890, 391, 507, 746, 774, 351, 878, 5, 129, 366, 916, 822, 18, 200, 526, 172, 301, 834, 760, 72, 225, 646, 931, 488, 362, 384, 226, 540, 906, 505, 702, 299, 546, 317, 339, 63, 386, 219, 47, 989, 778, 13, 414, 265, 964, 266, 612, 35, 143, 494, 502, 51, 547, 236, 582, 448, 595, 108, 735, 756, 265, 574, 856, 486, 431, 473, 595, 120, 319, 78, 362, 213, 566, 815, 217, 658, 967, 9, 608, 62, 620, 639, 243, 42, 924, 817, 675, 852, 862, 599, 458, 866, 591, 372, 707, 338, 241, 874, 282, 217, 629, 849, 430, 781, 442, 525, 619, 727, 75, 285, 998, 57, 1000, 316, 884, 536, 859, 772] 16 | }; 17 | 18 | contract('Soriting algorithms', function() { 19 | 20 | var checkSort = async function (client, data) { 21 | var arr = _.range(0, data.length); 22 | Promise.all(arr.map(async(i) => { 23 | arr[i] = await client.getElement.call(i); 24 | })); 25 | for (var i = 1; i < arr.length; i++) { 26 | assert.ok(arr[i] >= arr[i - 1], "Data isn't sorted correctly"); 27 | } 28 | }; 29 | 30 | var sortData = async function (client, data) { 31 | await client.setData(data); 32 | let tx = await client.sort(); 33 | console.log("Gas [" + data.length + " elements]: " + tx.receipt.gasUsed); 34 | }; 35 | 36 | var testScenario = async function (sorter, data) { 37 | let deployedSorter = await sorter.deployed(); 38 | Client.link("Sorter", deployedSorter.address); 39 | let client = await Client.new(); 40 | // console.log(data) 41 | await sortData(client, data); 42 | await checkSort(client, data); 43 | }; 44 | 45 | describe('Insertion Sort algorithm:', async function () { 46 | 47 | it("should sort 10 elements with insertion Sort", async function () { 48 | await testScenario(InsertionSorter, DATA[10]); 49 | }); 50 | 51 | it("should sort 25 elements with insertion Sort", async function () { 52 | await testScenario(InsertionSorter, DATA[25]); 53 | }); 54 | 55 | it("should sort 50 elements with insertion Sort", async function () { 56 | await testScenario(InsertionSorter, DATA[50]); 57 | }); 58 | 59 | it("should sort 100 elements with insertion Sort", async function () { 60 | await testScenario(InsertionSorter, DATA[100]); 61 | }); 62 | 63 | it("should sort 200 elements with insertion Sort", async function () { 64 | await testScenario(InsertionSorter, DATA[200]); 65 | }); 66 | }); 67 | 68 | describe('Quick Sort algorithm:', async function () { 69 | 70 | it("should sort 10 elements with Quick Sort", async function () { 71 | await testScenario(QuickSorter, DATA[10]); 72 | }); 73 | 74 | it("should sort 25 elements with Quick Sort", async function () { 75 | await testScenario(QuickSorter, DATA[25]); 76 | }); 77 | 78 | it("should sort 50 elements with Quick Sort", async function () { 79 | await testScenario(QuickSorter, DATA[50]); 80 | }); 81 | 82 | it("should sort 100 elements with Quick Sort", async function () { 83 | await testScenario(QuickSorter, DATA[100]); 84 | }); 85 | 86 | it("should sort 200 elements with Quick Sort", async function () { 87 | await testScenario(QuickSorter, DATA[200]); 88 | }); 89 | 90 | }); 91 | /* 92 | 93 | describe('Quick Sort algorithm2:', async function () { 94 | 95 | it("should sort 331 elements with Quick Sort", async function () { 96 | await testScenario(QuickSorter, genArray(331)); 97 | }); 98 | contractShouldThrow("on 332 items", async () => { 99 | await testScenario(QuickSorter, genArray(332)); 100 | }); 101 | }); 102 | */ 103 | 104 | }); 105 | 106 | function genArray(n) { 107 | var output = []; 108 | for (var i = 0; i < n; i++) { 109 | var value = Math.floor(Math.random()*100); 110 | output.push(value); 111 | } 112 | return output; 113 | } 114 | -------------------------------------------------------------------------------- /sorting/ethsort/test/testHelper.js: -------------------------------------------------------------------------------- 1 | import Promise from 'bluebird' 2 | require('coffee-script/register') 3 | process.env.NODE_ENV = 'test' 4 | 5 | global.Promise = Promise 6 | 7 | export const contractShouldThrow = (description, functionToCall, options, expectedErrorMessage = null) => { 8 | contractIt(description, (done) => { 9 | Promise.resolve().then(functionToCall 10 | ).then(() => { 11 | throw new Error('Expected solidity error to be thrown from contract, but was not') 12 | }).catch((error) => { 13 | expectedErrorMessage = expectedErrorMessage || /VM Exception while processing transaction: revert|VM Exception while processing transaction: invalid opcode/ 14 | if (!error.message || error.message.search(expectedErrorMessage) < 0) throw error 15 | }).then(done).catch(done) 16 | }, options) 17 | } 18 | 19 | export const contractShouldThrowOnly = (description, functionToCall) => { 20 | contractShouldThrow(description, functionToCall, {only: true}) 21 | } 22 | 23 | export const contractShouldThrowIfEtherSent = (functionToCall, opts) => { 24 | contractShouldThrow('should throw an error if ether is sent', functionToCall, opts, 25 | /Cannot send value to non-payable function|VM Exception while processing transaction: invalid opcode|VM Exception while processing transaction: revert/) 26 | } 27 | 28 | export const contractShouldThrowIfEtherSentOnly = (functionToCall) => { 29 | contractShouldThrowIfEtherSent(functionToCall, {only: true}) 30 | } 31 | 32 | export const contractShouldThrowForNonOwner = (functionToCall, opts) => { 33 | contractShouldThrow('should throw an error for non-owner', () => { 34 | return functionToCall() 35 | }, opts) 36 | } 37 | 38 | export const contractShouldThrowForNonOwnerOnly = (functionToCall) => { 39 | contractShouldThrowForNonOwner(functionToCall, {only: true}) 40 | } 41 | 42 | export const contractItOnly = (name, func) => { 43 | contractIt(name, func, {only: true}) 44 | } 45 | 46 | export const contractIt = (name, func, options) => { 47 | options = options || {} 48 | contract('', () => { 49 | describe('Contract:', function() { 50 | this.timeout(3000) 51 | if (options.only) { 52 | it.only(name, func) 53 | } else if (options.pending) { 54 | xit(name, func) 55 | } else { 56 | it(name, func) 57 | } 58 | }) 59 | }) 60 | } 61 | 62 | export const firstEvent = (events) => { 63 | return new Promise((resolve, reject) => { 64 | events.watch((error, log) => { 65 | if (error) { 66 | reject(error) 67 | } else { 68 | events.stopWatching() 69 | resolve(log) 70 | } 71 | }) 72 | }) 73 | } 74 | -------------------------------------------------------------------------------- /sorting/ethsort/truffle.js: -------------------------------------------------------------------------------- 1 | require('babel-register'); 2 | require('babel-polyfill'); 3 | 4 | module.exports = { 5 | networks: { 6 | development: { 7 | host: "localhost", 8 | port: 8545, 9 | network_id: "*" // Match any network id 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /sorting/test/benchmark/_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "GossipInterval": 300, 3 | "Duration": 5, 4 | "Clone": [{ "Role":"reader", "Number":10 }] 5 | } 6 | -------------------------------------------------------------------------------- /sorting/test/benchmark/reader.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tests": [ 3 | { 4 | "Time":4500, 5 | "Convey": "check the sorted array", 6 | "Zome": "sortArray", 7 | "Raw": true, 8 | "Input": "var hash=getArray();var array=sortArrayRead(hash);var x = function(array){var val = array[0];for (var i=1;i array[i]) return false;val = array[i];} return true }; x(array)", 9 | "Output": true, 10 | "Exposure": "public" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /sorting/test/benchmark/sorter.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tests": [ 3 | { 4 | "Convey": "create a sorted list", 5 | "Zome": "sortArray", 6 | "Raw": true, 7 | "Input": "var i=0;var a=[];for(i=0;i<20000;i++) {a.push( Math.floor(Math.random()*10000))};sortArrayCreate(a)", 8 | "Output": "%h1%" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /sorting/test/sortArray.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tests": [ 3 | { 4 | "Convey": "it creates a sorted array", 5 | "Zome": "sortArray", 6 | "FnName": "sortArrayCreate", 7 | "Input": [2,7,4,3,9,10,6,1,8,5], 8 | "Output": "%h1%", 9 | "Exposure": "public" 10 | }, 11 | { 12 | "Convey": "you can read the sorted array", 13 | "Zome": "sortArray", 14 | "FnName": "sortArrayRead", 15 | "Input": "%h1%", 16 | "Output": [1,2,3,4,5,6,7,8,9,10], 17 | "Exposure": "public" 18 | }, 19 | { 20 | "Convey": "you can get the sorted array from a link", 21 | "Zome": "sortArray", 22 | "FnName": "getArray", 23 | "Input": "", 24 | "Output": "%h1%", 25 | "Exposure": "public" 26 | } 27 | ] 28 | } 29 | --------------------------------------------------------------------------------