# MWC Slatepacks ## Contents : # * [About](./slatepack_data_format.md/#About) * [Community-level explanation](./slatepack_data_format.md/#Community-level-explanation) * [Reference-level explanation](./slatepack_data_format.md/#Reference-level-explanation) * [Slatepack Address](./slatepack_data_format.md/#Slatepack-Address ) * [Message Armor](./slatepack_data_format.md/#Message-Armor) * [Encryption/Decryption](./slatepack_data_format.md/#EncryptionDecryption) * [Binary Data Format](./slatepack_data_format.md/#Binary-Data-Format) # About Slatepacks are intented to simplify the exchange process for Slates in a secure and userfriendly way. Current file based methods have the following cons: * Files content is well readable, because of that it is not secure. * Files are susceptible to man in the middle attack because files are not addressed to specific wallet. * Users don't like files for exchanges. Sting with content is more friendly. To address those issues MWC adopts mwc's Slatepacks: https://docs.mwc.mw/wiki/transactions/slatepack/
Altho MWC slatepacks look very similar, the implementation is very different. This document desribes the Slatepack format and our deviation from mwcs Implementation. # Community-level explanation Slatepacks Simplify the existing transaction process so that a transaction can be built using a copy and pastable SlatepackMessage string asynchronously. So in easier words this simplyfies transactions alot as it's usable by a simple copy paste without the requirement to be online or to exchange files. An Example to elaborate; ```mwc-wallet send -d SlatepackAddress 1.337``` will generate an armored encrypted SlatepackMessage string that only you and the recipient can decipher if a TOR address was used as SlatepackAddress. In the case of MQS it will generate a non encrypted SlatepackMessage.
If a counterparty is unwilling or unable to provide a SlatepackAddress, an unencrypted plain text SlatepackMessage can still be exchanged This SlatepackMessage can then be exchanged manually by copy and paste. Example SlatepackAddress: f4ujdq2hzidsrwljst4mfxoaogolqzhwzbu4uxjke6w4ibclqgxaowid Sending a mobile MWC transaction should be as easy as scanning a simple QR code encoded from a bech32 SlatepackAddress Or as easy as pasting the SlatepackAddress of your counterparty into your wallet for any other device. Then the SlatepackMessage can be exchanged easily via copy and paste with a counterparty in an alternative communication channel (email, forum, social media, instant messenger, generic web text box, carrier pigeon etc.) # Reference-level explanation ## Slatepack Address MWC has a 'ProvableAddress' that includes a TOR or MQS address. For Slatepacks we will continue to use them. For encrypted Slatepacks only TOR addresses can be used because of encryption/decryption internals. If the ProvableAddress is a MQS Address it can't be used for encrypted slatepacks, but will generate an unencrypted SlatepackMessage instead. Please note, ProvableAddress is applicable to encrypted slatepack only. ## Message Armor Mwc Armor does binary to Base58 conversion and it works great for us. This part works as it is, the only change is the header and footer. https://docs.mwc.mw/wiki/transactions/slatepack/#armor For normal encrypted slatepacks the header/footer are: BEGINSLATEPACK / ENDSLATEPACK For non encrypted slatepacks in binary format the header/footer are: BEGINSLATE_BIN / ENDSLATE_BIN ## Encryption/Decryption Mwc's original design is using the 'age' rust library for encryption/decryption. The Age library had a huge data overhead on data size. The header is about 350 bytes. For example, initial send message size less then 150 bytes. Such overhead is not acceptable. Also it is not clear if age will allow to read the message that was archived. In MWC's implementation we don't use age, encryption/decryption is done with the same primitives as described below; ### Encryption (sender side) * Sender supply it's own ed25519 secret and receiver ed25519 public key. * sender's ed25519 SecretKey and recipient's ed25519 PublicKey are converted to x25519 StaticKey and x25519 PublicKey * calculating Diffie Hellman Shared Secret value. * Encrypt the data with this Shared Secret using symmetrical AEAD CHACHA20_POLY1305 algorithm. * Resulting data is 16 bytes larger then original one. ## Decryption (recipient side) * Read sender ed25519 PublicKey from unencrypted part of the payload. The recipient supply it's own ed25519 SecretKey. * recipient's ed25519 SecretKey and sender's ed25519 PublicKey are converted to x25519 StaticKey and x25519 PublicKey * calculating Diffie Hellman Shared Secret value. * Decrypt the data with this Shared Secret using symmetrical AEAD CHACHA20_POLY1305 algorithm. * Resulting data is 16 bytes smaller then original one. ## Slatepack Binary Data Format Users working with armored message, but underneath it is a pure binary format. Here we describe the format, so it will be easier to understand it. MWC slate data is using bit streaming as a format for data serialization. The serialization/deserialization functions are symmetrical and aren't using serde because we want full control to maintain compatibility. Backward compatibility will be maintained. The forward compatibility is nice to have, but it is not guaranteed. ### Slate package binary (not encrypted) header Data | Size | Descryption ---- | ---- | ----------- | Version | 1 byte | The slatepack binary format version. This version is global for all parts. Sender Public Key | 30 bytes | Sender public key. Needed to decode the encrypted data by receiver Receiver Public Key | 30 bytes | Receiver Public key. Needed to decode encryptrd by sender (archived data) Nonce | 12 bytes | AEAD message nonce Encrypted Data Size | 2 bytes | Length of the encrypted data in bytes ### Slate package encrypted data. Data | Size | Descryption ---- | ---- | ----------- | content | 3 bit | The content of the salte. Currently support: SendInitial, SendResponse, InvoiceInitial, InvoiceResponse, FullSlate values Slate UUID | 16 bytes | UUID of the slate. Need to identify transaction Network | 1 bit | 1 for mainnet and 0 for floonet/testnet amount | Varibale | Optional, Amount of the slate, nano coints fee | Varibale | Optional, Transaction fee, nano coints height | Varibale | slate height lock_height | Varibale | locking height Option ttl_cutoff_height | Varibale | TTL value of the slate Slate offset | 32 bytes | Optional, Transaction offset (blinding factor) Inputs types | 1 bit | Optional, 1 for commit + feature per input. 0 - just commits Input feature | 1 bit | Optional, 0 for Plain, 1 for Coinbase Input commit | 33 bytes | Optional, Input commit Input stop bit | 1 bit | Optional, 1 if has another input. O if no more inputs left to read Output commit | 33 bytes | Optional, Output commit Output Range proof size | 10 bits | Optional, Length of thange proof data Output Range proof | length | Optional, Range proff content Output stop bit | 1 bit | Optional, 1 if has another output. O if no more outputs left to read Kernel commit | 33 bytes | Optional, Kernel commit. Kernel signature | 64 bytes | Optional, Kernel signature Kernel stop bit | 1 bit | Optional, 1 if has another kernel. O if no more kernels left to read Participant blind Excess size | 7 bits | Optional, size of the blind excess public key Participant blind Excess | length | Optional, blind excess PK data Participant Nonce size | 7 bits | Optional, size of the nonce Participant Nonce | length | Optional, nonce data Participant signature flag | 1 bit | Optional, 1 if signature present, 0 if not Participant signature | 64 bytes | Optional, participant signature Participant message flag | 1 bit | Optional, 1 if message present, 0 if not Participant Message size | 16 bits | Size of the compressed text message Participant message | length | Message compressed with smaz algorithm Another participant data | | Optional, another participant data. Proof flag | 1 bit | Optional, 1 if proof data present, 0 if not Proof Sender Address | variable | Optional, the sender address saved as binary Dalek PK or secp256k1 PK Proof Receiver address | variable | Optional, the receiver address saved as binary Dalek PK or secp256k1 PK Proof Signature flag | 1 bit | Optional, 1 if signature data present, 0 if not Proof Signature len delta | 4 bit | Optional, length can be longet then 64 byte (can be 70). Len is 64 + this_value Proof Signature | 64 bytes | Optional, signature data Future usage | any | Here we can write encrypted frontward compatible data. CRC32 | last 4 bytes | The check sum for Unencrypoted and Encrypted data. It allow to verify is unencrypted or encrypted data was adjusted ## Slate package binary (not encrypted) tail Currently nothing, can be used for frontward compatible data.