From 9716fb7aa68a8770aee96413916e12edd69787fe Mon Sep 17 00:00:00 2001 From: Stefan Thomas Date: Mon, 8 Aug 2016 05:22:23 -0700 Subject: [PATCH] docs(asn1): update with final ilp payment packet Also includes draft of ILQP formats. --- asn1/CryptoConditions.asn | 145 ----------------------- asn1/GenericExtensionHeaderFormat.asn | 14 --- asn1/GenericPacket.asn | 45 +++++++ asn1/GenericTypes.asn | 35 +++++- asn1/InterledgerProtocol.asn | 31 +++++ asn1/InterledgerProtocolHeader.asn | 19 --- asn1/InterledgerQuotingProtocol.asn | 93 ++++++++++----- asn1/InterledgerTypes.asn | 162 +++++++++++++++++++++++--- asn1/UniversalModeHeader.asn | 21 ---- 9 files changed, 322 insertions(+), 243 deletions(-) delete mode 100644 asn1/CryptoConditions.asn delete mode 100644 asn1/GenericExtensionHeaderFormat.asn create mode 100644 asn1/GenericPacket.asn create mode 100644 asn1/InterledgerProtocol.asn delete mode 100644 asn1/InterledgerProtocolHeader.asn delete mode 100644 asn1/UniversalModeHeader.asn diff --git a/asn1/CryptoConditions.asn b/asn1/CryptoConditions.asn deleted file mode 100644 index 206f20cc..00000000 --- a/asn1/CryptoConditions.asn +++ /dev/null @@ -1,145 +0,0 @@ ----- -CryptoConditions DEFINITIONS AUTOMATIC TAGS ::= -BEGIN - -IMPORTS - UInt8, - UInt32, - UInt256, - UInt512, - VarUInt, - VarBytes - FROM GenericTypes -; - - -/** - * CONTAINERS - */ - -Condition ::= SEQUENCE { - version UInt8, - type FulfillmentType, - requiredSuites OCTET STRING, - fingerprint VarBytes, - maxFulfillmentLength VarUInt -} - -Fulfillment ::= SEQUENCE { - version UInt8, - type FulfillmentType, - payload VarBytes -} - -FulfillmentType ::= INTEGER { - preimageSha256(0), - rsaSha256(1), - prefixSha256(2), - thresholdSha256(3), - ed25519(4) -} (0..65535) - -/** - * FULFILLMENT PAYLOADS - */ - --- For preimage conditions, the payload *is* the preimage - -PrefixSha256FulfillmentPayload ::= SEQUENCE { - prefix VarBytes, - subfulfillment Fulfillment -} - -ThresholdSha256FulfillmentPayload ::= SEQUENCE { - threshold UInt32, - subfulfillments SEQUENCE OF ThresholdSubfulfillment -} - -ThresholdSubfulfillment ::= SEQUENCE { - weight UInt32 DEFAULT 1, - condition Condition OPTIONAL, - fulfillment Fulfillment OPTIONAL -} - -RsaSha256FulfillmentPayload ::= SEQUENCE { - modulus OCTET STRING (SIZE(128..512)), - signature OCTET STRING (SIZE(128..512)) -} - -Ed25519FulfillmentPayload ::= SEQUENCE { - publicKey UInt256, - signature UInt512 -} - -/** - * FINGERPRINTS - */ - --- SHA-256 hash of the fingerprint contents -Sha256Fingerprint ::= UInt256 -- digest - --- 32-byte Ed25519 public key -Ed25519Fingerprint ::= UInt256 -- publicKey - -/** - * FINGERPRINT CONTENTS - * - * The content that will be hashed to arrive at the fingerprint. - */ - --- The preimage type hashes the raw contents of the preimage - -PrefixSha256FingerprintContents ::= SEQUENCE { - version UInt8, - type FulfillmentType, - prefix VarBytes, - condition Condition -} - -ThresholdSha256FingerprintContents ::= SEQUENCE { - version UInt8, - type FulfillmentType, - threshold UInt32, - subconditions SEQUENCE OF ThresholdSubcondition -} - -ThresholdSubcondition ::= SEQUENCE { - weight UInt32, - condition Condition -} - -RsaSha256FingerprintContents ::= VarUInt -- modulus - -/** - * EXAMPLES - */ - -exampleCondition Condition ::= -{ - version 1, - type preimageSha256, - requiredSuites '03'H, - fingerprint 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855'H, - maxFulfillmentLength 2 -} - -exampleFulfillment Fulfillment ::= -{ - version 1, - type preimageSha256, - payload '00'H -} - -exampleRsaSha256FulfillmentPayload RsaSha256FulfillmentPayload ::= -{ - modulus 'B30E7A938783BABF836850FF49E14F87E3F92D5C46E33FECA3E4F0B22358580B11765995F4B8EEA7FB4712C2E1E316F7F775A953D232216A169D9A64DDC007120A400B37F2AFC077B62FE304DE74DE6A119EC4076B529C4F6096B0BAAD4F533DF0173B9B822FD85D65FA4BEFA92D8F524F69CBCA0136BD80D095C169AEC0E095'H, - signature '48E8945EFE007556D5BF4D5F249E4808F7307E29511D3262DAEF61D88098F9AA4A8BC0623A8C975738F65D6BF459D543F289D73CBC7AF4EA3A33FBF3EC4440447911D72294091E561833628E49A772ED608DE6C44595A91E3E17D6CF5EC3B2528D63D2ADD6463989B12EEC577DF6470960DF6832A9D84C360D1C217AD64C8625BDB594FB0ADA086CDECBBDE580D424BF9746D2F0C312826DBBB00AD68B52C4CB7D47156BA35E3A981C973863792CC80D04A180210A52415865B64B3A61774B1D3975D78A98B0821EE55CA0F86305D42529E10EB015CEFD402FB59B2ABB8DEEE52A6F2447D2284603D219CD4E8CF9CFFDD5498889C3780B59DD6A57EF7D732620'H -} - -exampleEd25519FulfillmentPayload Ed25519FulfillmentPayload ::= -{ - publicKey 'EC172B93AD5E563BF4932C70E1245034C35467EF2EFD4D64EBF819683467E2BF'H, - signature 'B62291FAD9432F8F298B9C4A4895DBE293F6FFDA1A68DADF0CCDEF5F47A0C7212A5FEA3CDA97A3F4C03EA9F2E8AC1CEC86A51D452127ABDBA09D1B6F331C070A'H -} - -END diff --git a/asn1/GenericExtensionHeaderFormat.asn b/asn1/GenericExtensionHeaderFormat.asn deleted file mode 100644 index 614f1948..00000000 --- a/asn1/GenericExtensionHeaderFormat.asn +++ /dev/null @@ -1,14 +0,0 @@ -GenericExtensionHeaderFormat DEFINITIONS AUTOMATIC TAGS ::= -BEGIN - -IMPORTS - UInt16 - FROM GenericTypes -; - -GenericHeaderPreamble ::= SEQUENCE { - type UInt16, - size UInt16 -} - -END diff --git a/asn1/GenericPacket.asn b/asn1/GenericPacket.asn new file mode 100644 index 00000000..c2496c7b --- /dev/null +++ b/asn1/GenericPacket.asn @@ -0,0 +1,45 @@ +GenericPacket +DEFINITIONS +AUTOMATIC TAGS ::= +BEGIN + +IMPORTS + UInt8, + VarBytes + FROM GenericTypes + + InterledgerProtocolPaymentMessage + FROM InterledgerProtocol + + QuoteLiquidityRequest, + QuoteLiquidityResponse, + QuoteBySourceAmountRequest, + QuoteBySourceAmountResponse, + QuoteByDestinationAmountRequest, + QuoteByDestinationAmountResponse + FROM InterledgerQuotingProtocol +; + +PACKET ::= CLASS { + &typeId UInt8 UNIQUE, + &Type +} WITH SYNTAX {&typeId &Type} + +PacketSet PACKET ::= { + {1 InterledgerProtocolPaymentMessage} | + {2 QuoteLiquidityRequest} | + {3 QuoteLiquidityResponse} | + {4 QuoteBySourceAmountRequest} | + {5 QuoteBySourceAmountResponse} | + {6 QuoteByDestinationAmountRequest} | + {7 QuoteByDestinationAmountResponse} +} + +InterledgerPacket ::= SEQUENCE { + -- One byte type ID + type PACKET.&typeId ({PacketSet}), + -- Length-prefixed header + data PACKET.&Type ({PacketSet}{@type}) +} + +END diff --git a/asn1/GenericTypes.asn b/asn1/GenericTypes.asn index 5cf1e2c7..64415844 100644 --- a/asn1/GenericTypes.asn +++ b/asn1/GenericTypes.asn @@ -1,4 +1,6 @@ -GenericTypes DEFINITIONS AUTOMATIC TAGS ::= +GenericTypes +DEFINITIONS +AUTOMATIC TAGS ::= BEGIN -- Small Integers @@ -27,6 +29,37 @@ UInt512 ::= OCTET STRING (SIZE(64)) VarInt ::= INTEGER VarUInt ::= INTEGER (0..MAX) +-- Binary Floating Point (IEEE 754) + +Float32 ::= REAL ( -- binary32 + 0 | + WITH COMPONENTS { + mantissa (-16777215..16777215), -- 23 bits + 1 sign bit + base (2), + -- Note that the exponent range in ASN.1 is given as the exponent relative to + -- the integer mantissa, i.e. mantissa * 2 ^ exponent, whereas in IEEE 754, the + -- exponent is relative to a binary fraction using the 23 fractional bits and + -- an implicit integer part of one. This is why the exponent range is offset + -- by 23, i.e. -149..104 instead of -126..127. + exponent (-149..104) + } +) + +Float64 ::= REAL ( -- binary64 + 0 | + WITH COMPONENTS { + mantissa (-9007199254740991..9007199254740991), -- 52 bits + 1 sign bit + base (2), + -- Note the exponent range in ASN.1 is given as the exponent relative to the + -- integer mantissa, i.e. mantissa * 2 ^ exponent, whereas in IEEE 754, the + -- exponent is relative to a binary fraction using the 52 fractional bits and + -- an implicit integer part of one. This is why the exponent range is offset + -- by 53, i.e. -1075..970 instead of -1022..1023. + -- TODO: Why isn't this offset by 52 instead of 53? + exponent (-1075..970) + } +) + -- Variable-Length Data VarBytes ::= OCTET STRING diff --git a/asn1/InterledgerProtocol.asn b/asn1/InterledgerProtocol.asn new file mode 100644 index 00000000..94eed6eb --- /dev/null +++ b/asn1/InterledgerProtocol.asn @@ -0,0 +1,31 @@ +InterledgerProtocol +DEFINITIONS +AUTOMATIC TAGS ::= +BEGIN + +IMPORTS + UInt64 + FROM GenericTypes + + Address, + Amount + FROM InterledgerTypes + + MetadataEntry + FROM MetadataEntry +; + +InterledgerProtocolPaymentMessage ::= SEQUENCE { + -- Amount which must be received at the destination + amount UInt64, + -- Destination ILP Address + account Address, + -- Information for recipient (transport layer information) + data OCTET STRING (SIZE (0..32767)), + -- Enable ASN.1 Extensibility + extensions SEQUENCE { + ... + } +} + +END diff --git a/asn1/InterledgerProtocolHeader.asn b/asn1/InterledgerProtocolHeader.asn deleted file mode 100644 index 2831b0fe..00000000 --- a/asn1/InterledgerProtocolHeader.asn +++ /dev/null @@ -1,19 +0,0 @@ -InterledgerHeader -DEFINITIONS -AUTOMATIC TAGS ::= -BEGIN - -IMPORTS - Address, - Amount - FROM InterledgerTypes -; - -InterledgerProtocolHeader ::= SEQUENCE { - version INTEGER(0..255), - destinationAddress Address, - destinationAmount Amount, - nextHeader INTEGER(0..65535) -} - -END diff --git a/asn1/InterledgerQuotingProtocol.asn b/asn1/InterledgerQuotingProtocol.asn index fc7c3ed0..92dfcc74 100644 --- a/asn1/InterledgerQuotingProtocol.asn +++ b/asn1/InterledgerQuotingProtocol.asn @@ -2,43 +2,76 @@ InterledgerQuotingProtocol DEFINITIONS AUTOMATIC TAGS ::= BEGIN IMPORTS - UInt64 - FROM GenericTypes - - Address, - Amount - FROM InterledgerTypes - - GenericHeaderPreamble - FROM GenericExtensionHeaderFormat + UInt8, + UInt32, + UInt64, + UInt128, + Int8 + FROM GenericTypes + + Address, + Amount, + Timestamp, + LiquidityCurve + FROM InterledgerTypes ; -QuoteRequest ::= SEQUENCE { - preamble GenericHeaderPreamble, - addresses AddressSet, - sourceAmount Amount OPTIONAL, - destinationAmount Amount OPTIONAL, - -- How long the receiver needs to fulfill the payment (when using TTP/ATP) - -- Defaults to 1.5 seconds - destinationHoldDuration IlpHoldDuration DEFAULT 1500000 +-- Request to receive liquidity information between the current ledger and the +-- destination account. This information is sufficient to locally quote any +-- amount until the curve expires. +QuoteLiquidityRequest ::= SEQUENCE { + requestId UInt128, + destinationAccount Address, + -- How much time the receiver needs to fulfill the payment (in milliseconds) + destinationHoldDuration UInt32 +} + +QuoteLiquidityResponse ::= SEQUENCE { + requestId UInt128, + -- Curve describing the liquidity (relationship between input and output + -- amounts) for the quoted route + liquidity LiquidityCurve, + -- Common prefix of all addresses for which this liquidity curve applies + -- SHOULD end with a period "." (but clients MUST NOT enforce this) + destinationPrefix Address, + -- How long the sender should put money on hold (in milliseconds) + sourceHoldDuration UInt32 + -- TODO: An exact quote expiry doesn't seem necessary... + -- expiresAt Timestamp } -QuoteResponse ::= SEQUENCE { - preamble GenericHeaderPreamble, - connectorAccount IlpAccountName, - -- Address that this quote response relates to - address Address, - -- Source or destination amount, depending on whichever one was NOT - -- provided in the request. - requestedAmount Amount, - sourceHoldDuration IlpHoldDuration +-- Quote with a specific source or destination amount +QuoteBySourceAmountRequest ::= SEQUENCE { + requestId UInt128, + destinationAccount Address, + sourceAmount Amount, + -- How much time the receiver needs to fulfill the payment (in milliseconds) + destinationHoldDuration UInt32 } -AddressSet ::= SEQUENCE OF Address +QuoteBySourceAmountResponse ::= SEQUENCE { + requestId UInt128, + -- Amount that will arrive at the receiver + destinationAmount Amount, + -- How long the sender should put money on hold (in milliseconds) + sourceHoldDuration UInt32 +} -IlpAccountName ::= OCTET STRING +-- Quote with a specific source or destination amount +QuoteByDestinationAmountRequest ::= SEQUENCE { + requestId UInt128, + destinationAccount Address, + destinationAmount Amount, + -- How much time the receiver needs to fulfill the payment (in milliseconds) + destinationHoldDuration UInt32 +} --- Length of hold in microseconds -IlpHoldDuration ::= UInt64 +QuoteByDestinationAmountResponse ::= SEQUENCE { + requestId UInt128, + -- Amount the sender needs to send based on the requested destination amount + sourceAmount Amount, + -- How long the sender should put money on hold (in milliseconds) + sourceHoldDuration UInt32 +} END diff --git a/asn1/InterledgerTypes.asn b/asn1/InterledgerTypes.asn index bd3225b1..14e91f70 100644 --- a/asn1/InterledgerTypes.asn +++ b/asn1/InterledgerTypes.asn @@ -1,29 +1,165 @@ -InterledgerTypes DEFINITIONS AUTOMATIC TAGS ::= +InterledgerTypes +DEFINITIONS +AUTOMATIC TAGS ::= BEGIN IMPORTS - Int8, - VarUInt - FROM GenericTypes + Int16, + UInt8, + UInt64, + VarUInt, + Float64 + FROM GenericTypes ; +-- Readable names for special characters that may appear in ILP addresses +hyphen IA5String ::= "-" +period IA5String ::= "." +underscore IA5String ::= "_" +tilde IA5String ::= "~" + +-- A standard interledger address +Address ::= IA5String + (FROM + ( hyphen + | period + | "0".."9" + | "A".."Z" + | underscore + | "a".."z" + | tilde ) + ) + (SIZE (1..1023)) + +-- -------------------------------------------------------------------------- + +-- Amounts are represented as IEEE 754 double-precision floating point. +-- +-- *audience gasps* +-- +-- Humans generally use decimals in today's financial systems. This is done +-- because binary floating point numbers cannot accurately reflect decimal +-- fractions and exhibit rounding errors when numbers are ultimately converted +-- back to decimal representation. +-- +-- However, we anticipate that Interledger will primarily be used by computers +-- to pay other computers. So we believe an efficient binary representation +-- makes sense long-term though of course we need to address the rounding +-- issue. +-- +-- Double precision binary floating point numbers (IEEE 754 binary64) can +-- accurately represent decimals of up to 15 significant digits. That means, +-- if the destination ledger of an Interledger payment uses base-10, we simply +-- need to convert the amount to a decimal fraction with 15 digits of +-- precision. +-- +-- Java: new BigDecimal(amount, new MathContext(15)); +-- JavaScript: new BigNumber(Number(amount).toPrecision(15)) +-- +-- Another reason to use binary amounts is that most numbers in Interledger +-- are either liquidity curves, or amounts that a liquidity curve has been +-- applied to. Since binary floating point math is much more efficient, it +-- makes sense to do all of the calculations consistently in binary and only +-- round to decimals for amounts that humans will actually see. +-- +-- Note that subnormal amounts as well as special amounts other than positive +-- zero (-Infinity, +Infinity, -0, NaN, ...) are not allowed in Interledger. + +Amount ::= UInt64 + +-- Selection of other options considered: + +-- Amount ::= Float64 + +-- Amount ::= REAL (0 | WITH COMPONENTS { +-- mantissa (-9223372036854775808..9223372036854775807), +-- base (10), +-- exponent (-127..127) +-- }) + +-- Amount ::= SEQUENCE { +-- mantissa UInt64, +-- exponent Int8 +-- } + +-- -------------------------------------------------------------------------- + +-- Different ledgers may use different rounding parameters + +-- NumberFormat ::= CHOICE { + -- Most ledgers today are designed for humans and use base-10. However, it + -- may be desirable to create base 2 ledgers in the future for efficiency. + -- base2 [2] IMPLICIT Base2NumberFormat, + -- base10 [10] IMPLICIT Base10NumberFormat +-- } + +-- Base2NumberFormat ::= SEQUENCE { + -- precision UInt8, + + -- Providing a range of exponents allows us to describe both + -- fixed-point (min == max) and floating-point (min != max) type ledgers. + -- minExponent Int16, + -- maxExponent Int16 +-- } + +-- Base10NumberFormat ::= SEQUENCE { + -- precision UInt8, + + -- Providing a range of exponents allows us to describe both + -- fixed-point (min == max) and floating-point (min != max) type ledgers. + -- minExponent Int16, + -- maxExponent Int16 + + -- Stepping is used in some assets some of the time. For instance, Swiss + -- Francs are sometimes rounded in CHF 0.05 increments. However, this is an + -- obscure enough use case that we don't feel it's necessary to support. + -- Note that stepping is only possible for base-10 ledgers, not base-2, + -- step UInt8 ( 1 | 2 | 5 ) + + -- Rounding could be specified per ledger, but we believe that in most cases + -- rounding is dictated by security and self-interest. For example, a + -- connector will always round in its favor to prevent its customers from + -- being able to extract money from it over time by tricking it to round in + -- their favor over and over. + -- roundingMode ENUMERATED { + -- up (0) + -- down (1) + -- ceiling (2) + -- floor (3) + -- halfUp (4) + -- halfDown (5) + -- halfEven (6) + -- } +--} + +-- -------------------------------------------------------------------------- -- GeneralizedTime is a standard ASN.1 time format based on ISO 8601. It was --- tempting to use the Unix epoch, however unfortunately, standard POSIX --- time is discontinuous. If we used POSIX time for expiries for example, a --- transfer might expire and then un-expire when a leap second occurs. Since +-- tempting to use the Unix epoch. Unfortunately, standard POSIX time is +-- discontinuous. If we used POSIX time for expiries for example, a transfer +-- might expire and then "un-expire" when a leap second occurs. Since -- Interledger protocols depend on causality, we cannot use POSIX time and -- since we do not wish to create our own time standard, we end up using ISO -- 8601. + Timestamp ::= GeneralizedTime --- A standard interledger address is an arbitrary byte string -Address ::= IA5String +-- -------------------------------------------------------------------------- + +-- Liquidity curves describe the relationship between input and output amount +-- for a given path between a given pair of ledgers. +-- +-- The curve is expressed as a series of points given as coordinates. +-- +-- Each x coordinate corresponds to an input amount, each y corresponds to an +-- output amount. Each point must have larger x and y values than the previous +-- point. All coordinates must be greater than zero. +-- +-- The only amounts --- A standard interledger amount is a base-10 floating point amount -Amount ::= SEQUENCE { - exponent Int8, - mantissa VarUInt +LiquidityCurve ::= SEQUENCE OF SEQUENCE { + x UInt64, + y UInt64 } END diff --git a/asn1/UniversalModeHeader.asn b/asn1/UniversalModeHeader.asn deleted file mode 100644 index e0e7d898..00000000 --- a/asn1/UniversalModeHeader.asn +++ /dev/null @@ -1,21 +0,0 @@ -UniversalModeHeader DEFINITIONS AUTOMATIC TAGS ::= -BEGIN - -IMPORTS - Timestamp - FROM Types - - Condition - FROM CryptoConditions - - GenericHeaderPreamble - FROM GenericExtensionHeaderFormat -; - -UniversalModeHeader ::= SEQUENCE { - preamble GenericHeaderPreamble, - condition Condition, - expiresAt Timestamp -} - -END