Fixes to validation pool
This commit is contained in:
parent
a481710cde
commit
e7120f87b1
|
@ -52,9 +52,9 @@ export class Bench extends Actor {
|
||||||
.reduce((acc, cur) => acc += cur, 0);
|
.reduce((acc, cur) => acc += cur, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
initiateValidationPool(authorId, {fee, duration, tokenLossRatio, contentiousDebate}) {
|
initiateValidationPool(authorId, {fee, duration, tokenLossRatio, contentiousDebate, signingPublicKey}) {
|
||||||
const validationPoolNumber = this.validationPools.size + 1;
|
const validationPoolNumber = this.validationPools.size + 1;
|
||||||
const validationPool = new ValidationPool(this, authorId, {fee, duration, tokenLossRatio, contentiousDebate},
|
const validationPool = new ValidationPool(this, authorId, {fee, duration, tokenLossRatio, contentiousDebate, signingPublicKey},
|
||||||
`pool${validationPoolNumber}`, scene);
|
`pool${validationPoolNumber}`, scene);
|
||||||
this.validationPools.set(validationPool.id, validationPool);
|
this.validationPools.set(validationPool.id, validationPool);
|
||||||
this.actions.createValidationPool.log(this, validationPool)
|
this.actions.createValidationPool.log(this, validationPool)
|
||||||
|
|
|
@ -17,7 +17,8 @@ export class Member extends Actor {
|
||||||
|
|
||||||
async initialize() {
|
async initialize() {
|
||||||
this.reputationKey = await CryptoUtil.generateAsymmetricKey();
|
this.reputationKey = await CryptoUtil.generateAsymmetricKey();
|
||||||
this.reputationPublicKey = await CryptoUtil.exportKey(this.reputationKey.publicKey);
|
// this.reputationPublicKey = await CryptoUtil.exportKey(this.reputationKey.publicKey);
|
||||||
|
this.reputationPublicKey = this.name;
|
||||||
this.status.set('Initialized');
|
this.status.set('Initialized');
|
||||||
this.activate();
|
this.activate();
|
||||||
return this;
|
return this;
|
||||||
|
@ -32,13 +33,17 @@ export class Member extends Actor {
|
||||||
await forumNode.receiveMessage(JSON.stringify(postMessage.toJSON()));
|
await forumNode.receiveMessage(JSON.stringify(postMessage.toJSON()));
|
||||||
}
|
}
|
||||||
|
|
||||||
initiateValidationPool(bench, options) {
|
async initiateValidationPool(bench, options) {
|
||||||
// For now, directly call bench.initiateValidationPool();
|
// For now, directly call bench.initiateValidationPool();
|
||||||
|
const signingKey = await CryptoUtil.generateAsymmetricKey();
|
||||||
|
const signingPublicKey = await CryptoUtil.exportKey(signingKey.publicKey)
|
||||||
this.actions.initiateValidationPool.log(this, bench);
|
this.actions.initiateValidationPool.log(this, bench);
|
||||||
return bench.initiateValidationPool(this.reputationPublicKey, options);
|
const pool = bench.initiateValidationPool(this.reputationPublicKey, {...options, signingPublicKey});
|
||||||
|
this.validationPools.set(pool.id, {signingPublicKey});
|
||||||
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
async castVote(validationPool, position, stake, lockingTime) {
|
async castVote(validationPool, {position, stake, lockingTime}) {
|
||||||
const signingKey = await CryptoUtil.generateAsymmetricKey();
|
const signingKey = await CryptoUtil.generateAsymmetricKey();
|
||||||
const signingPublicKey = await CryptoUtil.exportKey(signingKey.publicKey)
|
const signingPublicKey = await CryptoUtil.exportKey(signingKey.publicKey)
|
||||||
this.validationPools.set(validationPool.id, {signingPublicKey});
|
this.validationPools.set(validationPool.id, {signingPublicKey});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
const params = {
|
const params = {
|
||||||
mintingRatio: 1, // c1
|
mintingRatio: 1, // c1
|
||||||
stakeForWin: 0.5, // c2
|
stakeForWin: 0.5, // c2
|
||||||
stakeForAuthor: 0.5, // c3
|
// stakeForAuthor: 0.5, // c3 - For now we keep the default that stakeForAuthor = stakeForWin
|
||||||
winningRatio: 0.5, // c4
|
winningRatio: 0.5, // c4
|
||||||
quorum: 1, // c5
|
quorum: 0, // c5
|
||||||
activeVoterThreshold: null, // c6
|
activeVoterThreshold: null, // c6
|
||||||
voteDuration: { // c7
|
voteDuration: { // c7
|
||||||
min: 0,
|
min: 0,
|
||||||
|
|
|
@ -48,7 +48,6 @@ export class Scene {
|
||||||
|
|
||||||
deactivateAll() {
|
deactivateAll() {
|
||||||
for (const actor of this.actors.values()) {
|
for (const actor of this.actors.values()) {
|
||||||
console.log(actor);
|
|
||||||
while (actor.active) {
|
while (actor.active) {
|
||||||
actor.deactivate();
|
actor.deactivate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ const ValidationPoolStates = Object.freeze({
|
||||||
});
|
});
|
||||||
|
|
||||||
export class ValidationPool extends Actor {
|
export class ValidationPool extends Actor {
|
||||||
constructor(bench, authorId, {fee, duration, tokenLossRatio, contentiousDebate = false}, name, scene) {
|
constructor(bench, authorId, {signingPublicKey, fee, duration, tokenLossRatio, contentiousDebate = false}, name, scene) {
|
||||||
super(name, scene);
|
super(name, scene);
|
||||||
// If contentiousDebate = true, we will follow the progression defined by getTokenLossRatio()
|
// If contentiousDebate = true, we will follow the progression defined by getTokenLossRatio()
|
||||||
if (!contentiousDebate && (tokenLossRatio < 0 || tokenLossRatio > 1 || [null, undefined].includes(tokenLossRatio))) {
|
if (!contentiousDebate && (tokenLossRatio < 0 || tokenLossRatio > 1 || [null, undefined].includes(tokenLossRatio))) {
|
||||||
|
@ -33,9 +33,10 @@ export class ValidationPool extends Actor {
|
||||||
this.tokens = {
|
this.tokens = {
|
||||||
for: fee * params.mintingRatio * params.stakeForWin,
|
for: fee * params.mintingRatio * params.stakeForWin,
|
||||||
against: fee * params.mintingRatio * (1 - params.stakeForWin),
|
against: fee * params.mintingRatio * (1 - params.stakeForWin),
|
||||||
author: fee * params.mintingRatio * params.stakeForAuthor,
|
// author: fee * params.mintingRatio * params.stakeForAuthor,
|
||||||
}
|
}
|
||||||
// TODO: Consider availability stakes
|
// TODO: Consider availability stakes
|
||||||
|
this.castVote(signingPublicKey, true, this.tokens.for, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
castVote(signingPublicKey, position, stake, lockingTime) {
|
castVote(signingPublicKey, position, stake, lockingTime) {
|
||||||
|
@ -120,6 +121,7 @@ export class ValidationPool extends Actor {
|
||||||
// TODO: If quorum is not met, what should happen?
|
// TODO: If quorum is not met, what should happen?
|
||||||
if (!quorumMet) {
|
if (!quorumMet) {
|
||||||
this.deactivate();
|
this.deactivate();
|
||||||
|
// console.log("Quorum is not met", {upvoteValue, downvoteValue, activeAvailableReputation});
|
||||||
throw new Error("Quorum is not met");
|
throw new Error("Quorum is not met");
|
||||||
}
|
}
|
||||||
return votePasses && quorumMet;
|
return votePasses && quorumMet;
|
||||||
|
@ -128,19 +130,23 @@ export class ValidationPool extends Actor {
|
||||||
distributeTokens(result) {
|
distributeTokens(result) {
|
||||||
// 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
|
||||||
this.bench.reputations.addTokens(this.authorId, this.tokens.author);
|
if (result === true) {
|
||||||
// Reward the vote winners, in proportion to their stakes
|
// console.log("awarding to author", {id: this.authorId, tokens: this.tokens.for});
|
||||||
const tokensForWinners = result ? this.tokens.for : this.tokens.against;
|
this.bench.reputations.addTokens(this.authorId, this.tokens.for);
|
||||||
const winningVotes = this.listVotes(result);
|
// Reward the vote winners, in proportion to their stakes
|
||||||
const totalStakes = Array.from(winningVotes.values())
|
const tokensForWinners = this.tokens.against;
|
||||||
.map(({stake}) => stake).reduce((acc, cur) => acc += cur, 0);
|
const winningVotes = this.listVotes(result);
|
||||||
if (!totalStakes) {
|
const totalStakes = Array.from(winningVotes.values())
|
||||||
return;
|
.map(({stake}) => stake).reduce((acc, cur) => acc += cur, 0);
|
||||||
}
|
if (!totalStakes) {
|
||||||
for (const [signingPublicKey, {stake}] of winningVotes.entries()) {
|
return;
|
||||||
const {reputationPublicKey} = this.voters.get(signingPublicKey);
|
}
|
||||||
const reward = tokensForWinners * stake / totalStakes;
|
for (const [signingPublicKey, {stake}] of winningVotes.entries()) {
|
||||||
this.bench.reputations.addTokens(reputationPublicKey, reward);
|
const {reputationPublicKey} = this.voters.get(signingPublicKey);
|
||||||
|
const reward = tokensForWinners * stake / totalStakes;
|
||||||
|
// console.log("awarding to winning voter", {id: reputationPublicKey, tokens: reward, stake, totalStakes, tokensForWinners});
|
||||||
|
this.bench.reputations.addTokens(reputationPublicKey, reward);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
};
|
};
|
||||||
const graphDefinition = 'graph TB\na-->b';
|
const graphDefinition = 'graph TB\na-->b';
|
||||||
const graph = await mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
|
const graph = await mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg);
|
||||||
console.log("executed...");
|
|
||||||
console.log(graph);
|
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.innerHTML = graph;
|
div.innerHTML = graph;
|
||||||
document.body.append(div);
|
document.body.append(div);
|
||||||
|
|
|
@ -27,34 +27,35 @@ await delay(1000);
|
||||||
|
|
||||||
// First member can self-approve
|
// First member can self-approve
|
||||||
{
|
{
|
||||||
const pool = member1.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
const pool = await member1.initiateValidationPool(bench, {fee: 7, duration: 1000, tokenLossRatio: 1});
|
||||||
await member1.castVote(pool, true, 0, 0);
|
// await member1.castVote(pool, true, 0, 0);
|
||||||
await member1.revealIdentity(pool); // Vote passes
|
await member1.revealIdentity(pool); // Vote passes
|
||||||
await updateDisplayValues();
|
await updateDisplayValues();
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failure example: second member can not self-approve
|
// // Failure example: second member can not self-approve
|
||||||
try {
|
// try {
|
||||||
const pool = member2.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
// const pool = member2.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
||||||
await member2.castVote(pool, true, 0, 0);
|
// await member2.castVote(pool, true, 0, 0);
|
||||||
await member2.revealIdentity(pool); // Quorum not met!
|
// await member2.revealIdentity(pool); // Quorum not met!
|
||||||
await updateDisplayValues();
|
// await updateDisplayValues();
|
||||||
await delay(1000);
|
// await delay(1000);
|
||||||
} catch(e) {
|
// } catch(e) {
|
||||||
if (e.message.match(/Quorum is not met/)) {
|
// if (e.message.match(/Quorum is not met/)) {
|
||||||
console.log("Caught expected error: Quorum not met")
|
// console.log("Caught expected error: Quorum not met")
|
||||||
} else {
|
// } else {
|
||||||
console.error("Unexpected error")
|
// console.error("Unexpected error")
|
||||||
throw e;
|
// throw e;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Second member must be approved by first member
|
// Second member must be approved by first member
|
||||||
{
|
{
|
||||||
const pool = member2.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
const pool = await member2.initiateValidationPool(bench, {fee: 1, duration: 1000, tokenLossRatio: 1});
|
||||||
await member1.castVote(pool, true, 0.5, 1);
|
await member1.castVote(pool, {position: true, stake: 4, lockingTime: 0});
|
||||||
await member1.revealIdentity(pool); // Vote passes
|
await member1.revealIdentity(pool);
|
||||||
|
await member2.revealIdentity(pool); // Vote passes
|
||||||
await updateDisplayValues();
|
await updateDisplayValues();
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue