diff --git a/forum-network/public/classes/finance.js b/forum-network/public/classes/finance.js new file mode 100644 index 0000000..0ca5f53 --- /dev/null +++ b/forum-network/public/classes/finance.js @@ -0,0 +1,10 @@ +export class Token { + constructor(ownerPublicKey) { + this.ownerPublicKey = ownerPublicKey; + } + + transfer(newOwnerPublicKey) { + // TODO: Current owner must sign this request + this.ownerPublicKey = newOwnerPublicKey; + } +} diff --git a/forum-network/public/classes/forum-node.js b/forum-network/public/classes/forum-node.js index 6ac85a2..e09b6fa 100644 --- a/forum-network/public/classes/forum-node.js +++ b/forum-network/public/classes/forum-node.js @@ -84,6 +84,9 @@ export class ForumNode extends Actor { // Process an incoming post, received by whatever means processPost(authorId, post, stake) { + if (!post.id) { + post.id = CryptoUtil.randomUUID(); + } this.actions.storePost.log(this, this, null, { authorId, post, stake }); this.forumView.addPost(authorId, post.id, post, stake); } diff --git a/forum-network/public/classes/forum-view.js b/forum-network/public/classes/forum-view.js index 1176d03..e6a2d16 100644 --- a/forum-network/public/classes/forum-view.js +++ b/forum-network/public/classes/forum-view.js @@ -51,6 +51,7 @@ export class ForumView { const { citations = [], content } = postContent; const author = this.getOrInitializeAuthor(authorId); const postVertex = new PostVertex(postId, author, stake, content, citations); + console.log('addPost', { id: postId, postContent }); this.posts.addVertex(postId, postVertex); for (const citation of citations) { this.posts.addEdge('citation', postId, citation.postId, citation); diff --git a/forum-network/public/classes/forum.js b/forum-network/public/classes/forum.js index c7eacae..7cf197f 100644 --- a/forum-network/public/classes/forum.js +++ b/forum-network/public/classes/forum.js @@ -1,21 +1,18 @@ import { Actor } from './actor.js'; -import { Graph, Vertex } from './graph.js'; +import { Graph } from './graph.js'; +import { CryptoUtil } from './crypto.js'; import params from './params.js'; +import { Action } from './action.js'; -class PostVertex extends Vertex { +class Post extends Actor { constructor(forum, authorId, postContent) { - super(); - this.forum = forum; - this.id = postContent.id; + const index = forum.posts.countVertices(); + const name = `Post${index + 1}`; + super(name, forum.scene); + this.id = postContent.id ?? CryptoUtil.randomUUID(); this.authorId = authorId; - this.citations = postContent.citations; this.value = 0; } - - onValidate({ tokensMinted }) { - this.value = params.initialPostValueFunction({ tokensMinted }); - this.forum.distributeReputation(this, this.value); - } } /** @@ -26,14 +23,19 @@ export class Forum extends Actor { super(name, scene); this.bench = bench; this.posts = new Graph(); + this.actions = { + addPost: new Action('add post', scene), + }; } async addPost(authorId, postContent) { - const post = new PostVertex(this, authorId, postContent); + const post = new Post(this, authorId, postContent); + this.actions.addPost.log(this, post); this.posts.addVertex(post.id, post); for (const { postId: citedPostId, weight } of postContent.citations) { this.posts.addEdge('citation', post.id, citedPostId, { weight }); } + return post.id; } getPost(postId) { @@ -44,6 +46,11 @@ export class Forum extends Actor { return this.posts.getVertices(); } + onValidate({ tokensMinted }) { + const initialValue = params.initialPostValueFunction({ tokensMinted }); + this.distributeReputation(this, initialValue); + } + distributeReputation(post, amount, depth = 0) { console.log('distributeReputation', { post, amount, depth }); // Add the given value to the current post diff --git a/forum-network/public/classes/graph.js b/forum-network/public/classes/graph.js index a53d67a..2b22613 100644 --- a/forum-network/public/classes/graph.js +++ b/forum-network/public/classes/graph.js @@ -1,3 +1,6 @@ +import mermaid from 'https://unpkg.com/mermaid@9.2.2/dist/mermaid.esm.min.mjs'; +import { debounce } from '../util.js'; + export class Vertex { constructor(data) { this.data = data; @@ -38,7 +41,11 @@ export class Graph { data = id; id = this.nextVertexId++; } + if (this.vertices.has(id)) { + throw new Error(`Vertex already exists with id: ${id}`); + } const vertex = new Vertex(data); + console.log('addVertex', vertex); this.vertices.set(id, vertex); return this; } @@ -70,6 +77,7 @@ export class Graph { } addEdge(label, from, to, data) { + console.log('addEdge', { from, to }); if (this.getEdge(label, from, to)) { throw new Error(`Edge ${label} from ${from} to ${to} already exists`); } @@ -91,4 +99,24 @@ export class Graph { }); }); } + + countVertices() { + return this.vertices.size; + } + + async renderGraph() { + const render = async () => { + const dateStart = new Date(); + const graph = await mermaid.mermaidAPI.render( + this.seqDiagramElement.getId(), + this.logBox.getInnerText(), + ); + this.seqDiagramBox.setInnerHTML(graph); + if (!this.dateLastRender) { + this.dateLastRender = new Date(); + } + this.dateLastRender = dateStart; + }; + debounce(render, 100); + } } diff --git a/forum-network/public/classes/member.js b/forum-network/public/classes/member.js index 90b99e8..271e5db 100644 --- a/forum-network/public/classes/member.js +++ b/forum-network/public/classes/member.js @@ -8,6 +8,7 @@ export class Member extends Actor { constructor(name, scene) { super(name, scene); this.actions = { + submitPostViaNetwork: new Action('submit post via network', scene), submitPost: new Action('submit post', scene), initiateValidationPool: new Action('initiate validation pool', scene), castVote: new Action('cast vote', scene), @@ -28,15 +29,22 @@ export class Member extends Actor { return this; } - async submitPost(forumNode, post, stake) { + async submitPostViaNetwork(forumNode, post, stake) { // TODO: Include fee const postMessage = new PostMessage({ post, stake }); + console.log('submitPostViaNetwork', postMessage); await postMessage.sign(this.reputationKey); - this.actions.submitPost.log(this, forumNode, null, { id: post.id }); + this.actions.submitPostViaNetwork.log(this, forumNode, null, { id: post.id }); // For now, directly call forumNode.receiveMessage(); await forumNode.receiveMessage(JSON.stringify(postMessage.toJSON())); } + async submitPost(forum, postContent) { + // TODO: Include fee + this.actions.submitPost.log(this, forum); + return forum.addPost(this.reputationPublicKey, postContent); + } + async initiateValidationPool(bench, options) { // For now, directly call bench.initiateValidationPool(); const signingKey = await CryptoUtil.generateAsymmetricKey(); diff --git a/forum-network/public/classes/post.js b/forum-network/public/classes/post.js index e3c49a9..f85e32f 100644 --- a/forum-network/public/classes/post.js +++ b/forum-network/public/classes/post.js @@ -1,5 +1,3 @@ -import { CryptoUtil } from './crypto.js'; - export class Citation { constructor(postId, weight) { this.postId = postId; @@ -20,7 +18,6 @@ export class Citation { export class PostContent { constructor(content) { - this.id = CryptoUtil.randomUUID(); this.content = content; this.citations = []; } @@ -33,16 +30,16 @@ export class PostContent { toJSON() { return { - id: this.id, content: this.content, citations: this.citations.map((citation) => citation.toJSON()), + ...(this.id ? { id: this.id } : {}), }; } static fromJSON({ id, content, citations }) { const post = new PostContent(content); - post.id = id; post.citations = citations.map((citation) => Citation.fromJSON(citation)); + post.id = id; return post; } } diff --git a/forum-network/public/classes/scene.js b/forum-network/public/classes/scene.js index c4be663..28cc204 100644 --- a/forum-network/public/classes/scene.js +++ b/forum-network/public/classes/scene.js @@ -69,17 +69,8 @@ export class Scene { if (!this.dateLastRender) { this.dateLastRender = new Date(); } - console.log( - `renderSequenceDiagram time: ${ - new Date() - dateStart - } ms, time since last render: ${dateStart - this.dateLastRender}`, - ); this.dateLastRender = dateStart; }; debounce(render, 100); } - - insertSvg(svgCode) { - this.seqDiagramElement.setInnerHTML(svgCode); - } } diff --git a/forum-network/public/index.html b/forum-network/public/index.html index 77d5d26..fb3d946 100644 --- a/forum-network/public/index.html +++ b/forum-network/public/index.html @@ -13,5 +13,6 @@
  • Mermaid
  • Debounce
  • Availability
  • +
  • Forum
  • diff --git a/forum-network/public/tests/availability.html b/forum-network/public/tests/availability.html index 36cfd5b..8bc35fa 100644 --- a/forum-network/public/tests/availability.html +++ b/forum-network/public/tests/availability.html @@ -55,14 +55,12 @@ 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) - ); + for (const member of members) { + member.setValue( + "rep", + bench.reputations.getTokens(member.reputationPublicKey) + ); + } bench.setValue("total rep", bench.getTotalReputation()); await scene.renderSequenceDiagram(); }; diff --git a/forum-network/public/tests/forum-network.html b/forum-network/public/tests/forum-network.html index 0793bef..3013e5e 100644 --- a/forum-network/public/tests/forum-network.html +++ b/forum-network/public/tests/forum-network.html @@ -13,6 +13,7 @@ import { Member } from "/classes/member.js"; import { ForumNode } from "/classes/forum-node.js"; import { ForumNetwork } from "/classes/forum-network.js"; + import { CryptoUtil } from "/classes/crypto.js"; import { delay } from "/util.js"; const rootElement = document.getElementById("forum-network"); @@ -48,15 +49,24 @@ // const blockchain = new Blockchain(); window.post1 = new PostContent({ message: "hi" }); + window.post1.id = CryptoUtil.randomUUID(); 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 window.author1.submitPostViaNetwork( + window.forumNode1, + window.post1, + 50 + ); await delay(1000); - await window.author2.submitPost(window.forumNode2, window.post2, 100); + await window.author2.submitPostViaNetwork( + window.forumNode2, + window.post2, + 100 + ); await delay(1000); clearInterval(processInterval); diff --git a/forum-network/public/tests/forum.html b/forum-network/public/tests/forum.html new file mode 100644 index 0000000..6b1020a --- /dev/null +++ b/forum-network/public/tests/forum.html @@ -0,0 +1,81 @@ + + + Forum test + + + +
    + +