This page is designed to detail a proposed peer-to-peer economy system, based on the Ripple project which, like everything else in the OpenP2P library, can be constructed in a customizable form so it can be used by other components.
Many systems benefit from a economy so that it is possible to measure the contributions of individual nodes, ensuring that they can only consume as many resources as they contribute to the system. For example, it can be used in OFTorrent, or for normal torrents, to encourage nodes to seed blocks/files.
The primary aims are clearly:
- Payments resolve quickly (typically, resolution in under 10 seconds is desirable)
- Accurate accounting (i.e. nodes can't create money)
There are also additional standard requirements for peer-to-peer systems:
- Minimal network overhead
- No central points of control/failure
- No assumption of existing infrastructure (i.e. trusted nodes)
Furthermore, it is generally desirable to minimize CPU, and particularly local memory usage (consider mobile devices).
As mentioned above, this system is based on Ripple. Another system that currently exists is BitCoin, which has numerous advantages, but also the significant disadvantage that payments can take a long time to be verified and that a large amount of state must be maintained within the network. It also has the the much less significant disadvantage of being complex in order to satisfy its requirements.
BitCoin is based on the idea of normal money, where everyone has some finite amount greater than or equal to zero which they can transfer to others in exchange for resources/goods. Ripple instead works on the principle of credit/debt between entities, such that nodes can choose how much debt they allow neighboring nodes to possess to them. Payments then travel across many of these links, moving nodes in and out of debt with each other, up to the given limits. This has the big advantage that nodes manage state that is relevant to them, so they have an interest in maintaining its accuracy. The amount of state is also relatively small: for each neighbour it simply stores the current credit/debt and its limit for that debt. Nodes are free to use their own methods to set credit limits, and to adjust that credit (e.g. apply interest), although there's nothing stopping nodes from defaulting (which in this case simply means never crediting the neighbor they're in debt to) on their debts so credits should be set appropriately and in accordance to reasonable methods (e.g. trust, previous experience). A potentially significant advantage of this system is also that it is compatible with Dark-nets.
The greatest difficulty of Ripple is making the payments between nodes - it's possible to use dark-net routing to find a single path, but the relative credit/debt of two nodes is actually split over a large number of different paths between the two nodes. As a result, it is likely to be necessary to find multiple paths, or even all paths, between the two nodes. Fortunately, it is possible to do this without inefficient broadcast mechanisms by using the appropriate functionality within Darknet Routing. It is also true that in Ripple a node can pay different nodes different amounts, depending on the available paths to them - over time it is expected that this disappears, and is generally unlikely to be a problem.
When a node makes a payment, it first generates a random ID for the payment (probably known beforehand to the destination). Then it gets all its neighbors in the direction of the target node and works out how much debt they will accept (either by local knowledge or by directly asking). It then splits up the payment amount and sends whatever amount of debt it can towards each of its neighbors. They can reject the payments (in case the limit decreased recently) by sending a message back up the chain, so that the node must select another node to pay the additional debt not accepted by the previous node (assuming it does accept some debt). Further messages are sent up the chain if that node cannot find a neighbor in the direction of the target node that accepts enough debt. If that node can't find a path for the debt, it sends as much debt as it can, and then sends a message back up the chain itself reporting how much debt it managed to deliver. If a node has already delivered some debt but another neighbor asks it to deliver more debt, it then simply uses the same mechanism, applying the debt in addition to previous debt.
Finally, the messages reach the target node. Once the target node has received messages which total an acceptable amount, which would normally be the total amount, it sends ACKs back through the routes. Each node in the route remembers it for the payment ID, in a very similar way to circuit-based routing, where this initial process allocates a payment amount, which will be available until it is used up, closed by the source or target node, or it simply closes after a certain amount of time. While it is allocated, nodes act as if the payment has been made, so that the debt isn't simultaneously allocated for another payment, which reverts appropriately when the payment is 'deallocated'. Now, the source node can send some amount of debt to the target node by sending messages to the corresponding nodes, with the payment ID and the payment amount, so that they can route through the network as the allocation requests did. Again, when the target node receives the according amount it sends ACKs back up the network - however in this case nodes permanently update to reflect the payment amount. Before making the payment, the source node generates another random ID for the specific payment, and encrypts it using the public key of the target node (or some shared symmetric key), so that intermediate nodes are encouraged to deliver the messages down the payment routes, allow the target node to obtain the ID by decryption with its private key and sending valid ACKs back up the routes. At this point source nodes are obliged to accept payment occurred when given a valid ID, and must generally re-request it from target nodes within a certain amount of time.
When all payment routes are not needed, it is very useful to use the shortest paths available, since many requests need to be sent back and forth.
As a trust system
The aspect of finding all paths from a source to a target is closely related to the aspect of implementing a trust system, allowing a node to determine how much it should trust a target node. In this case, it sends request messages in the direction of the target node, until it reaches neighbors of the target node, which send messages back with their trust of the target node. Intermediate nodes then multiply the return value of each neighbor node with its trust of that node, and then returns the maximum of the calculated trust values. The source node then completes this procedure itself, and considers the produced value as its trust for the target node.