When propagating value, apply leaching before donations
This commit is contained in:
parent
5fc5bbe0b5
commit
a48d14905c
|
@ -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.
|
|
@ -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.
|
||||||
|
|
||||||
|
---
|
|
@ -144,8 +144,7 @@ export class Forum extends ReputationHolder {
|
||||||
}) {
|
}) {
|
||||||
const postVertex = edge.to;
|
const postVertex = edge.to;
|
||||||
const post = postVertex?.data;
|
const post = postVertex?.data;
|
||||||
const balanceFromInbound = this.posts.getEdgeWeight(BALANCE, edge.from, edge.to) ?? 0;
|
this.actions.propagateValue.log(edge.from.data, post, `(${increment})`);
|
||||||
this.actions.propagateValue.log(edge.from.data, post, `(${increment}) balance (${balanceFromInbound})`);
|
|
||||||
|
|
||||||
if (!!params.referenceChainLimit && depth > params.referenceChainLimit) {
|
if (!!params.referenceChainLimit && depth > params.referenceChainLimit) {
|
||||||
this.actions.propagateValue.log(
|
this.actions.propagateValue.log(
|
||||||
|
@ -164,37 +163,47 @@ export class Forum extends ReputationHolder {
|
||||||
depth,
|
depth,
|
||||||
value: post.value,
|
value: post.value,
|
||||||
increment,
|
increment,
|
||||||
balanceFromInbound,
|
|
||||||
initialNegative,
|
initialNegative,
|
||||||
});
|
});
|
||||||
|
|
||||||
let totalOutboundAmount = 0;
|
const propagate = async (positive) => {
|
||||||
|
let totalOutboundAmount = 0;
|
||||||
for (const citationEdge of postVertex.getEdges(CITATION, true)) {
|
const citationEdges = postVertex.getEdges(CITATION, true)
|
||||||
const { weight } = citationEdge;
|
.filter(({ weight }) => (positive ? weight > 0 : weight < 0));
|
||||||
let outboundAmount = weight * increment;
|
for (const citationEdge of citationEdges) {
|
||||||
const balanceToOutbound = this.posts.getEdgeWeight(BALANCE, citationEdge.from, citationEdge.to) ?? 0;
|
const { weight } = citationEdge;
|
||||||
// We need to ensure that we propagate no more reputation than we leached
|
let outboundAmount = weight * increment;
|
||||||
if (initialNegative) {
|
const balanceToOutbound = this.posts.getEdgeWeight(BALANCE, citationEdge.from, citationEdge.to) ?? 0;
|
||||||
outboundAmount = outboundAmount < 0
|
// We need to ensure that we at most undo the prior effects of this post
|
||||||
? Math.max(outboundAmount, -balanceToOutbound)
|
if (initialNegative) {
|
||||||
: Math.min(outboundAmount, -balanceToOutbound);
|
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) {
|
return totalOutboundAmount;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 rawNewValue = post.value + increment;
|
||||||
const newValue = Math.max(0, rawNewValue);
|
const newValue = Math.max(0, rawNewValue);
|
||||||
const appliedIncrement = newValue - post.value;
|
const appliedIncrement = newValue - post.value;
|
||||||
|
|
|
@ -28,8 +28,8 @@ describe('Forum', () => {
|
||||||
{ postId: posts[1], weight: 1 },
|
{ postId: posts[1], weight: 1 },
|
||||||
]);
|
]);
|
||||||
forum.getPost(posts[0]).value.should.equal(0);
|
forum.getPost(posts[0]).value.should.equal(0);
|
||||||
forum.getPost(posts[1]).value.should.equal(20);
|
forum.getPost(posts[1]).value.should.equal(30);
|
||||||
forum.getPost(posts[2]).value.should.equal(10);
|
forum.getPost(posts[2]).value.should.equal(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,8 +44,8 @@ describe('Forum', () => {
|
||||||
{ postId: posts[2], weight: 1 },
|
{ postId: posts[2], weight: 1 },
|
||||||
]);
|
]);
|
||||||
forum.getPost(posts[0]).value.should.equal(0);
|
forum.getPost(posts[0]).value.should.equal(0);
|
||||||
forum.getPost(posts[1]).value.should.equal(20);
|
forum.getPost(posts[1]).value.should.equal(30);
|
||||||
forum.getPost(posts[2]).value.should.equal(10);
|
forum.getPost(posts[2]).value.should.equal(0);
|
||||||
forum.getPost(posts[3]).value.should.equal(0);
|
forum.getPost(posts[3]).value.should.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ describe('Forum', () => {
|
||||||
]);
|
]);
|
||||||
console.log('test5', { posts });
|
console.log('test5', { posts });
|
||||||
forum.getPost(posts[0]).value.should.equal(0);
|
forum.getPost(posts[0]).value.should.equal(0);
|
||||||
forum.getPost(posts[1]).value.should.equal(30);
|
forum.getPost(posts[1]).value.should.equal(40);
|
||||||
forum.getPost(posts[2]).value.should.equal(10);
|
forum.getPost(posts[2]).value.should.equal(0);
|
||||||
forum.getPost(posts[3]).value.should.equal(0);
|
forum.getPost(posts[3]).value.should.equal(0);
|
||||||
forum.getPost(posts[4]).value.should.equal(0);
|
forum.getPost(posts[4]).value.should.equal(0);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue