Additional cleanup in preparation for forum test

This commit is contained in:
Ladd Hoffman 2023-01-04 15:18:29 -06:00
parent 07b992e572
commit 8980885881
11 changed files with 117 additions and 88 deletions

View File

@ -40,7 +40,7 @@ Should availability registration encumber reputation?
- Is a particular availability stake amount required? - Is a particular availability stake amount required?
Currently I support updating the staked amount. Currently we support updating the staked amount.
Seems like a soft protocol thing. Seems like a soft protocol thing.
A given DAO can have a formula for deciding appropriate amounts. A given DAO can have a formula for deciding appropriate amounts.
@ -59,7 +59,7 @@ The following was a code comment on `Business.submitRequest(fee, ...)`:
Does the following make sense? Does the following make sense?
We will link the forum to the bench We will link the forum to the bench
An author of a forum post /_ ? is always? can be? _/ a reputation holder. An author of a forum post /_ ? is always? can be? _/ a reputation holder.
This is what we call a member. Let's update that terminology to be `reputationHolder`. This is what we call a expert. Let's update that terminology to be `reputationHolder`.
That's too long, though. Let's rename it to `expert`. That's too long, though. Let's rename it to `expert`.
So we want to aim for the situation where the author of a forum post is an expert. So we want to aim for the situation where the author of a forum post is an expert.
For now let's try thinking of them as experts no matter what; For now let's try thinking of them as experts no matter what;

View File

