<pre>
  PIP: PIP-0027
  Title: E-PASA: Infinite Address-Space (via Layer-2)
  Type: Protocol, Front-End
  Impact: Hard-Fork
  Author: Herman Schoenfeld <herman@sphere10.com>
  Comments-URI: https://discord.gg/sJqcgtD  (channel #pip-0027)
  Status: Proposed
  Created: 2019-02-11
</pre>

## Summary

This PIP proposes a backwards compatible addressing scheme that enables an infinite address-space within PascalCoin. The usage of these extension addresses can be employed within existing infrastructure such as wallets and exchanges now as well as future Layer-2 dapps.

## Motivation

PascalCoin currently allows users to send/receive operations between accounts using their account numbers (PASA). 

These account numbers are a limited (and commoditized) resource which form a finite address-space (note: this is fundamental to SafeBox design and it's infinite-scaling capability).

PascalCoin will provide an infinite address-space (similar toother other crypto-currencies) via "decentralized custodial accounts" which are Layer-2 dapps governed via a Layer-2 Proof-of-Stake overlay network.

Before rolling out this Layer-2 infrastructure, PascalCoin first needs to establish an addressing-scheme for this infinite address-space.

This PIP provides one such scheme. Additionally, this scheme can also be immediately employed at the presention-layer to greatly simplify exchange integrations and payload-based payments.

## Specification

Layer-2 addresses will be herein referred to as Extended PASA, or E-PASA for short.

An E-PASA has the following unique characteristics:
* Each E-PASA is a **unique** identifier.
* An E-PASA is encoded into the raw network payload of operations.
* There is a 1-1 mapping between E-PASA and their raw payload form.
  * They are deterministically dehydrated to into raw payloads.
  * They are deterministically hydrated from raw payloads (**note**: requires V5 protocol).
* No two fully checksummed E-PASA's can refer to the same logical address.

### Extended PASA format (E-PASA)

An Extended PASA is defined by the below EBNF grammar:

```
    EPASA              = PASA, [ ExtendedAddress ], [ ':', EPASAChecksum ] ;
    PASA               = ( AccountName | AccountNumber ) ;
    AccountName        = Pascal64String ;
    AccountNumber      = Integer, "-", Checksum ;
    Checksum           = Digit, Digit ;
    EPASAChecksum      = HexByte, HexByte ;
    ExtendedAddress    = ( PublicPayload | ReceiverEncPayload | SenderEncPayload | PasswordEncPayload ) ;
    PublicPayload      = "[", [ Payload ], "]" ; 
    ReceiverEncPayload = "(", [ Payload ], ")" ;
    SenderEncPayload   = "<", [ Payload ], ">" ;
    PasswordEncPayload = "{", [ Payload ], ":", [ Password ], "}" ;
    Payload            = ( """, SafeAnsiString, """ | "0", "x", HexString | Base58String ) ;
    Password           = SafeAnsiString
    SafeAnsiString     = SafeAnsiChar, { SafeAnsiChar } ;
    SafeAnsiChar       = (" " | "!" | EscapeChar """ | "#" | "$" | "%" | "&" | "'" | "(" | ")" | "*" | "+" | "," | "-" | "." | "/" | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | ":" | ";" | "<" | "=" | ">" | "?" | "@" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "[" | EscapeChar "\" | "]" | "^" | "_" | "`" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | "{" | "|" | EscapeChar "}" | "~") ;
    Pascal64String     = SafePascal64Char, { Pascal64Char } ;
    Pascal64Char       = (Digit | SafePascal64Char)
    SafePascal64Char   = ( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "+", "{", "}", "[", "]", "_", ":", "`", "|", "<", ">", ",", ".", "?", "/", "~", ")" "-", "+", "{", "}", "[", "]", "_", ":", "`", "|", "<", ">", ",", ".", "?", "/", "~" ) ; 
    HexString          = HexByte { HexByte } ;
    HexByte            = HexNibble, HexNibble ;
    HexNibble          = ( Digit | "a" | "b" | "c" | "d" | "e" | "f" ) ;       (* no uppercase hex allowed *)
    Base58String       = Base58Char, { Base58Char } ;
    Base58Char         = ( NaturalDigit | Base58UpperChar | Base58LowerChar ) ; 
    Base58UpperChar    = ( "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ) ;     (* missing I, O *)
    Base58LowerChar    = ( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" ) ; (* missing l *)
    Integer            = NaturalDigit, { Digit } ;
    Digit              = ( "0" | NaturalDigit ) ;
    NaturalDigit       = ( "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ) ;
    EscapeChar         = "\" ;
```

| Rule               | Explanation                                                                                                   |
| -----------------: | :------------------------------------------------------------------------------------------------------------ |
| EPASA              | This is a layer-2 address, fully backwards compatible as Layer-1 address                                      |
| PASA               | This is the standard layer-1 address of the receiver account (account number or account name)                 |
| Checksum           | This is the standard layer-1 address checksum                                                                 |
| ExtendedAddress    | The optional extra text that forms part of layer-2 address (payload specification)                            |
| PublicPayload      | A payload which is not encrypted and publically visible                                                       |
| ReceiverEncPayload | A payload which is ECIES encrypted using receivers public key (the PASA portion specifies receiver)           |
| SenderEncPayload   | A payload which is ECIES encrypted using the senders public key (only sender can decrypt EPASA)               |
| PasswordEncPayload | A payload which is AES256 encrypted using the specified password                                              |
| Payload            | The actual payload data, specified it an well-defined encoding                                                |
| PayloadChecksum    | An UINT16 specified by two hexbytes (4 hexnibbles) that denotes a checksum of payload, used to ensure payload consistency (prevents typo/copy-paste errors)  |
| Password           | The password used in PasswordEndPayload. Must be specified as a SafeAnsiString (chars 32..126)                |
| Pascal64String     | An ANSI string involving a limited subset used for account names (cannot start with a digit)                  |
| SafeAnsiString     | An ANSI string involvolving subset characters 32..126                                                         |
| Base58String       | A Base58-encoded string. This is used for specifying public keys, and hashes of public keys                   |
| HexString          | A hexadecimal-encoded string prefixed with a 0x. Every byte specified by two hexdigits, lower-case            |


**NOTES**: 
 * Text payload and passwords are restricted to ANSI charset subset range 32..126
 * The following characters **\\**, **"**, and **}** must be escaped in ASCII payloads/AES passwords via preceding **\\**
 * Payload content is 

#### Validation Rules

#### AccountNumber Checksum

Layer-1 account checkum must be the following number:

```
  Checksum = ((AccountNumber*101) MOD 89) + 10
```

**NOTE** AccountNumber above denotes the integer portion of the string.

**IMPORTANT**: Whilst the E-PASA grammar allows optional PASA checksum, this is purely for convenience. Implementations are expected to automatically fill-in the checksum if not specified in the input.

#### Pascal64String 

These strings are used to denote an account names and conform to the following rules.
- By definition, they must **not** start with a digit. 
- String length must between 3..64 inclusive.

#### E-PASA Checksum

In order to avoid data entry errors, the EPASA is checksummed. In short, the E-PASA checksum is simply the 16-bit MurMur3 hash of all preceding text. 

Formally, the EPASA checksum is defined as follows:

```
    PayloadChecksum = ToHexStringLE ( CastToUINT16( MurMur3( ToAsciiBytes ( PASA ++ ExtendedAddress ) ) MOD 65536 ) )

    where
       ToAsciiBytes    = converts ASCII string argument into raw byte form, character by character (no endianness concerns here)                
       MurMur3         = performs 32bit MurMur3 hash of the byte array argument                
       CastToUINT16    = casts the integer argument into to a 16bit unsigned integer (should never overflow due to modulo 65536)
       ToHexStringLE   = converts the 16bit unsigned integer argument into 4 hexadecimal characters in little-endian
```

**IMPORTANT**: Whilst the E-PASA grammar allows optional E-PASA checksums, this is purely for convenience. Implementations are expected to automatically fill-in the checksum if not specified in the input.

#### Payload Lengths

The following validation rules must be applied to Payload lengths

|  Payload Type        | Encryption Mode  |  Byte-form Length   | E-PASA string-form length  |
| :------------------- | :--------------- | :------------------ | :------------------------- |
| ASCII                | None (Public)    | 255                 | 255                        |
| ASCII                | ECIES            | 144                 | 144                        |
| ASCII                | AES              | 223                 | 223                        |
| Hexadecimal          | None (Public)    | 255                 | 510+2                      |
| Hexadecimal          | ECIES            | 144                 | 288+2                      |
| Hexadecimal          | AES              | 223                 | 446+2                      |
| Base58               | None (Public)    | 255                 | 348                        |
| Base58               | ECIES            | 144                 | 196                        |
| Base58               | AES              | 223                 | 304                        |

**NOTE:** +2 accounts for "0x" prefix for hexadecimal strings

#### Payload Type

In order for an operation receiver to **automatically decode** an E-PASA from the raw network payload in the **exact same form** that it was entered by the sender, an additional *PayloadType* field is required for all operations that carry a Payload.

The PayloadType indicates how the raw network payload was encrypted and has general-purposes usage beyond this PIP.

For E-PASA, the PayloadType allows the receiver to deterministically and unambiguously derive the E-PASA used by the sender, including the encryption type and payload type (i.e. ascii/hex/base58) as well as if an account name was used instead of an account number.

This capability is fundamental for using E-PASA as an *address-space* in Layer-2 applications. Without this, a Layer-2 application could decode a single raw network payload in a multitude of E-PASA forms breaking the 1-1 relationship necessary to establish uniqueness.

#### Payload Type Specification:

| Value    | Interpretation                                                                  |
| -------: | :------------------------------------------------------------------------------ |
| 00000000 | Non-deterministic (requires manual decoding by receiver and **not** an E-PASA)  |
| 00000001 | Public payload (E-PASA shows empty payload)                                     |
| 00000010 | ECIES-Sender encrypted payload (E-PASA shows empty payload)                     |
| 00000100 | ECIES-Receiver encrypted payload (E-PASA shows empty payload)                   |
| 00001000 | AES encrypted payload (E-PASA shows empty payload)                              |
| 00010001 | Public payload in ASCII encoding                                                |
| 00010010 | ECIES-Sender encrypted payload in ASCII encoding                                |
| 00010100 | ECIES-Receiver encrypted payload in ASCII encoding                              |
| 00011000 | AES encrypted payload in ASCII encoding                                         |
| 00100001 | Public payload in hexadecimal encoding                                          |
| 00100010 | ECIES-Sender encrypted payload in hexadecimal encoding                          |
| 00100100 | ECIES-Receiver encrypted payload in hexadecimal encoding                        |
| 00101000 | AES encrypted payload in hexadecimal encoding                                   |
| 01000001 | Public payload in Base58 encoding                                               |
| 01000010 | ECIES-Sender encrypted payload in Base58 encoding                               |
| 01000100 | ECIES-Receiver encrypted payload in Base58 encoding                             |
| 01001000 | AES encrypted payload in Base58 encoding                                        |
| 10000000 | Non-deterministic (E-PASA shows Account Name)                                   |
| 10000001 | Public payload (E-PASA shows Account Name and empty payload)                    |
| 10000010 | ECIES-Sender encrypted payload (E-PASA shows AccountName and empty payload)     |
| 10000100 | ECIES-Receiver encrypted payload (E-PASA shows AccountName and empty payload)   |
| 10001000 | AES encrypted payload (E-PASA uses AccountName and empty payload)               |
| 10010001 | Public payload in ASCII encoding (E-PASA shows Account Name)                    |
| 10010010 | ECIES-Sender encrypted payload in ASCII encoding (E-PASA shows Account Name)    |
| 10010100 | ECIES-Receiver encrypted payload in ASCII encoding (E-PASA shows Account Name)  |
| 10011000 | AES encrypted payload in ASCII encoding (E-PASA shows AccountName)              |
| 10100001 | Public payload in hexadecimal encoding (E-PASA shows AccountName)               |
| 10100010 | ECIES-Sender encrypted payload in hexadecimal encoding (E-PASA shows AccountName)|
| 10100100 | ECIES-Receiver encrypted payload in hexadecimal encoding (E-PASA shows AccountName)|
| 10101000 | AES encrypted payload in hexadecimal encoding (E-PASA shows AccountName)        |
| 11000001 | Public payload in Base58 encoding (E-PASA shows AccountName)                    |
| 11000010 | ECIES-Sender encrypted payload in Base58 encoding (E-PASA shows AccountName)    |
| 11000100 | ECIES-Receiver encrypted payload in Base58 encoding (E-PASA shows AccountName)  |
| 11001000 | AES encrypted payload in Base58 encoding (E-PASA shows AccountName)             |


## E-PASA Examples

### Base Cases 

<table>
<thread>
    <th width="370">E-PASA</th>
    <th>Description</th>
</thead>
<tbody>
    <tr><td>123456-77</td><td>Account 123456-77 (backwards compatible with current addresses)</td></tr>
    <tr><td>pascalcoin-foundation</td><td>Account with name 'pascalcoin-foundation' no payload</td></tr>
    <tr><td>my-favorite-exchange("herman@email.com")</td><td>An account called "my-favorite-exchange" with a recipient-encrypted payload (e.g. an exchange deposit address where only exchange can see payload, used as a user ID)</td></tr>
</tbody>
</table>


### With ASCII payloads 

<table>
<thread>
    <th width="350">E-PASA</th>
    <th>Description</th>
</thead>
<tbody>
    <tr><td>123456-77</td><td>Account 123456-77 (backwards compatible)</td></tr>
    <tr><td>123456-77["Hello World!"]</td><td>With public ASCII payload "Hello World!" without checksum protection</td></tr>
    <tr><td>123456-77["Hello World!"]:10cb</td><td>Checksum protected</td></tr>
    <tr><td>123456-77("Hello World!"):7ba2</td><td>ECIES encrypted using <b>recipients</b> public key</td></tr>
    <tr><td>123456-77<"Hello World!">:b51f</td><td>ECIES encrypted using <b>senders</b> public key</td></tr>
    <tr><td>123456-77{"Hello World!":!43lp|-d|a%@#!}</td><td>AES256 encrypted payload using password <b>!43lp|-d|a%@#!</b></td></tr>
</tbody>
</table>

### With Hexadecimal payloads 

<table>
<thread>
    <th width="350">E-PASA</th>
    <th>Description</th>
</thead>
<tbody>
    <tr><td>77-44[0x416c70686124]</td><td>Account 77-44 with unencrypted (public) hexadecimal payload <b>without</b> protection</td></tr>
    <tr><td>77-44[0x416c70686124]:10cb</td><td>Checksum protected</td></tr>
    <tr><td>77-44(0x416c70686124):7ba2</td><td>ECIES encrypted using <b>recipients</b> public key (and checksum protected)</td></tr>
    <tr><td>77-44<0x416c70686124>:b51f</td><td>ECIES encrypted using <b>senders</b> public key (and checksum protected)</td></tr>
    <tr><td>77-44{0x416c70686124:!43lp-da%@#!}</td><td>AES encrypted using password <b>!43lp-da%@#!</b></td></tr> 
</tbody>
</table>


### With Base58 payloads 

<table>
<thread>
    <th width="500">E-PASA</th>
    <th>Description</th>
</thead>
<tbody>
    <tr><td>77-44[1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2]</td><td>Account 77-44 with unencrypted (public) Base58 payload (bitcoin address) <b>without</b> checksum protection</td></tr>
    <tr><td>77-44[1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2]:10cb</td><td>Checksum protected</td></tr>
    <tr><td>77-44(1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2):7ba2</td><td>ECIES encrypted using <b>recipients</b> public key</td></tr>
    <tr><td>77-44<1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2>:b51f</td><td>ECIES encrypted using <b>senders</b> public key</td></tr>
    <tr><td>77-44{1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2:!43lp-da%@#!}</td><td>AES encrypted using password <b>!43lp-da%@#!</b></td></tr> 
</tbody>
</table>


### Special Cases 

<table>
<thread>
    <th width="500">E-PASA</th>
    <th>Description</th>
</thead>
<tbody>
    <tr><td>999-72["Message with all escaped chars \\\"\} here"]</td><td>Public ANSI string <b>Message with all escaped chars \"} here</b></td></tr>
    <tr><td>999-72</td><td>Non-deterministic, raw network-level payload bytes ignored</td></tr>
    <tr><td>999-72[]</td><td>Empty Public payload, raw network-level payload bytes ignored</td></tr>
    <tr><td>999-72()</td><td>Empty ECIES payload, raw network-level payload bytes encrypted with receivers key but ignored</td></tr>
    <tr><td>999-72<></td><td>Empty ECIES payload, raw network-level payload bytes encrypted with senders key but ignored</td></tr>
    <tr><td>999-72{:}</td><td>Empty AES payload, raw network-level payload bytes AES encryped but ignored</td></tr>
    <tr><td>999-72{:pwd}</td><td>Empty AES payload, raw network-level payload bytes AES encryped with password <b>pwd</b> but ignored<b>pwd</b> but ignored</td></tr>
    <tr><td>my-account-name</td><td>Non-deterministic, raw network-level payload bytes ignored</td></tr>
    <tr><td>my-account-name[]</td><td>Empty public payload, raw network-level payload bytes ignored</td></tr>
    <tr><td>my-account-name()</td><td>Empty ECIES payload, raw network-level payload bytes encrypted with receivers key but ignored</td></tr>
    <tr><td>my-account-name<></td><td>Empty ECIES payload, raw network-level payload bytes encrypted with senders key but ignored</td></tr>
    <tr><td>my-account-name{:}</td><td>Empty AES payload, raw network-level payload bytes encrypted with empty password but ignored</td></tr>
    <tr><td>my-account-name{:pwd}</td><td>Empty AES payload, raw network-level payload bytes encrypted with password <b>pwd</b> but ignored</td></tr>
    <tr><td>999-72{"Hello":Funny\"Pwd}</td><td>AES encrypted using escaped password <b>Funny"Pwd</b></td></tr> 
    <tr><td>999-72{"Hello":\\\"\}}</td><td>AES encrypted using escaped password <b>\"}</b></td></tr>
</tbody>
</table>

## Rationale

The design approach was to remain backwards compatible so that EPASA can replace "account" in existing JSON APIs. The caller need not specify Payloads anymore since the EPASA can contain the Payload.


## Backwards Compatibility

This PIP is generally backwards compatible and does not require a hard-fork activation for using E-PASA as a convention.

For Layer-2 applications the ability for a receiver to auto-decode the E-PASA via PayloadType **does require a hard-fork**  **except** although this does not prevent usage of E-PASA for other purposes.

## Acknowledgements
* Ugochukwu Mmaduekwe for assistance developing payload length validation rules
* Benjamin Ansbach for regular feedback, assistance and insightful suggestions
* UrbanCohort for elegancy-improving suggestion
 
## Reference Implementation

WIP

## Links

None
