# Ripple Inter Server Protocol built on a fee system and single-hop consensus Johan Nygren, @BipedalJoe Ripple is a person-to-person money system that was invented by Ryan Fugger in 2004. The new idea with Ripple was that everyone is a bank, thus Ripple took banking down to the smallest possible scale. Ripple as a money system is therefore unique in that the bookkeeping only needs consensus at the person-to-person level, and thus it is possible to design and build a Ripple Inter Server Protocol where the computation also only needs consensus at the person-to-person level (thus a person could run their own isolated server and share state only with their trusted relationships, if they wanted to). The main problem in multi-server Ripple is the “reserve credit attack”. A fee system can be used to deter such an attack. The users of a multi-hop payment that are affected by a reserve-credit-attack can simply collect fees, and thus get paid for being attacked. Fees can apply a force on whoever has a net negative balance. During multi-hop payment coordination this means that the fees can enforce a signal if each “hop” gets stuck with the net negative balance. Thus both a cancel signal from the buyer and a finalize signal from the seller can be enforced with fees (Ryan Fugger originally focused on a seller-finalizes mechanism for this exact reason). The logical way to exploit the fees becomes a three step payment process: “commit”, “seal”, “finalize”, with the fee system applying a force on each of those steps. ## The game theory of fees as an incentive The fees can apply a force on a person during a payment coordination step if they are in a net negative balance. I.e., the fees act on whoever has a net negative balance. During multi-hop payment coordination this means that the fees can enforce a signal if each “hop” gets stuck with the net negative balance. Such is the case for both a “seller finalizes” mechanism as well as a "buyer cancels" signal. Thus, both those signals could reasonably be good building blocks for enforcing certain outcomes in multi-hop payment coordination (note that both have to be authenticated). Ryan Fugger originally focused on the seller finalizes but with a very crude penalty: the full payment, enforced by a simple timeout (technically a “staggered timeout”…) His idea could be practically usable if the penalty was reduced. A fee system where users themselves impose fees can be easily conceived. It can operate as soon as the users have begun to coordinate a multi-hop payment. But to reduce the penalty compared to Ryan's idea also means you reserve credit for longer periods of time. Thus it is important to make sure that everyone commits to doing so (that the path did not fail halfway). Conveniently, the “buyer cancels” building block is ideal for ensuring this. The fact that “buyer cancels” can be enforced by fees means you can simply let the buyer issue a “commit” signal towards the seller, and then have the seller signal the buyer (in an authenticated way) if it succeeded. If the “commit” failed, the buyer simply cancels. Since the buyer is the one with a net negative balance, the fee system that started at “commit” will enforce that the “long-term-reserve-credit” only starts if everyone has committed. With this first commit step, we thus set up an agreement where the payment will either succeed, or, large penalties will be inflicted on those who prevented it and large rewards handed out to everyone damaged by the failure. The payment has been “sealed” and can no longer be cancelled, it can only either succeed or failed. Formally, the “sealed” step (where the payment can no longer be cancelled, and everyone is stuck with it until it either succeeds or fails) starts when the buyer issues `SEAL_PAYMENT`. The fees as an enforcement mechanism here start to act on each intermediary, as they end up with a net negative balance when fees are collected from both sides (note, the buyer also has a net negative balance here). The propagation of `SEAL_PAYMENT` is then ensured to either succeed, or, to financially compensate each user who is damaged by the failure (while punishing the user who caused the failure). Then with everything set up perfectly thanks to `COMMIT_PAYMENT` and `SEAL_PAYMENT`, the fee system will also enforce that `FINALIZE_PAYMENT` propagates once the seller issues it after receiving `SEAL_PAYMENT`. ## The fee system The fee system idea is very simple: any user affected by a reserve credit attack simply collects fees themselves, thus paying themselves for their damages. Any attempt to cheat the mechanism only affects your own friends. Each user in the payment chain thus acts as a “buffer” to cheating (and the transaction history lets you prove if your friends cheat you). The fee system is coordinated in a very simple way: each user has a `FEE_RATE` parameter that defines how many seconds it takes to grab 1 XYZ as fee. They run a routine periodically where they grab a random amount from the so-far unclaimed fees. They then synchronize this claim in their accounts with the incoming and/or outgoing user. Their relationships will forward the claim if it is less than or equal to what they have calculated should be the fee so far. Thus the equilibrium is for people to use the same (or at least very similar) `FEE_RATE`. ## The user-to-user consensus mechanism “Lockstep” A person-to-person Ripple requires that consensus at the person-to-person level is guaranteed. The issue with person-to-person decision making over the internet is the "two general problem", that it is impossible to be certain about if an acknowledgement was delivered. Thus it follows that agreement is impossible. The solution to the two-general problem is to agree on a single general. The ideal way to do so, is to take turns being the general. Here I will conceptualize such a mechanism and call it “Lockstep”. ### Lockstep, a single-hop consensus mechanism People in a trustline-relationship agree to take turns to be "general" who gets to say which transaction should happen next. They coordinate this with the use of a counter, and agree that one person will validate when `counter mod 2` is 0 and the other when `counter mod 2` is 1. The person who is not the "general" at a turn can propose transactions to the "general". Each person stores the instruction they last validated in permanent storage until they receive the next rounds validated transaction (thus continuity is guaranteed.) In permanent storage you thus maintain a turn bit (0 or 1) for `counter mod turnbit`, and a turn counter for same operation, and the last validated instruction (an instruction being a command with arguments). The "state transition function" in Lockstep includes incrementing the turn counter and setting the last validated instruction, as well as the state changes that the instruction performed, and is "atomic", all-or-nothing. Thus, two accounts are in perfect agreement over every decision that they make. ### Integrating Lockstep with the role as an intermediary With single-hop guaranteed, two-hop at an intermediary is guaranteed since it is on a single machine. But it still has to be organized practically, on that machine. A simple approach is that the command handler returns an "inter-lockstep" callback. This callback is executed only if the Lockstep state transition succeeded. Since such callback could fail, it is ideally combined with "failsafe" routines. For example, a callback that queues a transaction could fail because the queue is full. A failsafe routine can derive the same decision from the permanently stored data, and run periodically to catch any failures. ### Guaranteed single-hop consensus makes multi-hop agreements possible Lockstep guarantees that any signal that propagates over multiple hops has been agreed on by every previous hop. But it does not guarantee that a signal propagates, nor is it able to discover propagation failure. Thus, multi-hop agreements have to conform to the fact that propagated signals can be trusted but signal propagation cannot. The fundamentals are: assume perfect consensus about that propagated signals are honest, assume zero consensus about if a signal has propagated (i.e., the receiver can be certain, the sender cannot). It follows that only the end receiver of a signal can know if an agreement succeeded. ### Multi-hop payment with honest signals but uncertain signal propagation The coordination steps described for the multi-hop payment assumes honest signals but uncertain signal propagation. When the seller receives `COMMIT_PAYMENT` they can be certain that every intermediary has propagated it (i.e., the receiver can be certain, the sender cannot). Likewise, when the seller notifies the buyer of this, the buyer can be certain everyone has committed. When the buyer then submits `SEAL_PAYMENT` they can be certain that everyone is “all-in” on the payment. When `SEAL_PAYMENT` reaches the seller, they can be certain the buyer revoked their right to cancel, i.e., that everyone is all–in. When the seller then submits `FINALIZE_PAYMENT`, each person knows since before that the payment has been sealed and that they are penalized by fees if they do not propagate the “finalize” signal.