@ -57,6 +57,9 @@ export class Actor {
} }
setValue(label, value) { setValue(label, value) {
if (typeof value === 'number') {
value = value.toFixed(2);
}
let displayValue = this.values.get(label); let displayValue = this.values.get(label);
if (!displayValue) { if (!displayValue) {
displayValue = this.scene.addDisplayValue(`${this.name} ${label}`); displayValue = this.scene.addDisplayValue(`${this.name} ${label}`);

View File

@ -55,9 +55,7 @@ export class Bench extends Actor {
.reduce((acc, cur) => (acc += cur), 0); .reduce((acc, cur) => (acc += cur), 0);
} }
initiateValidationPool( initiateValidationPool({
authorId,
{
postId, postId,
fee, fee,
duration, duration,
@ -66,12 +64,10 @@ export class Bench extends Actor {
signingPublicKey, signingPublicKey,
authorStake, authorStake,
anonymous, anonymous,
}, }) {
) {
const validationPoolNumber = this.validationPools.size + 1; const validationPoolNumber = this.validationPools.size + 1;
const validationPool = new ValidationPool( const validationPool = new ValidationPool(
this, this,
authorId,
{ {
postId, postId,
fee, fee,

View File

@ -61,7 +61,7 @@ export class Business extends Actor {
// Validation pool supports secret ballots but we aren't using that here, since we want // Validation pool supports secret ballots but we aren't using that here, since we want
// the post to be attributable to the reputation holder. // the post to be attributable to the reputation holder.
this.actions.initiateValidationPool.log(this, this.bench); this.actions.initiateValidationPool.log(this, this.bench);
const pool = await this.bench.initiateValidationPool(reputationPublicKey, { const pool = await this.bench.initiateValidationPool({
postId: post.id, postId: post.id,
fee: request.fee, fee: request.fee,
duration, duration,

View File

@ -44,20 +44,28 @@ export class Expert extends Actor {
return forum.addPost(this.reputationPublicKey, postContent); return forum.addPost(this.reputationPublicKey, postContent);
} }
async initiateValidationPool(bench, options) { async submitPostWithFee(bench, forum, postContent, poolOptions) {
this.actions.submitPost.log(this, forum);
const postId = await forum.addPost(this.reputationPublicKey, postContent);
const pool = await this.initiateValidationPool(bench, { ...poolOptions, postId, anonymous: false });
return { postId, pool };
}
async initiateValidationPool(bench, poolOptions) {
// For now, directly call bench.initiateValidationPool(); // For now, directly call bench.initiateValidationPool();
if (poolOptions.anonymous) {
const signingKey = await CryptoUtil.generateAsymmetricKey(); const signingKey = await CryptoUtil.generateAsymmetricKey();
const signingPublicKey = await CryptoUtil.exportKey(signingKey.publicKey); poolOptions.signingPublicKey = await CryptoUtil.exportKey(signingKey.publicKey);
} else {
poolOptions.signingPublicKey = this.reputationPublicKey;
}
this.actions.initiateValidationPool.log( this.actions.initiateValidationPool.log(
this, this,
bench, bench,
`(fee: ${options.fee})`, `(fee: ${poolOptions.fee})`,
); );
const pool = bench.initiateValidationPool(this.reputationPublicKey, { const pool = bench.initiateValidationPool(poolOptions);
...options, this.validationPools.set(pool.id, poolOptions);
signingPublicKey,
});
this.validationPools.set(pool.id, { signingPublicKey });
return pool; return pool;
} }

View File

@ -28,7 +28,6 @@ export class Scene {
darkMode: true, darkMode: true,
primaryColor: '#2a5b6c', primaryColor: '#2a5b6c',
primaryTextColor: '#b6b6b6', primaryTextColor: '#b6b6b6',
fontFamily: 'monospace',
noteBkgColor: '#516f77', noteBkgColor: '#516f77',
noteTextColor: '#cecece', noteTextColor: '#cecece',
}, },

View File

@ -16,7 +16,6 @@ const ValidationPoolStates = Object.freeze({
export class ValidationPool extends Actor { export class ValidationPool extends Actor {
constructor( constructor(
bench, bench,
authorId,
{ {
postId, postId,
signingPublicKey, signingPublicKey,
@ -61,7 +60,8 @@ export class ValidationPool extends Actor {
this.bench = bench; this.bench = bench;
this.id = CryptoUtil.randomUUID(); this.id = CryptoUtil.randomUUID();
this.dateStart = new Date(); this.dateStart = new Date();
this.authorId = authorId; this.authorSigningPublicKey = signingPublicKey;
this.anonymous = anonymous;
this.fee = fee; this.fee = fee;
this.duration = duration; this.duration = duration;
this.tokenLossRatio = tokenLossRatio; this.tokenLossRatio = tokenLossRatio;
@ -201,10 +201,17 @@ export class ValidationPool extends Actor {
} }
distributeTokens(result) { distributeTokens(result) {
let authorReputationPublicKey;
if (this.anonymous) {
const author = this.voters.get(this.authorSigningPublicKey);
authorReputationPublicKey = author.reputationPublicKey;
} else {
authorReputationPublicKey = this.authorSigningPublicKey;
}
// Reward the author // Reward the author
// TODO: If the vote fails, distribute tokens.author among winning voters // TODO: If the vote fails, distribute tokens.author among winning voters
if (result === true) { if (result === true) {
this.bench.reputations.addTokens(this.authorId, this.tokens.for); this.bench.reputations.addTokens(authorReputationPublicKey, this.tokens.for);
// Reward the vote winners, in proportion to their stakes // Reward the vote winners, in proportion to their stakes
const tokensForWinners = this.tokens.against; const tokensForWinners = this.tokens.against;
const winningVotes = this.listVotes(result); const winningVotes = this.listVotes(result);

View File

@ -1,6 +1,5 @@
body { body {
background-color: #1b3d49; background-color: #09343f;
background-color: #114754;
color: #b6b6b6; color: #b6b6b6;
font-family: monospace; font-family: monospace;
font-size: 8pt; font-size: 8pt;

View File

@ -26,17 +26,17 @@
"sequenceDiagram" "sequenceDiagram"
)); ));
const members = (window.members = []); const experts = (window.experts = []);
const newExpert = async () => { const newExpert = async () => {
const index = members.length; const index = experts.length;
const name = `Expert${index + 1}`; const name = `Expert${index + 1}`;
const member = await new Expert(name, scene).initialize(); const expert = await new Expert(name, scene).initialize();
members.push(member); experts.push(expert);
return member; return expert;
}; };
const member1 = await newExpert(); const expert1 = await newExpert();
const member2 = await newExpert(); const expert2 = await newExpert();
await newExpert(); await newExpert();
const bench = (window.bench = new Bench("Bench", scene)); const bench = (window.bench = new Bench("Bench", scene));
const forum = (window.forum = new Forum(bench, "Forum", scene)); const forum = (window.forum = new Forum(bench, "Forum", scene));
@ -55,10 +55,10 @@
const requestor = new Public("Public", scene); const requestor = new Public("Public", scene);
const updateDisplayValues = async () => { const updateDisplayValues = async () => {
for (const member of members) { for (const expert of experts) {
member.setValue( expert.setValue(
"rep", "rep",
bench.reputations.getTokens(member.reputationPublicKey) bench.reputations.getTokens(expert.reputationPublicKey)
); );
} }
bench.setValue("total rep", bench.getTotalReputation()); bench.setValue("total rep", bench.getTotalReputation());
@ -73,10 +73,10 @@
const getActiveWorker = async () => { const getActiveWorker = async () => {
let worker; let worker;
let request; let request;
for (const member of members) { for (const expert of experts) {
request = await member.getAssignedWork(availability, business); request = await expert.getAssignedWork(availability, business);
if (request) { if (request) {
worker = member; worker = expert;
worker.actions.getAssignedWork.log(worker, availability); worker.actions.getAssignedWork.log(worker, availability);
worker.activate(); worker.activate();
break; break;
@ -86,9 +86,9 @@
}; };
const voteForWorkEvidence = async (worker, pool) => { const voteForWorkEvidence = async (worker, pool) => {
for (const member of members) { for (const expert of experts) {
if (member !== worker) { if (expert !== worker) {
await member.castVote(pool, { await expert.castVote(pool, {
position: true, position: true,
stake: 1, stake: 1,
anonymous: false, anonymous: false,
@ -100,8 +100,8 @@
await updateDisplayValuesAndDelay(); await updateDisplayValuesAndDelay();
// Populate availability pool // Populate availability pool
await member1.registerAvailability(availability, 1); await expert1.registerAvailability(availability, 1);
await member2.registerAvailability(availability, 1); await expert2.registerAvailability(availability, 1);
await updateDisplayValuesAndDelay(); await updateDisplayValuesAndDelay();
// Submit work request // Submit work request

View File

@ -27,33 +27,26 @@
"sequenceDiagram" "sequenceDiagram"
)); ));
const members = (window.members = []); const experts = (window.experts = []);
const newExpert = async () => { const newExpert = async () => {
const index = members.length; const index = experts.length;
const name = `Expert${index + 1}`; const name = `Expert${index + 1}`;
const member = await new Expert(name, scene).initialize(); const expert = await new Expert(name, scene).initialize();
members.push(member); experts.push(expert);
return member; return expert;
}; };
const posts = (window.posts = []); const expert1 = await newExpert();
const newPost = async (author, content, citations) => { const expert2 = await newExpert();
const postContent = new PostContent({ hello: "there" });
const postId = await member1.submitPost(forum, postContent1);
return postId;
};
const member1 = await newExpert();
const member2 = await newExpert();
await newExpert(); await newExpert();
const bench = (window.bench = new Bench("Bench", scene)); const bench = (window.bench = new Bench("Bench", scene));
const forum = (window.forum = new Forum(bench, "Forum", scene)); const forum = (window.forum = new Forum(bench, "Forum", scene));
const updateDisplayValues = async () => { const updateDisplayValues = async () => {
for (const member of members) { for (const expert of experts) {
member.setValue( expert.setValue(
"rep", "rep",
bench.reputations.getTokens(member.reputationPublicKey) bench.reputations.getTokens(expert.reputationPublicKey)
); );
} }
bench.setValue("total rep", bench.getTotalReputation()); bench.setValue("total rep", bench.getTotalReputation());
@ -67,15 +60,39 @@
await updateDisplayValuesAndDelay(); await updateDisplayValuesAndDelay();
const postId1 = await member1.submitPost( const { postId: postId1, pool: pool1 } = await expert1.submitPostWithFee(
bench,
forum, forum,
new PostContent({ hello: "there" }) new PostContent({ hello: "there" }),
{
fee: 10,
duration: 1000,
tokenLossRatio: 1,
}
); );
await updateDisplayValuesAndDelay(); await updateDisplayValuesAndDelay();
const postId2 = await member1.submitPost( await expert2.castVote(pool1, { position: true, stake: 1, anonymous: false });
await updateDisplayValuesAndDelay();
await pool1.evaluateWinningConditions();
await updateDisplayValuesAndDelay();
const { pool: pool2 } = await expert2.submitPostWithFee(
bench,
forum, forum,
new PostContent({ hello: "to you as well" }).addCitation(postId1, 0.5) new PostContent({ hello: "to you as well" }).addCitation(postId1, 0.5),
{
fee: 10,
duration: 1000,
tokenLossRatio: 1,
}
); );
await updateDisplayValuesAndDelay(); await updateDisplayValuesAndDelay();
await expert1.castVote(pool2, { position: true, stake: 1, anonymous: false });
await updateDisplayValuesAndDelay();
await pool2.evaluateWinningConditions();
await updateDisplayValuesAndDelay();
</script> </script>

View File

@ -19,24 +19,24 @@
const scene = (window.scene = new Scene("Validation Pool test", rootBox).log( const scene = (window.scene = new Scene("Validation Pool test", rootBox).log(
"sequenceDiagram" "sequenceDiagram"
)); ));
const member1 = (window.member1 = await new Expert( const expert1 = (window.expert1 = await new Expert(
"Expert1", "Expert1",
scene scene
).initialize()); ).initialize());
const member2 = (window.member2 = await new Expert( const expert2 = (window.expert2 = await new Expert(
"Expert2", "Expert2",
scene scene
).initialize()); ).initialize());
const bench = (window.bench = new Bench("Bench", scene)); const bench = (window.bench = new Bench("Bench", scene));
const updateDisplayValues = async () => { const updateDisplayValues = async () => {
member1.setValue( expert1.setValue(
"rep", "rep",
bench.reputations.getTokens(member1.reputationPublicKey) bench.reputations.getTokens(expert1.reputationPublicKey)
); );
member2.setValue( expert2.setValue(
"rep", "rep",
bench.reputations.getTokens(member2.reputationPublicKey) bench.reputations.getTokens(expert2.reputationPublicKey)
); );
bench.setValue("total rep", bench.getTotalReputation()); bench.setValue("total rep", bench.getTotalReputation());
// With params.lockingTimeExponent = 0 and params.activeVoterThreshold = null, // With params.lockingTimeExponent = 0 and params.activeVoterThreshold = null,
@ -50,14 +50,14 @@
updateDisplayValues(); updateDisplayValues();
await delay(1000); await delay(1000);
// First member can self-approve // First expert can self-approve
{ {
const pool = await member1.initiateValidationPool(bench, { const pool = await expert1.initiateValidationPool(bench, {
fee: 7, fee: 7,
duration: 1000, duration: 1000,
tokenLossRatio: 1, tokenLossRatio: 1,
}); });
await member1.revealIdentity(pool); await expert1.revealIdentity(pool);
// Attempting to evaluate winning conditions before the duration has expired // Attempting to evaluate winning conditions before the duration has expired
// should result in an exception // should result in an exception
try { try {
@ -78,14 +78,14 @@
await delay(1000); await delay(1000);
} }
// Failure example: second member can not self-approve // Failure example: second expert can not self-approve
try { try {
const pool = await member2.initiateValidationPool(bench, { const pool = await expert2.initiateValidationPool(bench, {
fee: 1, fee: 1,
duration: 1000, duration: 1000,
tokenLossRatio: 1, tokenLossRatio: 1,
}); });
await member2.revealIdentity(pool); await expert2.revealIdentity(pool);
await delay(1000); await delay(1000);
await pool.evaluateWinningConditions(); // Quorum not met! await pool.evaluateWinningConditions(); // Quorum not met!
await updateDisplayValues(); await updateDisplayValues();
@ -99,16 +99,16 @@
} }
} }
// Second member must be approved by first member // Second expert must be approved by first expert
{ {
const pool = await member2.initiateValidationPool(bench, { const pool = await expert2.initiateValidationPool(bench, {
fee: 1, fee: 1,
duration: 1000, duration: 1000,
tokenLossRatio: 1, tokenLossRatio: 1,
}); });
await member1.castVote(pool, { position: true, stake: 4, lockingTime: 0 }); await expert1.castVote(pool, { position: true, stake: 4, lockingTime: 0 });
await member1.revealIdentity(pool); await expert1.revealIdentity(pool);
await member2.revealIdentity(pool); await expert2.revealIdentity(pool);
await delay(1000); await delay(1000);
await pool.evaluateWinningConditions(); // Vote passes await pool.evaluateWinningConditions(); // Vote passes
await updateDisplayValues(); await updateDisplayValues();