diff --git a/forum-network/public/availability-test.html b/forum-network/public/availability-test.html deleted file mode 100644 index 5f3db62..0000000 --- a/forum-network/public/availability-test.html +++ /dev/null @@ -1,10 +0,0 @@ - - - Availability test - - - - -
- - { - 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(); diff --git a/forum-network/public/basic.html b/forum-network/public/basic.html deleted file mode 100644 index f0a81f1..0000000 --- a/forum-network/public/basic.html +++ /dev/null @@ -1,9 +0,0 @@ - - - Forum Network - - - - -
- diff --git a/forum-network/public/basic.js b/forum-network/public/basic.js deleted file mode 100644 index 48e587d..0000000 --- a/forum-network/public/basic.js +++ /dev/null @@ -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); -}()); diff --git a/forum-network/public/debounce-test.html b/forum-network/public/debounce-test.html deleted file mode 100644 index 028b237..0000000 --- a/forum-network/public/debounce-test.html +++ /dev/null @@ -1,9 +0,0 @@ - - - Forum Graph: Debounce test - - - - -
- diff --git a/forum-network/public/debounce-test.js b/forum-network/public/debounce-test.js deleted file mode 100644 index 278becf..0000000 --- a/forum-network/public/debounce-test.js +++ /dev/null @@ -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); diff --git a/forum-network/public/forum-network-test.html b/forum-network/public/forum-network-test.html deleted file mode 100644 index 21b7a39..0000000 --- a/forum-network/public/forum-network-test.html +++ /dev/null @@ -1,9 +0,0 @@ - - - Forum Network test - - - - -
- diff --git a/forum-network/public/forum-network-test.js b/forum-network/public/forum-network-test.js deleted file mode 100644 index c74e547..0000000 --- a/forum-network/public/forum-network-test.js +++ /dev/null @@ -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); diff --git a/forum-network/public/graph-test.html b/forum-network/public/graph-test.html deleted file mode 100644 index 2907cc2..0000000 --- a/forum-network/public/graph-test.html +++ /dev/null @@ -1,9 +0,0 @@ - - - Forum Graph - - - - -
- diff --git a/forum-network/public/graph-test.js b/forum-network/public/graph-test.js deleted file mode 100644 index 8c50aa3..0000000 --- a/forum-network/public/graph-test.js +++ /dev/null @@ -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); diff --git a/forum-network/public/index.html b/forum-network/public/index.html index b8a4ba0..77d5d26 100644 --- a/forum-network/public/index.html +++ b/forum-network/public/index.html @@ -1,16 +1,17 @@ Forum Network - + +

Tests

diff --git a/forum-network/public/tests/availability.html b/forum-network/public/tests/availability.html new file mode 100644 index 0000000..36cfd5b --- /dev/null +++ b/forum-network/public/tests/availability.html @@ -0,0 +1,159 @@ + + + Availability test + + + +
+ + diff --git a/forum-network/public/tests/basic.html b/forum-network/public/tests/basic.html new file mode 100644 index 0000000..de0e6e1 --- /dev/null +++ b/forum-network/public/tests/basic.html @@ -0,0 +1,203 @@ + + + Forum Network + + + +
+ + diff --git a/forum-network/public/tests/debounce.html b/forum-network/public/tests/debounce.html new file mode 100644 index 0000000..86259ad --- /dev/null +++ b/forum-network/public/tests/debounce.html @@ -0,0 +1,25 @@ + + + Forum Graph: Debounce test + + + +
+ + diff --git a/forum-network/public/tests/forum-network.html b/forum-network/public/tests/forum-network.html new file mode 100644 index 0000000..0793bef --- /dev/null +++ b/forum-network/public/tests/forum-network.html @@ -0,0 +1,63 @@ + + + Forum Network test + + + +
+ + diff --git a/forum-network/public/tests/graph.html b/forum-network/public/tests/graph.html new file mode 100644 index 0000000..d905ce2 --- /dev/null +++ b/forum-network/public/tests/graph.html @@ -0,0 +1,33 @@ + + + Forum Graph + + + +
+ + diff --git a/forum-network/public/mermaid-test.html b/forum-network/public/tests/mermaid.html similarity index 92% rename from forum-network/public/mermaid-test.html rename to forum-network/public/tests/mermaid.html index f3b0ab4..2c9c87b 100644 --- a/forum-network/public/mermaid-test.html +++ b/forum-network/public/tests/mermaid.html @@ -1,7 +1,7 @@ Mermaid test - + diff --git a/forum-network/public/validation-pool-test.html b/forum-network/public/validation-pool-test.html deleted file mode 100644 index 7016a03..0000000 --- a/forum-network/public/validation-pool-test.html +++ /dev/null @@ -1,10 +0,0 @@ - - - Validation Pool test - - - - -
- - { - 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();