There are three types of currencies on ripple: ripple's native currency, also known as Ripples or XRP, fiat currencies and custom currencies. The later two are used to denominate IOUs on the ripple network.
Native currency is handled by the absence of a currency indicator. If there is ever a case where a currency ID is needed, native currency will use all zero bits.
Custom currencies will use the 160-bit hash of their currency definition node as their ID. (The details have not been worked out yet.)
National currencies will be handled by a naming convention that species the three-letter currency code, a version (in case the currency is fundamentally changed), and a scaling factor. Currencies that differ only by a scaling factor can automatically be converted as transactions are processed. (So whole dollars and millionths of a penny can both be traded and inter-converted automatically.)
The 160-bit identifier for national currencies will be assembled as follows:
|Zero||96||Indicates a national currency|
|ISO code||24||The three-letter code for this currency in upper case ASCII.|
|Version||16||This will be zero for all currencies at first. It can be bumped if a currency is replaced/reissued|
|Reserved||24||Should be zero for now, but non-zero values should not be rejected|
- ISO 4217
Currency 160-bit identifier is the hash of the currency definition block, which is also its storage index. Contains: Domain of issuer. Issuer's account. Auditor's account (if any). Client display information. Hash of policy document.
The Ripple code uses a specialized internal and wire format to represent amounts of currency. Because the server code does not rely on a central authority, it can have no idea what ranges are sensible with currencies. In addition, it's handy to be able to use the same code both to handle currencies that have inflated to the point that you need billions of units to buy a loaf of bread and to handle currencies that have become extremely valuable and so extremely small amounts need to be tracked.
The design goals are:
- Accuracy - 15 decimal digits
- Wide representation range - 10^80 units of currency to 10^-80 units
- Deterministic - no vague rounding by unspecified rules.
- Fast - Integer math only.
The format used internally is an integer exponent and a 64-bit integer mantissa. The number of units of currency represented is the mantissa multiplied by ten raised to the power of the exponent.
The legal exponent range is -96 to +80. With the exception of 0 (which is represented as a mantissa of zero), the legal mantissa range is 10^15 to 10^16 -1.
The wire format is a single unsigned 64-bit integer. It is formed by adding 124 to the exponent and placing that in the upper 8 bits. The mantissa is placed in the lower 56 bits. This ensures that comparisons on numbers in wire format work.
The display/Json format is exact in all cases. If the range is sensible for decimal display (which it almost always will be), the display is in standard currency format with no extra digits. Typical examples of this format are: 1, 2.25, and .001432.
If the display is out of range for sensible display in this form, the exact internal representation is displayed. The display consists of the mantissa, followed by the letter e, followed by the exponent.
It is expected that any client would have a table of currency formats and would know to display US dollars with two decimal digits unless the user desired more precision.
Core operations are: canonicalize, +, -, * and /.
The canonicalize operation adjusts a value to comply with the mantissa range rules. This is needed when accepting values in another format and when fixing up values after other operations. It must start with a value whose mantissa is in the range of zero to 2^64 - 1.
The + operation adds two currency values. After testing both values for zero and handling those special cases, the value with the smaller exponent is shifted until they have the same exponents. The mantissas are added in a 64-bit register (so overflow is impossible). The final result is then canonicalized.
The - operation subtracts one currency value from another. If either or both numbers are zero, that special case is handled appropriately. If the number subtracted has a larger exponent, an error is generated. Then the number subtracted is shifted until the exponents are equal. Then the subtraction is performed and the result is canonicalized.
The * operation multiplies one currency value by another. Internal +5/10 LSB followed by integer truncation rounding is used. After appropriate special cases for zero, the two mantissas are multiplied using 128-bit integer arithmetic and then divided by 10^18. The result must then lie in the range of roughly 10^16 to 10^18. A new amount is formed with a mantissa of the result of the division and an exponent equal to the sum of the two original numbers exponents plus 16. This result is then canonicalized.
To round, each mantissa is multiplied by ten prior to multiplication. After multiplication, 50 is added to the result and the result is divided by 100.
The / operation divides one currency value by another. After appropriate special cases for zero, the mantissa of the numerator is multiplied by 10^16 using 128-bit integer arithmetic. The product is then divided by the denominator. The result must then lie in the range of roughly 10^15 to 10^17. A new amount is formed with a mantissa of the result of the division and an exponent of the numerator's exponent minus the denominator's exponent minus 16. This amount is then canonicalized.
Internal currency values are shown as "mantissa e exponent". Input values are shown as "mantissa , exponent". Display values are shown normally.
One dollar can be expressed non-canonically as 1,0 (one dollar) or 100,-2 (100 pennies). Either way, it canonicalizes to 1000000000000000e-15 and displays as "1".
One penny can be input as 1,-2. It canonicalizes to 1000000000000000e-17 and displays as ".01".
Some divisions are shown below. The number to the right of the equals sign is the actual answer from the current code in display format, which is also the exact internal value. (The internal value is always an integer. The decimal point is added for display.) For the first three, exact values (calculated with an arbitrary precision calculator, not this code) are shown for comparison.
4034,0 / 9081,0 = 0.4442242043827772 (exact: .4442242043827772271...) 9081,0 / 4034,0 = 2.251115518096182 (exact: 2.251115518096182449...) 9082,0 / 4034,0 = 2.251363411006445 (exact: 2.251363411006445215...) 11,0 / 1,70 = 1100000000000000e-84 1,70 / 11,0 = 9090909090909090e53 11,0 / 1,-70 = 1100000000000000e56 1,-70 / 11,0 = 9090909090909090e-87
This shows the offer logic. An offer is made. A few takes are placed against it. One shows an example of calculating how much you have to offer to get a desired output. Then a test is made offering slightly less. Then a full take (for more than the offer) is shown. (What the offeror gets is always equal to what the taker pays.)
Offer: For 17.3 sprockets, I will give 2340 widgets Someone offers 1 sprockets Offerror gets 1 sprockets and they get 135.2601156069364 widgets Offer: For 16.3 sprockets, I will give 2204.739884393064 widgets Jack needs 100 widgets. He should give 0.7393162393162391 sprockets Someone offers 0.7393162393162391 sprockets Offerror gets 0.7393162393162391 sprockets and they get 100 widgets Offer: For 15.56068376068377 sprockets, I will give 2104.739884393064 widgets Someone offers 0.739316239316239 sprockets Offerror gets 0.739316239316239 sprockets and they get 99.99999999999987 widgets Offer: For 14.82136752136754 sprockets, I will give 2004.739884393065 widgets Someone offers 5000 sprockets Offerror gets 14.82136752136754 sprockets and they get 2004.739884393065 widgets Offer: For 0 sprockets, I will give 0 widgets Offer is fully taken
Native Currency Scaling
Native currency is scaled for display as transaction fees are destroyed.
Starting conditions: Total Coins: 15000000000, Your Coins: 100000 You spend 100 newcoins. Your Coins: 99900 10000 newcoins are eaten by transaction fees. Your Coins: 99900.0666000444 You spend 250 newcoins. Your Coins: 99650.0666000444 150000 newcoins are eaten by transaction fees. Your Coins: 99651.0631106755
Creating your currencies
Ripple will support three types of currencies:
- Ripple's native currency.
- ISO 4217 (3 Letter currencies)
- The commonly used codes such as USD, EUR, JPY, etc...
- Not currently enforced.
- Custom currencies
- Client currently supports arbitrary three letter currency codes and strings
- If not entered as three capital letters, client automatically assigns a three capital letter currency code.
- Forthcoming - Currency resolution, intrinsic rates, or term length
- Client currently supports arbitrary three letter currency codes and strings
Ripple has no particular support for any of the 3 letter currencies. Ripple requires its users to agree on meaning of these codes. In particular, the person trusting or accepting a balance of a particular currency from an issuer, must agree to the issuer's meaning.
As result, any 3 letter code can be used for represent currencies on the Ripple network as long the involved parties agree.
However, it is illegal to use XRP as 3 letter currency code in the 160 bit encoding. In the 160 bit encoding, XRP must be specified as zero. For convenience, syntactically "XRP" is often allowed as an alternative to specifying zero.
Walk through of creating and paying with a made up currency
Suppose Alice commonly issues a currency ALC. And, Bob wants to hold ALC.
- Bob trust Alice's Ripple account for, say, 100 ALC.
- In the client, Bob goes to the trust tab and types in ALC for the currency when setting trust.
- Alice may now make a payment to Bob for 20 ALC.
- Alice manually types in ALC when sending the payment.