Skip to content

Instantly share code, notes, and snippets.

@TheCyberWatchers
Created October 3, 2022 10:38
Show Gist options
  • Save TheCyberWatchers/5ec9a626188e1eb70cbd4772e4bbc8be to your computer and use it in GitHub Desktop.
Save TheCyberWatchers/5ec9a626188e1eb70cbd4772e4bbc8be to your computer and use it in GitHub Desktop.
//index.mjs
import { loadStdlib } from "@reach-sh/stdlib";
import * as backend from './build/index.main.mjs';
const stdlib = loadStdlib();
const startingBalance = stdlib.parseCurrency(100);
const accAlice = await stdlib.newTestAccount(startingBalance);
const accBob = await stdlib.newTestAccount(startingBalance);
const fmt = (x) => stdlib.formatCurrency(x, 4);
const getBalance = async (who) => fmt(await stdlib.balanceOf(who));
const beforeAlice = await getBalance(accAlice);
const beforeBob = await getBalance(accBob);
const ctcAlice = accAlice.contract(backend);
const ctcBob = accBob.contract(backend, ctcAlice.getInfo());
const HAND = ['Rock', 'Paper', 'Scissors'];
const OUTCOME = ['Bob Wins!', 'Draw', 'Alice Wins!'];
const Player = (Who) => ({
...stdlib.hasRandom,
getHand: async() => {
const hand = Math.floor(Math.random() * 3);
console.log(`${Who} played ${HAND[hand]}`)
if (Math.random() <= 0.01) {
for (let i = 0; i < 10; i++){
console.log(`${Who} takes their sweet time sending it back`);
await stdlib.wait(1);
}
}
return hand;
},
seeOutcome: (outcome) => {
console.log(`${Who} saw outcome ${OUTCOME[outcome]}`);
},
informTimeout: () => {
console.log(`${Who} observed a timeout`);
}
})
await Promise.all([
ctcAlice.p.Alice({
// Alice interact object here
...Player('Alice'),
wager: stdlib.parseCurrency(5),
deadline: 10,
}),
ctcBob.p.Bob({
// Bob interact object here
...Player('Bob'),
acceptWager: (amt) => {
console.log(`Bob accepts the wager of ${fmt(amt)}.`);
},
}),
]);
const afterAlice = await getBalance(accAlice);
const afterBob = await getBalance(accBob);
console.log(`Alice went from ${beforeAlice} to ${afterAlice}`);
console.log(`Bob went from ${beforeBob} to ${afterBob}`);
//index.rsh
'reach 0.1'
const [ isHand, ROCK, PAPER, SCISSORS ] = makeEnum(3);
const [ isOutcome, B_WINS, DRAW, A_WINS ] = makeEnum(3);
const winner = (handAlice, handBob) =>
((handAlice + (4 - handBob)) % 3);
assert(winner(ROCK, PAPER) == B_WINS);
assert(winner(PAPER, ROCK) == A_WINS);
assert(winner(ROCK, ROCK) == DRAW);
/*
forall(UInt, a =>
forall(UInt, b =>
forall(UInt, c =>
forall(UInt, d =>
assert(isOutcome(winner(a, b, c, d)))))));
*/
forall(UInt, handAlice =>
forall(UInt, handBob =>
assert(isOutcome(winner(handAlice, handBob)))));
forall(UInt, (hand) =>
assert(winner(hand, hand) == DRAW));
const Player = {
...hasRandom,
getHand: Fun([], UInt),
seeOutcome: Fun([UInt], Null),
informTimeout: Fun([], Null),
}
export const main = Reach.App(() => {
const Alice = Participant('Alice', {
// specify Alice's interact interface here
...Player,
wager: UInt,
deadline: UInt,
})
const Bob = Participant('Bob', {
...Player,
acceptWager: Fun([UInt], Null),
})
init()
const informTimeout = () => {
each([Alice, Bob], () => {
interact.informTimeout();
});
};
// write program here
Alice.only(() => {
const amount = declassify(interact.wager);
const deadline = declassify(interact.deadline);
})
Alice.publish(amount, deadline)
.pay(amount)
commit()
Bob.only(() => {
interact.acceptWager(amount);
});
Bob.pay(amount)
.timeout(relativeTime(deadline), () => closeTo(Alice, informTimeout));
//must be in consensus
var [outcome, v2] = [DRAW, 0];
invariant(balance() == (2 * amount))
while(outcome == DRAW){
//body of loop
commit();
Alice.only(() => {
const _handAlice = interact.getHand();
const [_commitAlice, _saltAlice] = makeCommitment(interact, _handAlice);
const commitAlice = declassify(_commitAlice);
});
Alice.publish(commitAlice)
.timeout(relativeTime(deadline), () => closeTo(Bob, informTimeout));
commit();
unknowable(Bob, Alice(_handAlice, _saltAlice));
Bob.only(() => {
const handBob = declassify(interact.getHand());
})
Bob.publish(handBob)
.timeout(relativeTime(deadline), () => closeTo(Alice, informTimeout));
commit();
Alice.only(() => {
const saltAlice = declassify(_saltAlice);
const handAlice = declassify(_handAlice);
});
Alice.publish(saltAlice, handAlice)
.timeout(relativeTime(deadline), () => closeTo(Bob, informTimeout));
checkCommitment(commitAlice, saltAlice, handAlice);
outcome = winner(handAlice, handBob);
continue;
}
//assert(outcome == A_WINS || outcome == B_WINS);
transfer(2 * amount).to(outcome == A_WINS ? Alice : Bob);
commit()
each([Alice, Bob], () => {
interact.seeOutcome(outcome)
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment