Skip to content

Instantly share code, notes, and snippets.

@0xankit
Last active June 9, 2020 05:44
Show Gist options
  • Save 0xankit/25505cee9634fa7e9ed147d15b36363f to your computer and use it in GitHub Desktop.
Save 0xankit/25505cee9634fa7e9ed147d15b36363f to your computer and use it in GitHub Desktop.
// Run with command: node Differential.js
/*
This experiment aims to measure the percentage of users on the internet who are actually dogs.
Real dogs would like to remain anonymous. After all, on the internet nobody knows you're a dog.
*/
// real (secret) populations
let numPeople = 90;
let numDogs = 10;
// TIP! try making the populations larger. What happens to the accuracy of the
// differentially-private estimate when we do?
const bigPopulation = false;
if (bigPopulation) {
numPeople *= 10000;
numDogs *= 10000;
}
// answer returns a differentially-private answer to the question "Are you a dog?". Takes `realDog`
// as input, depending on whether the user answering the question is truly a dog.
function answer(realDog) {
if (Math.random() < .5) {
// answer truthfully
return realDog;
}
// answer randomly
return Math.random() < .5;
}
// total counts the number of responses to the question "Are you a dog?". Some respondents are
// telling the truth, other are not
let total = 0;
// ask all the dogs
for (let i = 0; i < numDogs; i++) {
if (answer(true)) { total++; }
}
// ask all the people
for (let i = 0; i < numPeople; i++) {
if (answer(false)) { total++; }
}
// 50% of the answers are true. The other 50% have a 50% probability of being true, and a 50% probability of being false
const estimate = 2 * (total / (numPeople+numDogs) - .25);
(2 * total)/(numPeople+numDogs) - .25;
(total)/(numPeople) - .25;
function percentage(x) {
return (100 * x).toFixed(2) + '%';
}
console.log(`The actual percentage of dogs on the internet: ${percentage(numDogs/(numPeople+numDogs))}`);
console.log(`Differentially-private estimate of dogs on the internet: ${percentage(estimate)}`);
// npm install js-sha256
// Run with command: node hash.js
const sha256 = require('js-sha256'); // npm install js-sha256
/*
Alice has created a will (legal document) detailing how she would like to distribute her personal assets
upon her death. She wants to record this information to the blockchain for safety, but does not want to
reveal her net work or account addresses to the public. To do this she computes the SHA256 hash of her
document, records the hash to the blockchain and sends the complete document to Bob, her heir.
*/
/*
The super secret document!
*/
const document = 'Give 50 BTC from my wallet 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa to Bob';
/*
Alice computes the hash of her document
*/
const hash = sha256(document); // Result: 4f09ccb54e3074d49bb745d923fcc810e88181c241560b5499bc07919ed30ea7
console.log(`Alice hashes her document and records the following hash value to the blockchain: ${hash}`);
/*
Bob receives a document, which purports to be from Alice. He can compare the document to the hash by
computing the received document's SHA256 and verifying it matches the value he obtains from the blockchain
*/
if (sha256(document) === hash) {
console.log('Document is legit 👍');
} else {
console.log("Whoa! That's a fake document");
}
/*
Suppose instead that Bob's sister Eve wanted to inherit Alice's bitcoins, and she distributes a forged will.
Alice and Bob can still communicate with all the reliability as if she'd publicly written her will to the
blockchain itself
*/
const fake = 'Give 50 BTC from my wallet 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa to Eve';
if (sha256(fake) === hash) {
console.log('Document is legit 👍');
} else {
console.log("Whoa! That's a fake document");
}
pragma solidity ^0.4.24;
// Define a contract 'Lemonade Stand'
contract LemonadeStand {
// Variable: Owner
address owner;
// Variable: SKU count
uint skuCount;
// Event: 'State' with value 'ForSale'
enum State { ForSale, Sold, shipped }
// Struct: Item. name, sku, price, state, seller, buyer
struct Item {
string name;
uint sku;
uint price;
State state;
address seller;
address buyer;
}
// Define a public mapping 'items' that maps the SKU (a number) to an Item.
mapping (uint => Item) items;
// Events
event ForSale(uint skuCount);
event Sold(uint sku);
event shipped(uint sku);
// Modifier: Only Owner see if msg.sender == owner of the contract
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
// Define a modifier that verifies the Caller
modifier verifyCaller (address _address) {
require(msg.sender == _address);
_;
}
// Define a modifier that checks if the paid amount is sufficient to cover the price
modifier paidEnough(uint _price) {
require(msg.value >= _price);
_;
}
// Define a modifier that checks if an item.state of a sku is ForSale
modifier forSale(uint _sku) {
require(items[_sku].state == State.ForSale);
_;
}
// Define a modifier that checks if an item.state of a sku is Sold
modifier sold(uint _sku) {
require(items[_sku].state == State.Sold);
_;
}
modifier checkValue(uint _sku) {
_;
uint _price = items[_sku].price;
uint amountToRefund = msg.value - _price;
items[_sku].buyer.transfer(amountToRefund);
}
constructor() public payable {
owner = msg.sender;
skuCount = 0;
}
function addItem(string _name, uint _price) onlyOwner public {
// Increment sku
skuCount = skuCount + 1;
// Emit the appropriate event
emit ForSale(skuCount);
// Add the new item into inventory and mark it for sale
items[skuCount] = Item({name: _name, sku: skuCount, price: _price, state: State.ForSale, seller: msg.sender, buyer: 0});
}
function buyItem(uint sku) forSale(sku) paidEnough(items[sku].price) checkValue(sku) public payable {
address buyer = msg.sender;
uint price = items[sku].price;
// Update Buyer
items[sku].buyer = buyer;
// Update State
items[sku].state = State.Sold;
// Transfer money to seller
items[sku].seller.transfer(price);
// Emit the appropriate event
emit Sold(sku);
}
function shipItem(uint _sku) public onlyOwner sold(_sku){
items[_sku].state = State.shipped;
emit shipped(_sku);
}
function fetchItem(uint _sku) public view returns (string name, uint sku, uint price, string stateIs, address seller, address buyer) {
uint state;
name = items[_sku].name;
sku = items[_sku].sku;
price = items[_sku].price;
state = uint(items[_sku].state);
if( state == 0) {
stateIs = "For Sale";
}
if( state == 1) {
stateIs = "Sold";
}
seller = items[_sku].seller;
buyer = items[_sku].buyer;
}
}
// npm install js-sha256
// Run with command: node Merkle.js
const sha256 = require('js-sha256');
function MerkleTree(vals) {
// hash values and add to leaves of tree
const hashes = [];
hashes.push(vals.map(v => sha256(''+v)));
// add hash parents as until they converge to a single root
for (let last = hashes[hashes.length - 1]; last.length > 1; last = hashes[hashes.length - 1]) {
// calc next level of hashes and add to tree
hashes.push(parents(last));
}
this.__hashes = hashes;
}
// parents is a helper function for the MerkleTree constructor. It combines
// child values and hashes them to create parent values for one generation of
// children
function parents(children) {
const parents = [];
// step through children 2 by 2. Designate the first child the "left" child
// and the (optional) second child the "right" child
for (let i = 0; i < children.length; i += 2) {
const left = children[i];
// is children array has odd length, double the last child
const right = children.length > i+1 ? children[i+1] : children[i];
parents.push(sha256(left+right));
}
return parents;
}
// root returns the root of the Merkle tree
MerkleTree.prototype.root = function() {
return this.__hashes[this.__hashes.length - 1][0];
}
// proof returns the hashes along a single branch of the Merkle tree, aka the
// Merkle "proof"
MerkleTree.prototype.proof = function(val) {
const hash = sha256(''+val);
// find a leaf with matching hash
let idx = this.__hashes[0].indexOf(hash);
if (idx < 0) { return; } // value not present in tree
// construct proof
const proof = [];
for (let i = 0; i < this.__hashes.length - 1; i++) {
// choose hash to the left or right of element, depending on position
let offset = idx % 2 === 0 ? 1 : -1;
// if right pair is beyond the number of elements in array, pair with self
if (idx+offset >= this.__hashes[i].length) { offset = 0; }
if (offset >= 0) { proof.push('_'); } // empty slot before hash
proof.push(this.__hashes[i][idx+offset]);
if (offset < 0) { proof.push('_'); } // empty slot after hash
idx >>= 1; // integer division by 2
}
return proof;
};
// checkProof checks the validity of the supplied proof. It hashes the supplied
// value and recursively substitutes merkle hashes in slots provided in the
// proof. Returns the final value (for comparison with root)
function checkProof(val, proof) {
let hash = sha256(''+val);
if (!proof) { return hash; }
for (let i = 0; i < proof.length; i += 2) {
// read off two elements
const left = proof[i] === '_' ? hash : proof[i];
const right = proof[i+1] === '_' ? hash : proof[i+1];
hash = sha256(left + right);
}
return hash;
}
// To Student: Try changing values
const vals = ['S', 'N', 3, 1, 9, '🐶'];
console.log(`Hashing values ${vals} into Merkle tree...\n`);
const tree = new MerkleTree(vals);
console.log(`Merkle root for all values is: ${tree.root()}\n`);
['🐶', '😼'].forEach(val => {
const proof = tree.proof(val);
console.log(`Does Merkle tree contain '${val}'? Proof: ${proof}`);
console.log(`Verifying proof... Should produce same root with '${val}'...`);
if (checkProof(val, proof) == tree.root()) {
console.log(`... And it matches!`);
} else {
console.log(`... But there's no match`);
}
console.log();
});
// npm install lrs //
// Run with command: node ring.js
var lrs = require("lrs");
// 3 parties generate their public/private key pairs
var alice = lrs.gen();
var bob = lrs.gen();
var eve = lrs.gen();
// The list of public key is known and distributed
var group = [alice, bob, eve].map((m) => m.publicKey);
// Alice signs a message in behalf of one of the 3
var signed = lrs.sign(group, alice, "The body is buried on the backyard.");
// Anyone is able to verify *some* of them signed that message
console.log(lrs.verify(group, signed, "The body is buried on the backyard."));
// If that same person signs another message...
var signed2 = lrs.sign(group, alice, "Just kidding, he is alive.");
// We are able to tell the signature came from the same person
console.log(lrs.link(signed, signed2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment