Move tests to subdir and consolidate html+js
This commit is contained in:
parent
fc3138adab
commit
03af7d4b10
|
@ -1,10 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Availability test</title>
|
|
||||||
<script type="module" src="./availability-test.js" defer></script>
|
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="availability-test"></div>
|
|
||||||
</body>
|
|
||||||
<scr
|
|
|
@ -1,104 +0,0 @@
|
||||||
import { Box } from './classes/box.js';
|
|
||||||
import { Scene } from './classes/scene.js';
|
|
||||||
import { Member } from './classes/member.js';
|
|
||||||
import { Bench } from './classes/bench.js';
|
|
||||||
import { Business } from './classes/business.js';
|
|
||||||
import { Availability } from './classes/availability.js';
|
|
||||||
import { delay } from './util.js';
|
|
||||||
import { Forum } from './classes/forum.js';
|
|
||||||
import { Public } from './classes/public.js';
|
|
||||||
|
|
||||||
const DELAY_INTERVAL = 500;
|
|
||||||
|
|
||||||
const rootElement = document.getElementById('availability-test');
|
|
||||||
const rootBox = new Box('rootBox', rootElement).flex();
|
|
||||||
|
|
||||||
const scene = window.scene = new Scene('Availability test', rootBox).log('sequenceDiagram');
|
|
||||||
|
|
||||||
const members = window.members = [];
|
|
||||||
const newMember = async () => {
|
|
||||||
const index = members.length;
|
|
||||||
const name = `Member${index + 1}`;
|
|
||||||
const member = await new Member(name, scene).initialize();
|
|
||||||
members.push(member);
|
|
||||||
return member;
|
|
||||||
};
|
|
||||||
|
|
||||||
const member1 = await newMember();
|
|
||||||
const member2 = await newMember();
|
|
||||||
await newMember();
|
|
||||||
const bench = window.bench = new Bench('Bench', scene);
|
|
||||||
const forum = window.forum = new Forum(bench, 'Forum', scene);
|
|
||||||
const availability = window.bench = new Availability(bench, 'Availability', scene);
|
|
||||||
const business = window.business = new Business(bench, forum, availability, 'Business', scene);
|
|
||||||
const requestor = window.requestor = new Public('Public', scene);
|
|
||||||
|
|
||||||
const updateDisplayValues = async () => {
|
|
||||||
member1.setValue('rep', bench.reputations.getTokens(member1.reputationPublicKey));
|
|
||||||
member2.setValue('rep', bench.reputations.getTokens(member2.reputationPublicKey));
|
|
||||||
bench.setValue('total rep', bench.getTotalReputation());
|
|
||||||
await scene.renderSequenceDiagram();
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateDisplayValuesAndDelay = async () => {
|
|
||||||
await updateDisplayValues();
|
|
||||||
await delay(DELAY_INTERVAL);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getActiveWorker = async () => {
|
|
||||||
let worker;
|
|
||||||
let request;
|
|
||||||
for (const member of members) {
|
|
||||||
request = await member.getAssignedWork(availability, business);
|
|
||||||
if (request) {
|
|
||||||
worker = member;
|
|
||||||
worker.actions.getAssignedWork.log(worker, availability);
|
|
||||||
worker.activate();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { worker, request };
|
|
||||||
};
|
|
||||||
|
|
||||||
const voteForWorkEvidence = async (worker, pool) => {
|
|
||||||
for (const member of members) {
|
|
||||||
if (member !== worker) {
|
|
||||||
await member.castVote(pool, { position: true, stake: 1, anonymous: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
await updateDisplayValuesAndDelay();
|
|
||||||
|
|
||||||
// Populate availability pool
|
|
||||||
await member1.registerAvailability(availability, 1);
|
|
||||||
await member2.registerAvailability(availability, 1);
|
|
||||||
await updateDisplayValuesAndDelay();
|
|
||||||
|
|
||||||
// Submit work request
|
|
||||||
await requestor.submitRequest(business, { fee: 100 }, { please: 'do some work' });
|
|
||||||
await updateDisplayValuesAndDelay();
|
|
||||||
|
|
||||||
// Receive work request
|
|
||||||
const { worker, request } = await getActiveWorker();
|
|
||||||
|
|
||||||
// Submit work evidence
|
|
||||||
const pool = await worker.submitWork(business, request.id, {
|
|
||||||
here: 'is some evidence of work product',
|
|
||||||
}, {
|
|
||||||
tokenLossRatio: 1,
|
|
||||||
duration: 1000,
|
|
||||||
});
|
|
||||||
worker.deactivate();
|
|
||||||
await updateDisplayValuesAndDelay();
|
|
||||||
|
|
||||||
// Vote on work evidence
|
|
||||||
await voteForWorkEvidence(worker, pool);
|
|
||||||
await updateDisplayValuesAndDelay();
|
|
||||||
|
|
||||||
// Wait for validation pool duration to elapse
|
|
||||||
await delay(1000);
|
|
||||||
|
|
||||||
// Distribute reputation awards and fees
|
|
||||||
await pool.evaluateWinningConditions();
|
|
||||||
await updateDisplayValuesAndDelay();
|
|
|
@ -1,9 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Forum Network</title>
|
|
||||||
<script type="module" src="./basic.js" defer></script>
|
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="basic"></div>
|
|
||||||
</body>
|
|
|
@ -1,193 +0,0 @@
|
||||||
import { Box } from './classes/box.js';
|
|
||||||
import { Scene } from './classes/scene.js';
|
|
||||||
|
|
||||||
const rootElement = document.getElementById('basic');
|
|
||||||
const rootBox = new Box('rootBox', rootElement).flex();
|
|
||||||
|
|
||||||
function randomDelay(min, max) {
|
|
||||||
const delayMs = min + Math.random() * max;
|
|
||||||
return delayMs;
|
|
||||||
}
|
|
||||||
|
|
||||||
function delay(min, max = min) {
|
|
||||||
const delayMs = min + Math.random() * (max - min);
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
setTimeout(resolve, delayMs);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (true) {
|
|
||||||
const scene = new Scene('Scene 1', rootBox);
|
|
||||||
const webClientStatus = scene.addDisplayValue('WebClient Status');
|
|
||||||
const node1Status = scene.addDisplayValue('Node 1 Status');
|
|
||||||
const blockchainStatus = scene.addDisplayValue('Blockchain Status');
|
|
||||||
|
|
||||||
const webClient = scene.addActor('web client');
|
|
||||||
const node1 = scene.addActor('node 1');
|
|
||||||
const blockchain = scene.addActor('blockchain');
|
|
||||||
const requestForumPage = scene.addAction('requestForumPage');
|
|
||||||
const readBlockchainData = scene.addAction('readBlockchainData');
|
|
||||||
const blockchainData = scene.addAction('blockchainData');
|
|
||||||
const forumPage = scene.addAction('forumPage');
|
|
||||||
|
|
||||||
webClientStatus.set('Initialized');
|
|
||||||
node1Status.set('Idle');
|
|
||||||
blockchainStatus.set('Idle');
|
|
||||||
|
|
||||||
node1.on(requestForumPage, (src, detail) => {
|
|
||||||
node1Status.set('Processing request');
|
|
||||||
node1.on(blockchainData, (_src, data) => {
|
|
||||||
node1Status.set('Processing response');
|
|
||||||
setTimeout(() => {
|
|
||||||
node1.send(src, forumPage, data);
|
|
||||||
node1Status.set('Idle');
|
|
||||||
}, randomDelay(500, 1000));
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
node1.send(blockchain, readBlockchainData, detail);
|
|
||||||
}, randomDelay(500, 1500));
|
|
||||||
});
|
|
||||||
|
|
||||||
blockchain.on(readBlockchainData, (src, _detail) => {
|
|
||||||
blockchainStatus.set('Processing request');
|
|
||||||
setTimeout(() => {
|
|
||||||
blockchain.send(src, blockchainData, {});
|
|
||||||
blockchainStatus.set('Idle');
|
|
||||||
}, randomDelay(500, 1500));
|
|
||||||
});
|
|
||||||
|
|
||||||
webClient.on(forumPage, (_src, _detail) => {
|
|
||||||
webClientStatus.set('Received forum page');
|
|
||||||
});
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
webClient.send(node1, requestForumPage);
|
|
||||||
webClientStatus.set('Requested forum page');
|
|
||||||
}, randomDelay(6000, 12000));
|
|
||||||
}
|
|
||||||
|
|
||||||
(async function run() {
|
|
||||||
const scene = new Scene('Scene 2', rootBox);
|
|
||||||
|
|
||||||
const webClient = scene.addActor('webClient');
|
|
||||||
|
|
||||||
const nodes = [];
|
|
||||||
const memories = [];
|
|
||||||
const storages = [];
|
|
||||||
|
|
||||||
function addNode() {
|
|
||||||
const idx = nodes.length;
|
|
||||||
const node = scene.addActor(`node${idx}`);
|
|
||||||
const memory = scene.addActor(`memory${idx}`);
|
|
||||||
const storage = scene.addActor(`storage${idx}`);
|
|
||||||
node.memory = memory;
|
|
||||||
node.storage = storage;
|
|
||||||
nodes.push(node);
|
|
||||||
memories.push(memory);
|
|
||||||
storages.push(storage);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPeer(node) {
|
|
||||||
const peers = nodes.filter((peer) => peer !== node);
|
|
||||||
const idx = Math.floor(Math.random() * peers.length);
|
|
||||||
return peers[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
addNode();
|
|
||||||
addNode();
|
|
||||||
|
|
||||||
const [
|
|
||||||
seekTruth,
|
|
||||||
considerInfo,
|
|
||||||
evaluateConfidence,
|
|
||||||
chooseResponse,
|
|
||||||
qualifiedOpinions,
|
|
||||||
requestMemoryData,
|
|
||||||
memoryData,
|
|
||||||
requestStorageData,
|
|
||||||
storageData,
|
|
||||||
] = [
|
|
||||||
'seek truth',
|
|
||||||
'consider available information',
|
|
||||||
'evaluate confidence',
|
|
||||||
'choose response',
|
|
||||||
'qualified opinions',
|
|
||||||
'request in-memory data',
|
|
||||||
'in-memory data',
|
|
||||||
'request storage data',
|
|
||||||
'storage data',
|
|
||||||
].map((name) => scene.addAction(name));
|
|
||||||
|
|
||||||
memories.forEach((memory) => {
|
|
||||||
memory.setStatus('Idle');
|
|
||||||
memory.on(requestMemoryData, async (src, _detail) => {
|
|
||||||
memory.setStatus('Retrieving data');
|
|
||||||
await delay(1000);
|
|
||||||
memory.send(src, memoryData, {});
|
|
||||||
memory.setStatus('Idle');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
storages.forEach((storage) => {
|
|
||||||
storage.setStatus('Idle');
|
|
||||||
storage.on(requestStorageData, async (src, _detail) => {
|
|
||||||
storage.setStatus('Retrieving data');
|
|
||||||
await delay(1000);
|
|
||||||
storage.send(src, storageData, {});
|
|
||||||
storage.setStatus('Idle');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
nodes.forEach((node) => {
|
|
||||||
node.setStatus('Idle');
|
|
||||||
node.on(seekTruth, async (seeker, detail) => {
|
|
||||||
node.setStatus('Processing request');
|
|
||||||
|
|
||||||
node.on(chooseResponse, async (_src, _info) => {
|
|
||||||
node.setStatus('Choosing response');
|
|
||||||
await delay(1000);
|
|
||||||
node.send(seeker, qualifiedOpinions, {});
|
|
||||||
node.setStatus('Idle');
|
|
||||||
});
|
|
||||||
|
|
||||||
node.on(evaluateConfidence, async (_src, _info) => {
|
|
||||||
node.setStatus('Evaluating confidence');
|
|
||||||
await delay(1000);
|
|
||||||
node.send(node, chooseResponse);
|
|
||||||
});
|
|
||||||
|
|
||||||
node.on(considerInfo, async (_src, _info) => {
|
|
||||||
node.setStatus('Considering info');
|
|
||||||
await delay(1000);
|
|
||||||
node.send(node, evaluateConfidence);
|
|
||||||
});
|
|
||||||
|
|
||||||
node.on(memoryData, (_src, _data) => {
|
|
||||||
node.on(storageData, (__src, __data) => {
|
|
||||||
if (detail?.readConcern === 'single') {
|
|
||||||
node.send(node, considerInfo, {});
|
|
||||||
} else {
|
|
||||||
const peer = getPeer(node);
|
|
||||||
node.on(qualifiedOpinions, (___src, info) => {
|
|
||||||
node.send(node, considerInfo, info);
|
|
||||||
});
|
|
||||||
node.send(peer, seekTruth, { readConcern: 'single' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
node.send(node.storage, requestStorageData);
|
|
||||||
});
|
|
||||||
|
|
||||||
await delay(1000);
|
|
||||||
node.send(node.memory, requestMemoryData);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
webClient.on(qualifiedOpinions, (_src, _detail) => {
|
|
||||||
webClient.setStatus('Received opinions and qualifications');
|
|
||||||
});
|
|
||||||
|
|
||||||
await delay(1000);
|
|
||||||
webClient.setStatus('Seek truth');
|
|
||||||
webClient.send(nodes[0], seekTruth);
|
|
||||||
}());
|
|
|
@ -1,9 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Forum Graph: Debounce test</title>
|
|
||||||
<script type="module" src="./debounce-test.js" defer></script>
|
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="debounce-test"></div>
|
|
||||||
</body>
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { Box } from './classes/box.js';
|
|
||||||
import { Scene } from './classes/scene.js';
|
|
||||||
import { debounce, delay } from './util.js';
|
|
||||||
|
|
||||||
const rootElement = document.getElementById('debounce-test');
|
|
||||||
const rootBox = new Box('rootBox', rootElement).flex();
|
|
||||||
|
|
||||||
const scene = window.scene = new Scene('Debounce test', rootBox);
|
|
||||||
|
|
||||||
const log = () => scene.log('event');
|
|
||||||
debounce(log, 500);
|
|
||||||
debounce(log, 500);
|
|
||||||
await delay(500);
|
|
||||||
debounce(log, 500);
|
|
||||||
debounce(log, 500);
|
|
|
@ -1,9 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Forum Network test</title>
|
|
||||||
<script type="module" src="./forum-network-test.js" defer></script>
|
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="forum-network"></div>
|
|
||||||
</body>
|
|
|
@ -1,42 +0,0 @@
|
||||||
import { Box } from './classes/box.js';
|
|
||||||
import { Scene } from './classes/scene.js';
|
|
||||||
import { PostContent } from './classes/post.js';
|
|
||||||
import { Member } from './classes/member.js';
|
|
||||||
import { ForumNode } from './classes/forum-node.js';
|
|
||||||
import { ForumNetwork } from './classes/forum-network.js';
|
|
||||||
import { delay } from './util.js';
|
|
||||||
|
|
||||||
const rootElement = document.getElementById('forum-network');
|
|
||||||
const rootBox = new Box('rootBox', rootElement).flex();
|
|
||||||
|
|
||||||
window.scene = new Scene('Forum Network test', rootBox).log('sequenceDiagram');
|
|
||||||
|
|
||||||
window.author1 = await new Member('author1', window.scene).initialize();
|
|
||||||
window.author2 = await new Member('author2', window.scene).initialize();
|
|
||||||
|
|
||||||
window.forumNetwork = new ForumNetwork();
|
|
||||||
|
|
||||||
window.forumNode1 = await new ForumNode('node1', window.scene).initialize(window.forumNetwork);
|
|
||||||
window.forumNode2 = await new ForumNode('node2', window.scene).initialize(window.forumNetwork);
|
|
||||||
window.forumNode3 = await new ForumNode('node3', window.scene).initialize(window.forumNetwork);
|
|
||||||
|
|
||||||
const processInterval = setInterval(async () => {
|
|
||||||
await window.forumNode1.processNextMessage();
|
|
||||||
await window.forumNode2.processNextMessage();
|
|
||||||
await window.forumNode3.processNextMessage();
|
|
||||||
|
|
||||||
await window.scene.renderSequenceDiagram();
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// const blockchain = new Blockchain();
|
|
||||||
|
|
||||||
window.post1 = new PostContent({ message: 'hi' });
|
|
||||||
window.post2 = new PostContent({ message: 'hello' }).addCitation(window.post1.id, 1.0);
|
|
||||||
|
|
||||||
await delay(1000);
|
|
||||||
await window.author1.submitPost(window.forumNode1, window.post1, 50);
|
|
||||||
await delay(1000);
|
|
||||||
await window.author2.submitPost(window.forumNode2, window.post2, 100);
|
|
||||||
|
|
||||||
await delay(1000);
|
|
||||||
clearInterval(processInterval);
|
|
|
@ -1,9 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Forum Graph</title>
|
|
||||||
<script type="module" src="./graph-test.js" defer></script>
|
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="graph-test"></div>
|
|
||||||
</body>
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { Box } from './classes/box.js';
|
|
||||||
import { Scene } from './classes/scene.js';
|
|
||||||
import { Graph } from './classes/graph.js';
|
|
||||||
|
|
||||||
const rootElement = document.getElementById('graph-test');
|
|
||||||
const rootBox = new Box('rootBox', rootElement).flex();
|
|
||||||
|
|
||||||
window.scene = new Scene('Graph test', rootBox);
|
|
||||||
|
|
||||||
window.graph = new Graph();
|
|
||||||
|
|
||||||
window.v = [];
|
|
||||||
function addVertex() {
|
|
||||||
const vertex = window.graph.addVertex({ seq: window.v.length });
|
|
||||||
window.v.push(vertex);
|
|
||||||
}
|
|
||||||
addVertex();
|
|
||||||
addVertex();
|
|
||||||
addVertex();
|
|
||||||
addVertex();
|
|
||||||
addVertex();
|
|
||||||
|
|
||||||
window.graph.addEdge('e1', 0, 1);
|
|
|
@ -1,16 +1,17 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
<title>Forum Network</title>
|
<title>Forum Network</title>
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
<link type="text/css" rel="stylesheet" href="/index.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<h2>Tests</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="./basic.html">Basic test</a></li>
|
<li><a href="/tests/basic.html">Basic</a></li>
|
||||||
<li><a href="./forum-network-test.html">Forum Network test</a></li>
|
<li><a href="/tests/forum-network.html">Forum Network</a></li>
|
||||||
<li><a href="./graph-test.html">Graph test</a></li>
|
<li><a href="/tests/graph.html">Graph</a></li>
|
||||||
<li><a href="./validation-pool-test.html">Validation Pool test</a></li>
|
<li><a href="/tests/validation-pool.html">Validation Pool</a></li>
|
||||||
<li><a href="./mermaid-test.html">Mermaid test</a></li>
|
<li><a href="/tests/mermaid.html">Mermaid</a></li>
|
||||||
<li><a href="./debounce-test.html">Debounce test</a></li>
|
<li><a href="/tests/debounce.html">Debounce</a></li>
|
||||||
<li><a href="./availability-test.html">Availability test</a></li>
|
<li><a href="/tests/availability.html">Availability</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Availability test</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/index.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="availability-test"></div>
|
||||||
|
</body>
|
||||||
|
<script type="module">
|
||||||
|
import { Box } from "/classes/box.js";
|
||||||
|
import { Scene } from "/classes/scene.js";
|
||||||
|
import { Member } from "/classes/member.js";
|
||||||
|
import { Bench } from "/classes/bench.js";
|
||||||
|
import { Business } from "/classes/business.js";
|
||||||
|
import { Availability } from "/classes/availability.js";
|
||||||
|
import { delay } from "/util.js";
|
||||||
|
import { Forum } from "/classes/forum.js";
|
||||||
|
import { Public } from "/classes/public.js";
|
||||||
|
|
||||||
|
const DELAY_INTERVAL = 500;
|
||||||
|
|
||||||
|
const rootElement = document.getElementById("availability-test");
|
||||||
|
const rootBox = new Box("rootBox", rootElement).flex();
|
||||||
|
|
||||||
|
const scene = (window.scene = new Scene("Availability test", rootBox).log(
|
||||||
|
"sequenceDiagram"
|
||||||
|
));
|
||||||
|
|
||||||
|
const members = (window.members = []);
|
||||||
|
const newMember = async () => {
|
||||||
|
const index = members.length;
|
||||||
|
const name = `Member${index + 1}`;
|
||||||
|
const member = await new Member(name, scene).initialize();
|
||||||
|
members.push(member);
|
||||||
|
return member;
|
||||||
|
};
|
||||||
|
|
||||||
|
const member1 = await newMember();
|
||||||
|
const member2 = await newMember();
|
||||||
|
await newMember();
|
||||||
|
const bench = (window.bench = new Bench("Bench", scene));
|
||||||
|
const forum = (window.forum = new Forum(bench, "Forum", scene));
|
||||||
|
const availability = (window.bench = new Availability(
|
||||||
|
bench,
|
||||||
|
"Availability",
|
||||||
|
scene
|
||||||
|
));
|
||||||
|
const business = (window.business = new Business(
|
||||||
|
bench,
|
||||||
|
forum,
|
||||||
|
availability,
|
||||||
|
"Business",
|
||||||
|
scene
|
||||||
|
));
|
||||||
|
const requestor = new Public("Public", scene);
|
||||||
|
|
||||||
|
const updateDisplayValues = async () => {
|
||||||
|
member1.setValue(
|
||||||
|
"rep",
|
||||||
|
bench.reputations.getTokens(member1.reputationPublicKey)
|
||||||
|
);
|
||||||
|
member2.setValue(
|
||||||
|
"rep",
|
||||||
|
bench.reputations.getTokens(member2.reputationPublicKey)
|
||||||
|
);
|
||||||
|
bench.setValue("total rep", bench.getTotalReputation());
|
||||||
|
await scene.renderSequenceDiagram();
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateDisplayValuesAndDelay = async () => {
|
||||||
|
await updateDisplayValues();
|
||||||
|
await delay(DELAY_INTERVAL);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getActiveWorker = async () => {
|
||||||
|
let worker;
|
||||||
|
let request;
|
||||||
|
for (const member of members) {
|
||||||
|
request = await member.getAssignedWork(availability, business);
|
||||||
|
if (request) {
|
||||||
|
worker = member;
|
||||||
|
worker.actions.getAssignedWork.log(worker, availability);
|
||||||
|
worker.activate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { worker, request };
|
||||||
|
};
|
||||||
|
|
||||||
|
const voteForWorkEvidence = async (worker, pool) => {
|
||||||
|
for (const member of members) {
|
||||||
|
if (member !== worker) {
|
||||||
|
await member.castVote(pool, {
|
||||||
|
position: true,
|
||||||
|
stake: 1,
|
||||||
|
anonymous: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
|
// Populate availability pool
|
||||||
|
await member1.registerAvailability(availability, 1);
|
||||||
|
await member2.registerAvailability(availability, 1);
|
||||||
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
|
// Submit work request
|
||||||
|
await requestor.submitRequest(
|
||||||
|
business,
|
||||||
|
{ fee: 100 },
|
||||||
|
{ please: "do some work" }
|
||||||
|
);
|
||||||
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
|
// Receive work request
|
||||||
|
const { worker, request } = await getActiveWorker();
|
||||||
|
|
||||||
|
// Submit work evidence
|
||||||
|
const pool = await worker.submitWork(
|
||||||
|
business,
|
||||||
|
request.id,
|
||||||
|
{
|
||||||
|
here: "is some evidence of work product",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tokenLossRatio: 1,
|
||||||
|
duration: 1000,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
worker.deactivate();
|
||||||
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
|
// Vote on work evidence
|
||||||
|
await voteForWorkEvidence(worker, pool);
|
||||||
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
|
// Wait for validation pool duration to elapse
|
||||||
|
await delay(1000);
|
||||||
|
|
||||||
|
// Distribute reputation awards and fees
|
||||||
|
await pool.evaluateWinningConditions();
|
||||||
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
|
// This should throw an exception since the pool is already resolved
|
||||||
|
try {
|
||||||
|
await pool.evaluateWinningConditions();
|
||||||
|
} catch (e) {
|
||||||
|
if (e.message.match(/Validation pool has already been resolved/)) {
|
||||||
|
console.log(
|
||||||
|
"Caught expected error: Validation pool has already been resolved"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.error("Unexpected error");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,203 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Forum Network</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/index.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="basic"></div>
|
||||||
|
</body>
|
||||||
|
<script type="module">
|
||||||
|
import { Box } from "/classes/box.js";
|
||||||
|
import { Scene } from "/classes/scene.js";
|
||||||
|
|
||||||
|
const rootElement = document.getElementById("basic");
|
||||||
|
const rootBox = new Box("rootBox", rootElement).flex();
|
||||||
|
|
||||||
|
function randomDelay(min, max) {
|
||||||
|
const delayMs = min + Math.random() * max;
|
||||||
|
return delayMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delay(min, max = min) {
|
||||||
|
const delayMs = min + Math.random() * (max - min);
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, delayMs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
const scene = new Scene("Scene 1", rootBox);
|
||||||
|
const webClientStatus = scene.addDisplayValue("WebClient Status");
|
||||||
|
const node1Status = scene.addDisplayValue("Node 1 Status");
|
||||||
|
const blockchainStatus = scene.addDisplayValue("Blockchain Status");
|
||||||
|
|
||||||
|
const webClient = scene.addActor("web client");
|
||||||
|
const node1 = scene.addActor("node 1");
|
||||||
|
const blockchain = scene.addActor("blockchain");
|
||||||
|
const requestForumPage = scene.addAction("requestForumPage");
|
||||||
|
const readBlockchainData = scene.addAction("readBlockchainData");
|
||||||
|
const blockchainData = scene.addAction("blockchainData");
|
||||||
|
const forumPage = scene.addAction("forumPage");
|
||||||
|
|
||||||
|
webClientStatus.set("Initialized");
|
||||||
|
node1Status.set("Idle");
|
||||||
|
blockchainStatus.set("Idle");
|
||||||
|
|
||||||
|
node1.on(requestForumPage, (src, detail) => {
|
||||||
|
node1Status.set("Processing request");
|
||||||
|
node1.on(blockchainData, (_src, data) => {
|
||||||
|
node1Status.set("Processing response");
|
||||||
|
setTimeout(() => {
|
||||||
|
node1.send(src, forumPage, data);
|
||||||
|
node1Status.set("Idle");
|
||||||
|
}, randomDelay(500, 1000));
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
node1.send(blockchain, readBlockchainData, detail);
|
||||||
|
}, randomDelay(500, 1500));
|
||||||
|
});
|
||||||
|
|
||||||
|
blockchain.on(readBlockchainData, (src, _detail) => {
|
||||||
|
blockchainStatus.set("Processing request");
|
||||||
|
setTimeout(() => {
|
||||||
|
blockchain.send(src, blockchainData, {});
|
||||||
|
blockchainStatus.set("Idle");
|
||||||
|
}, randomDelay(500, 1500));
|
||||||
|
});
|
||||||
|
|
||||||
|
webClient.on(forumPage, (_src, _detail) => {
|
||||||
|
webClientStatus.set("Received forum page");
|
||||||
|
});
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
webClient.send(node1, requestForumPage);
|
||||||
|
webClientStatus.set("Requested forum page");
|
||||||
|
}, randomDelay(6000, 12000));
|
||||||
|
}
|
||||||
|
|
||||||
|
(async function run() {
|
||||||
|
const scene = new Scene("Scene 2", rootBox);
|
||||||
|
|
||||||
|
const webClient = scene.addActor("webClient");
|
||||||
|
|
||||||
|
const nodes = [];
|
||||||
|
const memories = [];
|
||||||
|
const storages = [];
|
||||||
|
|
||||||
|
function addNode() {
|
||||||
|
const idx = nodes.length;
|
||||||
|
const node = scene.addActor(`node${idx}`);
|
||||||
|
const memory = scene.addActor(`memory${idx}`);
|
||||||
|
const storage = scene.addActor(`storage${idx}`);
|
||||||
|
node.memory = memory;
|
||||||
|
node.storage = storage;
|
||||||
|
nodes.push(node);
|
||||||
|
memories.push(memory);
|
||||||
|
storages.push(storage);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPeer(node) {
|
||||||
|
const peers = nodes.filter((peer) => peer !== node);
|
||||||
|
const idx = Math.floor(Math.random() * peers.length);
|
||||||
|
return peers[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
addNode();
|
||||||
|
addNode();
|
||||||
|
|
||||||
|
const [
|
||||||
|
seekTruth,
|
||||||
|
considerInfo,
|
||||||
|
evaluateConfidence,
|
||||||
|
chooseResponse,
|
||||||
|
qualifiedOpinions,
|
||||||
|
requestMemoryData,
|
||||||
|
memoryData,
|
||||||
|
requestStorageData,
|
||||||
|
storageData,
|
||||||
|
] = [
|
||||||
|
"seek truth",
|
||||||
|
"consider available information",
|
||||||
|
"evaluate confidence",
|
||||||
|
"choose response",
|
||||||
|
"qualified opinions",
|
||||||
|
"request in-memory data",
|
||||||
|
"in-memory data",
|
||||||
|
"request storage data",
|
||||||
|
"storage data",
|
||||||
|
].map((name) => scene.addAction(name));
|
||||||
|
|
||||||
|
memories.forEach((memory) => {
|
||||||
|
memory.setStatus("Idle");
|
||||||
|
memory.on(requestMemoryData, async (src, _detail) => {
|
||||||
|
memory.setStatus("Retrieving data");
|
||||||
|
await delay(1000);
|
||||||
|
memory.send(src, memoryData, {});
|
||||||
|
memory.setStatus("Idle");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
storages.forEach((storage) => {
|
||||||
|
storage.setStatus("Idle");
|
||||||
|
storage.on(requestStorageData, async (src, _detail) => {
|
||||||
|
storage.setStatus("Retrieving data");
|
||||||
|
await delay(1000);
|
||||||
|
storage.send(src, storageData, {});
|
||||||
|
storage.setStatus("Idle");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
nodes.forEach((node) => {
|
||||||
|
node.setStatus("Idle");
|
||||||
|
node.on(seekTruth, async (seeker, detail) => {
|
||||||
|
node.setStatus("Processing request");
|
||||||
|
|
||||||
|
node.on(chooseResponse, async (_src, _info) => {
|
||||||
|
node.setStatus("Choosing response");
|
||||||
|
await delay(1000);
|
||||||
|
node.send(seeker, qualifiedOpinions, {});
|
||||||
|
node.setStatus("Idle");
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on(evaluateConfidence, async (_src, _info) => {
|
||||||
|
node.setStatus("Evaluating confidence");
|
||||||
|
await delay(1000);
|
||||||
|
node.send(node, chooseResponse);
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on(considerInfo, async (_src, _info) => {
|
||||||
|
node.setStatus("Considering info");
|
||||||
|
await delay(1000);
|
||||||
|
node.send(node, evaluateConfidence);
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on(memoryData, (_src, _data) => {
|
||||||
|
node.on(storageData, (__src, __data) => {
|
||||||
|
if (detail?.readConcern === "single") {
|
||||||
|
node.send(node, considerInfo, {});
|
||||||
|
} else {
|
||||||
|
const peer = getPeer(node);
|
||||||
|
node.on(qualifiedOpinions, (___src, info) => {
|
||||||
|
node.send(node, considerInfo, info);
|
||||||
|
});
|
||||||
|
node.send(peer, seekTruth, { readConcern: "single" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
node.send(node.storage, requestStorageData);
|
||||||
|
});
|
||||||
|
|
||||||
|
await delay(1000);
|
||||||
|
node.send(node.memory, requestMemoryData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
webClient.on(qualifiedOpinions, (_src, _detail) => {
|
||||||
|
webClient.setStatus("Received opinions and qualifications");
|
||||||
|
});
|
||||||
|
|
||||||
|
await delay(1000);
|
||||||
|
webClient.setStatus("Seek truth");
|
||||||
|
webClient.send(nodes[0], seekTruth);
|
||||||
|
})();
|
||||||
|
</script>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Forum Graph: Debounce test</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/index.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="debounce-test"></div>
|
||||||
|
</body>
|
||||||
|
<script type="module">
|
||||||
|
import { Box } from "/classes/box.js";
|
||||||
|
import { Scene } from "/classes/scene.js";
|
||||||
|
import { debounce, delay } from "/util.js";
|
||||||
|
|
||||||
|
const rootElement = document.getElementById("debounce-test");
|
||||||
|
const rootBox = new Box("rootBox", rootElement).flex();
|
||||||
|
|
||||||
|
const scene = (window.scene = new Scene("Debounce test", rootBox));
|
||||||
|
|
||||||
|
const log = () => scene.log("event");
|
||||||
|
debounce(log, 500);
|
||||||
|
debounce(log, 500);
|
||||||
|
await delay(500);
|
||||||
|
debounce(log, 500);
|
||||||
|
debounce(log, 500);
|
||||||
|
</script>
|
|
@ -0,0 +1,63 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Forum Network test</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/index.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="forum-network"></div>
|
||||||
|
</body>
|
||||||
|
<script type="module">
|
||||||
|
import { Box } from "/classes/box.js";
|
||||||
|
import { Scene } from "/classes/scene.js";
|
||||||
|
import { PostContent } from "/classes/post.js";
|
||||||
|
import { Member } from "/classes/member.js";
|
||||||
|
import { ForumNode } from "/classes/forum-node.js";
|
||||||
|
import { ForumNetwork } from "/classes/forum-network.js";
|
||||||
|
import { delay } from "/util.js";
|
||||||
|
|
||||||
|
const rootElement = document.getElementById("forum-network");
|
||||||
|
const rootBox = new Box("rootBox", rootElement).flex();
|
||||||
|
|
||||||
|
window.scene = new Scene("Forum Network test", rootBox).log(
|
||||||
|
"sequenceDiagram"
|
||||||
|
);
|
||||||
|
|
||||||
|
window.author1 = await new Member("author1", window.scene).initialize();
|
||||||
|
window.author2 = await new Member("author2", window.scene).initialize();
|
||||||
|
|
||||||
|
window.forumNetwork = new ForumNetwork();
|
||||||
|
|
||||||
|
window.forumNode1 = await new ForumNode("node1", window.scene).initialize(
|
||||||
|
window.forumNetwork
|
||||||
|
);
|
||||||
|
window.forumNode2 = await new ForumNode("node2", window.scene).initialize(
|
||||||
|
window.forumNetwork
|
||||||
|
);
|
||||||
|
window.forumNode3 = await new ForumNode("node3", window.scene).initialize(
|
||||||
|
window.forumNetwork
|
||||||
|
);
|
||||||
|
|
||||||
|
const processInterval = setInterval(async () => {
|
||||||
|
await window.forumNode1.processNextMessage();
|
||||||
|
await window.forumNode2.processNextMessage();
|
||||||
|
await window.forumNode3.processNextMessage();
|
||||||
|
|
||||||
|
await window.scene.renderSequenceDiagram();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// const blockchain = new Blockchain();
|
||||||
|
|
||||||
|
window.post1 = new PostContent({ message: "hi" });
|
||||||
|
window.post2 = new PostContent({ message: "hello" }).addCitation(
|
||||||
|
window.post1.id,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
|
|
||||||
|
await delay(1000);
|
||||||
|
await window.author1.submitPost(window.forumNode1, window.post1, 50);
|
||||||
|
await delay(1000);
|
||||||
|
await window.author2.submitPost(window.forumNode2, window.post2, 100);
|
||||||
|
|
||||||
|
await delay(1000);
|
||||||
|
clearInterval(processInterval);
|
||||||
|
</script>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Forum Graph</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/index.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="graph-test"></div>
|
||||||
|
</body>
|
||||||
|
<script type="module">
|
||||||
|
import { Box } from "/classes/box.js";
|
||||||
|
import { Scene } from "/classes/scene.js";
|
||||||
|
import { Graph } from "/classes/graph.js";
|
||||||
|
|
||||||
|
const rootElement = document.getElementById("graph-test");
|
||||||
|
const rootBox = new Box("rootBox", rootElement).flex();
|
||||||
|
|
||||||
|
window.scene = new Scene("Graph test", rootBox);
|
||||||
|
|
||||||
|
window.graph = new Graph();
|
||||||
|
|
||||||
|
window.v = [];
|
||||||
|
function addVertex() {
|
||||||
|
const vertex = window.graph.addVertex({ seq: window.v.length });
|
||||||
|
window.v.push(vertex);
|
||||||
|
}
|
||||||
|
addVertex();
|
||||||
|
addVertex();
|
||||||
|
addVertex();
|
||||||
|
addVertex();
|
||||||
|
addVertex();
|
||||||
|
|
||||||
|
window.graph.addEdge("e1", 0, 1);
|
||||||
|
</script>
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
<title>Mermaid test</title>
|
<title>Mermaid test</title>
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
<link type="text/css" rel="stylesheet" href="/index.css" />
|
||||||
|
|
||||||
<script type="module" defer>
|
<script type="module" defer>
|
||||||
// import mermaid from './mermaid.mjs';
|
// import mermaid from './mermaid.mjs';
|
|
@ -0,0 +1,109 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Validation Pool test</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="/index.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="validation-pool"></div>
|
||||||
|
</body>
|
||||||
|
<script type="module">
|
||||||
|
import { Box } from "/classes/box.js";
|
||||||
|
import { Scene } from "/classes/scene.js";
|
||||||
|
import { Member } from "/classes/member.js";
|
||||||
|
import { Bench } from "/classes/bench.js";
|
||||||
|
import { delay } from "/util.js";
|
||||||
|
|
||||||
|
const rootElement = document.getElementById("validation-pool");
|
||||||
|
const rootBox = new Box("rootBox", rootElement).flex();
|
||||||
|
|
||||||
|
const scene = (window.scene = new Scene("Validation Pool test", rootBox).log(
|
||||||
|
"sequenceDiagram"
|
||||||
|
));
|
||||||
|
const member1 = (window.member1 = await new Member(
|
||||||
|
"Member1",
|
||||||
|
scene
|
||||||
|
).initialize());
|
||||||
|
const member2 = (window.member2 = await new Member(
|
||||||
|
"Member2",
|
||||||
|
scene
|
||||||
|
).initialize());
|
||||||
|
const bench = (window.bench = new Bench("Bench", scene));
|
||||||
|
|
||||||
|
const updateDisplayValues = async () => {
|
||||||
|
member1.setValue(
|
||||||
|
"rep",
|
||||||
|
bench.reputations.getTokens(member1.reputationPublicKey)
|
||||||
|
);
|
||||||
|
member2.setValue(
|
||||||
|
"rep",
|
||||||
|
bench.reputations.getTokens(member2.reputationPublicKey)
|
||||||
|
);
|
||||||
|
bench.setValue("total rep", bench.getTotalReputation());
|
||||||
|
// With params.lockingTimeExponent = 0 and params.activeVoterThreshold = null,
|
||||||
|
// these next 3 propetries are all equal to total rep
|
||||||
|
// bench.setValue('available rep', bench.getTotalAvailableReputation());
|
||||||
|
// bench.setValue('active rep', bench.getTotalActiveReputation());
|
||||||
|
// bench.setValue('active available rep', bench.getTotalActiveAvailableReputation());
|
||||||
|
await scene.renderSequenceDiagram();
|
||||||
|
};
|
||||||
|
|
||||||
|
updateDisplayValues();
|
||||||
|
await delay(1000);
|
||||||
|
|
||||||
|
// First member can self-approve
|
||||||
|
{
|
||||||
|
const pool = await member1.initiateValidationPool(bench, {
|
||||||
|
fee: 7,
|
||||||
|
duration: 1000,
|
||||||
|
tokenLossRatio: 1,
|
||||||
|
});
|
||||||
|
await member1.revealIdentity(pool);
|
||||||
|
await delay(1000);
|
||||||
|
await pool.evaluateWinningConditions(); // Vote passes
|
||||||
|
await updateDisplayValues();
|
||||||
|
await delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failure example: second member can not self-approve
|
||||||
|
try {
|
||||||
|
const pool = await member2.initiateValidationPool(bench, {
|
||||||
|
fee: 1,
|
||||||
|
duration: 1000,
|
||||||
|
tokenLossRatio: 1,
|
||||||
|
});
|
||||||
|
await member2.revealIdentity(pool);
|
||||||
|
await delay(1000);
|
||||||
|
await pool.evaluateWinningConditions(); // Quorum not met!
|
||||||
|
await updateDisplayValues();
|
||||||
|
await delay(1000);
|
||||||
|
} catch (e) {
|
||||||
|
if (e.message.match(/Quorum is not met/)) {
|
||||||
|
console.log("Caught expected error: Quorum not met");
|
||||||
|
} else {
|
||||||
|
console.error("Unexpected error");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second member must be approved by first member
|
||||||
|
{
|
||||||
|
const pool = await member2.initiateValidationPool(bench, {
|
||||||
|
fee: 1,
|
||||||
|
duration: 1000,
|
||||||
|
tokenLossRatio: 1,
|
||||||
|
});
|
||||||
|
await member1.castVote(pool, { position: true, stake: 4, lockingTime: 0 });
|
||||||
|
await member1.revealIdentity(pool);
|
||||||
|
await member2.revealIdentity(pool);
|
||||||
|
await delay(1000);
|
||||||
|
await pool.evaluateWinningConditions(); // Vote passes
|
||||||
|
await updateDisplayValues();
|
||||||
|
await delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateDisplayValues();
|
||||||
|
|
||||||
|
scene.deactivateAll();
|
||||||
|
|
||||||
|
await updateDisplayValues();
|
||||||
|
</script>
|
|
@ -1,10 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Validation Pool test</title>
|
|
||||||
<script type="module" src="./validation-pool-test.js" defer></script>
|
|
||||||
<link type="text/css" rel="stylesheet" href="./index.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="validation-pool"></div>
|
|
||||||
</body>
|
|
||||||
<scr
|
|
|
@ -1,73 +0,0 @@
|
||||||
import { Box } from './classes/box.js';
|
|
||||||
import { Scene } from './classes/scene.js';
|
|
||||||
import { Member } from './classes/member.js';
|
|
||||||
import { Bench } from './classes/bench.js';
|
|
||||||
import { delay } from './util.js';
|
|
||||||
|
|
||||||
const rootElement = document.getElementById('validation-pool');
|
|
||||||
const rootBox = new Box('rootBox', rootElement).flex();
|
|
||||||
|
|
||||||
const scene = window.scene = new Scene('Validation Pool test', rootBox).log('sequenceDiagram');
|
|
||||||
const member1 = window.member1 = await new Member('Member1', scene).initialize();
|
|
||||||
const member2 = window.member2 = await new Member('Member2', scene).initialize();
|
|
||||||
const bench = window.bench = new Bench('Bench', scene);
|
|
||||||
|
|
||||||
const updateDisplayValues = async () => {
|
|
||||||
member1.setValue('rep', bench.reputations.getTokens(member1.reputationPublicKey));
|
|
||||||
member2.setValue('rep', bench.reputations.getTokens(member2.reputationPublicKey));
|
|
||||||
bench.setValue('total rep', bench.getTotalReputation());
|
|
||||||
// With params.lockingTimeExponent = 0 and params.activeVoterThreshold = null,
|
|
||||||
// these next 3 propetries are all equal to total rep
|
|
||||||
// bench.setValue('available rep', bench.getTotalAvailableReputation());
|
|
||||||
// bench.setValue('active rep', bench.getTotalActiveReputation());
|
|
||||||
// bench.setValue('active available rep', bench.getTotalActiveAvailableReputation());
|
|
||||||
await scene.renderSequenceDiagram();
|
|
||||||
};
|
|
||||||
|
|
||||||
updateDisplayValues();
|
|
||||||
await delay(1000);
|
|
||||||
|
|
||||||
// First member can self-approve
|
|
||||||
{
|
|
||||||
const pool = await member1.initiateValidationPool(bench, { fee: 7, duration: 1000, tokenLossRatio: 1 });
|
|
||||||
await member1.revealIdentity(pool);
|
|
||||||
await delay(1000);
|
|
||||||
await pool.evaluateWinningConditions(); // Vote passes
|
|
||||||
await updateDisplayValues();
|
|
||||||
await delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Failure example: second member can not self-approve
|
|
||||||
try {
|
|
||||||
const pool = await member2.initiateValidationPool(bench, { fee: 1, duration: 1000, tokenLossRatio: 1 });
|
|
||||||
await member2.revealIdentity(pool);
|
|
||||||
await delay(1000);
|
|
||||||
await pool.evaluateWinningConditions(); // Quorum not met!
|
|
||||||
await updateDisplayValues();
|
|
||||||
await delay(1000);
|
|
||||||
} catch (e) {
|
|
||||||
if (e.message.match(/Quorum is not met/)) {
|
|
||||||
console.log('Caught expected error: Quorum not met');
|
|
||||||
} else {
|
|
||||||
console.error('Unexpected error');
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second member must be approved by first member
|
|
||||||
{
|
|
||||||
const pool = await member2.initiateValidationPool(bench, { fee: 1, duration: 1000, tokenLossRatio: 1 });
|
|
||||||
await member1.castVote(pool, { position: true, stake: 4, lockingTime: 0 });
|
|
||||||
await member1.revealIdentity(pool);
|
|
||||||
await member2.revealIdentity(pool);
|
|
||||||
await delay(1000);
|
|
||||||
await pool.evaluateWinningConditions(); // Vote passes
|
|
||||||
await updateDisplayValues();
|
|
||||||
await delay(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
await updateDisplayValues();
|
|
||||||
|
|
||||||
scene.deactivateAll();
|
|
||||||
|
|
||||||
await updateDisplayValues();
|
|
Loading…
Reference in New Issue