Post value propagation

This commit is contained in:
Ladd Hoffman 2023-01-04 16:28:36 -06:00
parent 8980885881
commit cfa445471f
8 changed files with 58 additions and 30 deletions

View File

@ -8,8 +8,9 @@ import { Action } from './action.js';
* Purpose: Keep track of reputation holders
*/
export class Bench extends Actor {
constructor(name, scene) {
constructor(forum, name, scene) {
super(name, scene);
this.forum = forum;
this.validationPools = new Map();
this.voters = new Map();
this.reputations = new Reputations();
@ -68,6 +69,7 @@ export class Bench extends Actor {
const validationPoolNumber = this.validationPools.size + 1;
const validationPool = new ValidationPool(
this,
this.forum,
{
postId,
fee,
@ -78,7 +80,7 @@ export class Bench extends Actor {
authorStake,
anonymous,
},
`pool${validationPoolNumber}`,
`Pool${validationPoolNumber}`,
this.scene,
);
this.validationPools.set(validationPool.id, validationPool);

View File

@ -25,7 +25,7 @@ export class Business extends Actor {
this.actions = {
assignWork: new Action('assign work', scene),
addPost: new Action('add post', scene),
submitPost: new Action('submit post', scene),
initiateValidationPool: new Action('initiate validation pool', scene),
};
}
@ -54,7 +54,7 @@ export class Business extends Actor {
requestId,
workEvidence,
});
this.actions.addPost.log(this, this.forum);
this.actions.submitPost.log(this, this.forum);
await this.forum.addPost(reputationPublicKey, post);
// Initiate a validation pool for this work evidence.

View File

@ -12,6 +12,16 @@ class Post extends Actor {
this.id = postContent.id ?? CryptoUtil.randomUUID();
this.authorId = authorId;
this.value = 0;
this.citations = postContent.citations;
}
setPostValue(value) {
this.setValue('value', value);
this.value = value;
}
getPostValue() {
return this.value;
}
}
@ -19,9 +29,8 @@ class Post extends Actor {
* Purpose: Maintain a directed, acyclic, weighted graph of posts referencing other posts
*/
export class Forum extends Actor {
constructor(bench, name, scene) {
constructor(name, scene) {
super(name, scene);
this.bench = bench;
this.posts = new Graph();
this.actions = {
addPost: new Action('add post', scene),
@ -46,11 +55,6 @@ 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

View File

@ -45,7 +45,6 @@ export class Graph {
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;
}
@ -77,7 +76,6 @@ 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`);
}

View File

@ -19,7 +19,7 @@ const params = {
lockingTimeExponent: 0, // c11
/* Forum parameters */
initialPostValueFunction: ({ tokensMinted }) => tokensMinted, // q1
initialPostValue: () => 1, // q1
citationFraction: 0.3, // q2
};

View File

@ -16,6 +16,7 @@ const ValidationPoolStates = Object.freeze({
export class ValidationPool extends Actor {
constructor(
bench,
forum,
{
postId,
signingPublicKey,
@ -52,6 +53,7 @@ export class ValidationPool extends Actor {
}]; got ${duration}`,
);
}
this.forum = forum;
this.postId = postId;
this.state = ValidationPoolStates.OPEN;
this.setStatus('Open');
@ -66,6 +68,7 @@ export class ValidationPool extends Actor {
this.duration = duration;
this.tokenLossRatio = tokenLossRatio;
this.contentiousDebate = contentiousDebate;
this.tokensMinted = fee * params.mintingRatio;
this.tokens = {
for: fee * params.mintingRatio * params.stakeForWin,
against: fee * params.mintingRatio * (1 - params.stakeForWin),
@ -93,7 +96,6 @@ export class ValidationPool extends Actor {
}
this.votes.set(signingPublicKey, vote);
if (!anonymous) {
console.log('castVote: revealing identity since this is not an anonymous vote');
await this.revealIdentity(signingPublicKey, signingPublicKey);
}
}
@ -200,20 +202,33 @@ export class ValidationPool extends Actor {
return result;
}
distributeTokens(result) {
let authorReputationPublicKey;
if (this.anonymous) {
const author = this.voters.get(this.authorSigningPublicKey);
authorReputationPublicKey = author.reputationPublicKey;
} else {
authorReputationPublicKey = this.authorSigningPublicKey;
propagateValue(nextPost, increment) {
const postValue = nextPost.getPostValue();
nextPost.setPostValue(postValue + increment);
for (const { postId: citedPostId, weight } of nextPost.citations) {
console.log('citedPostId', citedPostId);
const citedPost = this.forum.getPost(citedPostId);
this.propagateValue(citedPost, weight * increment);
}
// Reward the author
// TODO: If the vote fails, distribute tokens.author among winning voters
}
distributeTokens(result) {
const authorReputationPublicKey = this.anonymous
? this.voters.get(this.authorSigningPublicKey).reputationPublicKey
: this.authorSigningPublicKey;
// TODO: Take tokenLossRatio into account
if (result === true) {
this.bench.reputations.addTokens(authorReputationPublicKey, this.tokens.for);
// Take initialValue into account
const initialPostValue = params.initialPostValue() * this.tokensMinted;
const tokensForAuthor = initialPostValue * params.stakeForWin;
const tokensForWinners = initialPostValue * (1 - params.stakeForWin);
// Reward the author
this.bench.reputations.addTokens(authorReputationPublicKey, tokensForAuthor);
// Reward the vote winners, in proportion to their stakes
const tokensForWinners = this.tokens.against;
const winningVotes = this.listVotes(result);
const totalStakes = Array.from(winningVotes.values())
.map(({ stake }) => stake)
@ -226,6 +241,15 @@ export class ValidationPool extends Actor {
const reward = (tokensForWinners * stake) / totalStakes;
this.bench.reputations.addTokens(reputationPublicKey, reward);
}
// Update the forum post to set its (initial) value
const post = this.forum.getPost(this.postId);
// Recursively update values of referenced posts
this.propagateValue(post, initialPostValue);
} else {
// TODO: If the vote fails, distribute tokens.author among winning voters.
throw new Error("Vote did not pass -- we don't currently handle that!");
}
}
}

View File

@ -38,8 +38,8 @@
const expert1 = await newExpert();
const expert2 = await newExpert();
await newExpert();
const bench = (window.bench = new Bench("Bench", scene));
const forum = (window.forum = new Forum(bench, "Forum", scene));
const forum = (window.forum = new Forum("Forum", scene));
const bench = (window.bench = new Bench(forum, "Bench", scene));
const availability = (window.bench = new Availability(
bench,
"Availability",

View File

@ -39,8 +39,8 @@
const expert1 = await newExpert();
const expert2 = await newExpert();
await newExpert();
const bench = (window.bench = new Bench("Bench", scene));
const forum = (window.forum = new Forum(bench, "Forum", scene));
const forum = (window.forum = new Forum("Forum", scene));
const bench = (window.bench = new Bench(forum, "Bench", scene));
const updateDisplayValues = async () => {
for (const expert of experts) {