From a48d14905c298b7410a1b81362389a5c642106ae Mon Sep 17 00:00:00 2001 From: Ladd Hoffman Date: Tue, 31 Jan 2023 09:28:06 -0600 Subject: [PATCH] When propagating value, apply leaching before donations --- forum-network/notes/protocol.md | 37 +++++++++++ forum-network/notes/work.md | 19 ++++++ forum-network/src/classes/forum.js | 63 +++++++++++-------- .../src/tests/scripts/forum/forum3.test.js | 4 +- .../src/tests/scripts/forum/forum4.test.js | 8 +-- 5 files changed, 98 insertions(+), 33 deletions(-) create mode 100644 forum-network/notes/protocol.md create mode 100644 forum-network/notes/work.md diff --git a/forum-network/notes/protocol.md b/forum-network/notes/protocol.md new file mode 100644 index 0000000..31aa73a --- /dev/null +++ b/forum-network/notes/protocol.md @@ -0,0 +1,37 @@ +The communication protocol(s) among network nodes +Each communication protocol among network nodes +has its own purpose +has its own assumptions, expectations, requirements, constraints + +I think it makes sense to identify the constraints for our protocols. + +We need the general public to be able to reliably + +- Query information about the reputation WDAG +- Submit requests and fees for work +- Obtain the products of the work submitted by forum experts + +Suppose we want only the requestor to be able to access a given work product. +(Why might we want this?) +Then the (soft) protocol for reviewing the work product would consist of +validating a signature by the requestor, attesting to their acceptance of the work product. + +Alternatively access could be permitted to some group, such as reputation holders (a.k.a. experts). + +Otherwise, for maximum utility, we would want to make the work products available indefinitely, as valuable artifacts. +Value here can be equated to the expected fees that the work products will help attract, which can in turn be equated to +reputation awarded to authors and reviewers of the work products. + +Thus, the work of making the artifacts available must be funded. + +The work of participating in a gossip / forum node consensus protocol and validating forum chain blocks must also be funded. + +Suppose we have a storage contract. + +- There can be a market for specific pledges of storage. + - buy: (amount, duration, price) + - sell: (amount, duration, price) +- Governance: Management of storage price + - may negotiate via loose -> tight binding traversal forum post sequence + - reputation in accordance with majority opinions on price parameters +- Verification of storage must occur by (randomly) querying the storage nodes and validating their responses. diff --git a/forum-network/notes/work.md b/forum-network/notes/work.md new file mode 100644 index 0000000..1f7c05e --- /dev/null +++ b/forum-network/notes/work.md @@ -0,0 +1,19 @@ +This system is meant to represent a body of experts receiving fees to perform work. +Experts register their availability to receive work via the availability contract. +Request and associated fees are sumbitted via the business contract. +Evidence of the work performed is submitted as a post to the forum. +A successful validation pool ratifies the post. +Reputation is minted and distributed. +Fees are distributed. + +What if we want the work to be block production for a blockchain? +Then to perform this work, an expert will need to participate in a communications network +such that they can confidently arrive at a majority view of each block. +Or else must at least be able to attest that a proposed block is valid, +meaning that it + +- does not conflict with what the node believes to be the majority view +- includes what the node believes must be included according to the majority view + note that with this scheme there be muliple possible valid proposed blocks. + +--- diff --git a/forum-network/src/classes/forum.js b/forum-network/src/classes/forum.js index d1b1dbf..7ea03b1 100644 --- a/forum-network/src/classes/forum.js +++ b/forum-network/src/classes/forum.js @@ -144,8 +144,7 @@ export class Forum extends ReputationHolder { }) { const postVertex = edge.to; const post = postVertex?.data; - const balanceFromInbound = this.posts.getEdgeWeight(BALANCE, edge.from, edge.to) ?? 0; - this.actions.propagateValue.log(edge.from.data, post, `(${increment}) balance (${balanceFromInbound})`); + this.actions.propagateValue.log(edge.from.data, post, `(${increment})`); if (!!params.referenceChainLimit && depth > params.referenceChainLimit) { this.actions.propagateValue.log( @@ -164,37 +163,47 @@ export class Forum extends ReputationHolder { depth, value: post.value, increment, - balanceFromInbound, initialNegative, }); - let totalOutboundAmount = 0; - - for (const citationEdge of postVertex.getEdges(CITATION, true)) { - const { weight } = citationEdge; - let outboundAmount = weight * increment; - const balanceToOutbound = this.posts.getEdgeWeight(BALANCE, citationEdge.from, citationEdge.to) ?? 0; - // We need to ensure that we propagate no more reputation than we leached - if (initialNegative) { - outboundAmount = outboundAmount < 0 - ? Math.max(outboundAmount, -balanceToOutbound) - : Math.min(outboundAmount, -balanceToOutbound); + const propagate = async (positive) => { + let totalOutboundAmount = 0; + const citationEdges = postVertex.getEdges(CITATION, true) + .filter(({ weight }) => (positive ? weight > 0 : weight < 0)); + for (const citationEdge of citationEdges) { + const { weight } = citationEdge; + let outboundAmount = weight * increment; + const balanceToOutbound = this.posts.getEdgeWeight(BALANCE, citationEdge.from, citationEdge.to) ?? 0; + // We need to ensure that we at most undo the prior effects of this post + if (initialNegative) { + outboundAmount = outboundAmount < 0 + ? Math.max(outboundAmount, -balanceToOutbound) + : Math.min(outboundAmount, -balanceToOutbound); + } + if (Math.abs(outboundAmount) > EPSILON) { + const refundFromOutbound = await this.propagateValue(citationEdge, { + rewardsAccumulator, + increment: outboundAmount, + depth: depth + 1, + initialNegative: initialNegative || (depth === 0 && outboundAmount < 0), + }); + outboundAmount -= refundFromOutbound; + this.posts.setEdgeWeight(BALANCE, citationEdge.from, citationEdge.to, balanceToOutbound + outboundAmount); + totalOutboundAmount += outboundAmount; + } } - if (Math.abs(outboundAmount) > EPSILON) { - const refundFromOutbound = await this.propagateValue(citationEdge, { - rewardsAccumulator, - increment: outboundAmount, - depth: depth + 1, - initialNegative: initialNegative || (depth === 0 && outboundAmount < 0), - }); - outboundAmount -= refundFromOutbound; - this.posts.setEdgeWeight(BALANCE, citationEdge.from, citationEdge.to, balanceToOutbound + outboundAmount); - totalOutboundAmount += outboundAmount; - } - } + return totalOutboundAmount; + }; - increment -= totalOutboundAmount * params.leachingValue; + // First, leach value via negative citations + const totalLeachingAmount = await propagate(false); + increment -= totalLeachingAmount * params.leachingValue; + // Now propagate value via positive citations + const totalDonationAmount = await propagate(true); + increment -= totalDonationAmount * params.leachingValue; + + // Apply the remaining increment to the present post const rawNewValue = post.value + increment; const newValue = Math.max(0, rawNewValue); const appliedIncrement = newValue - post.value; diff --git a/forum-network/src/tests/scripts/forum/forum3.test.js b/forum-network/src/tests/scripts/forum/forum3.test.js index fb2a63e..e5d5038 100644 --- a/forum-network/src/tests/scripts/forum/forum3.test.js +++ b/forum-network/src/tests/scripts/forum/forum3.test.js @@ -28,8 +28,8 @@ describe('Forum', () => { { postId: posts[1], weight: 1 }, ]); forum.getPost(posts[0]).value.should.equal(0); - forum.getPost(posts[1]).value.should.equal(20); - forum.getPost(posts[2]).value.should.equal(10); + forum.getPost(posts[1]).value.should.equal(30); + forum.getPost(posts[2]).value.should.equal(0); }); }); }); diff --git a/forum-network/src/tests/scripts/forum/forum4.test.js b/forum-network/src/tests/scripts/forum/forum4.test.js index 921ac58..0ae804d 100644 --- a/forum-network/src/tests/scripts/forum/forum4.test.js +++ b/forum-network/src/tests/scripts/forum/forum4.test.js @@ -44,8 +44,8 @@ describe('Forum', () => { { postId: posts[2], weight: 1 }, ]); forum.getPost(posts[0]).value.should.equal(0); - forum.getPost(posts[1]).value.should.equal(20); - forum.getPost(posts[2]).value.should.equal(10); + forum.getPost(posts[1]).value.should.equal(30); + forum.getPost(posts[2]).value.should.equal(0); forum.getPost(posts[3]).value.should.equal(0); }); @@ -55,8 +55,8 @@ describe('Forum', () => { ]); console.log('test5', { posts }); forum.getPost(posts[0]).value.should.equal(0); - forum.getPost(posts[1]).value.should.equal(30); - forum.getPost(posts[2]).value.should.equal(10); + forum.getPost(posts[1]).value.should.equal(40); + forum.getPost(posts[2]).value.should.equal(0); forum.getPost(posts[3]).value.should.equal(0); forum.getPost(posts[4]).value.should.equal(0); });