-
Notifications
You must be signed in to change notification settings - Fork 316
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #142 from stellar/attachments
Attachments
- Loading branch information
Showing
1 changed file
with
121 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
## Preamble | ||
|
||
``` | ||
SEP: xxxx | ||
Title: Attachment Convention | ||
Author: stellar.org | ||
Status: Draft | ||
Created: 2018-08-03 | ||
``` | ||
|
||
## Simple Summary | ||
Sometimes there is a need to send more information about a transaction than fits in the provided memo field, for example: KYC info, an invoice, a short note. Such data shouldn't be placed in the [ledger](https://www.stellar.org/developers/guides/concepts/ledger.html) because of it's size or private nature. Instead, you should create what we call an attachment. A Stellar attachment is simply a JSON document. The `sha-256` hash of this attachment is included as a `memo_hash` in the transaction. The actual attachment document can be sent to the receiver through some other channel, most likely through the receiver's [Auth server](./sep-0003.md). | ||
|
||
## Specification | ||
|
||
The attachment has a following structure: | ||
|
||
```json | ||
{ | ||
"nonce": "<nonce>", | ||
"transaction": { | ||
"sender_info": { | ||
"first_name": "<first_name>", | ||
"middle_name": "<middle_name>", | ||
"last_name": "<last_name>", | ||
"address": "<address>", | ||
"city": "<city>", | ||
"province": "<province>", | ||
"country": "<country in ISO 3166-1 alpha-2 format>", | ||
"date_of_birth": "<date of birth in YYYY-MM-DD format>", | ||
"company_name": "<company_name>" | ||
}, | ||
"route": "<route>", | ||
"note": "<note>" | ||
}, | ||
"operations": [ | ||
{ | ||
"sender_info": <sender_info>, | ||
"route": "<route>", | ||
"note": "<note>" | ||
}, | ||
// ... | ||
] | ||
} | ||
``` | ||
|
||
Attachments can be extended with extra information however, the should contain the following fields: | ||
|
||
Name | Data Type | Description | ||
-----|-----------|------------ | ||
`nonce` | string | [Nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) is a unique value. Every transaction you send should have a different value. A nonce is needed to distinguish attachments of two transactions sent with otherwise identical details. For example if you send $10 to Bob two days in a row. | ||
`transaction.sender_info` | JSON | JSON containing KYC info of the sender. This JSON object can be extended with more fields if needed. | ||
`transaction.route` | string | The route information returned by the receiving federation server (`memo` value). Tells the receiver how to get the transaction to the ultimate recipient. | ||
`transaction.note` | string | A note attached to transaction. | ||
`operations[i]` | | `i`th operation data. Can be omitted if transaction has only one operation. | ||
`operations[i].sender_info` | JSON | `sender_info` for `i`th operation in the transaction. If empty, will inherit value from `transaction`. | ||
`operations[i].route` | string | `route` for `i`th operation in the transaction. If empty, will inherit value from `transaction`. | ||
`operations[i].note` | string | `note` for `i`th operation in the transaction. If empty, will inherit value from `transaction`. | ||
|
||
### Sending Attachments | ||
|
||
An attachment and its hash (in a transaction) can be sent to Auth server of a receiving organization using [Compliance protocol](./compliance-protocol.md). | ||
|
||
### Calculating Attachment hash | ||
|
||
To calculate the Attachment hash you need to stringify the JSON object and calculate `sha-256` hash. In Node.js: | ||
|
||
```js | ||
const crypto = require('crypto'); | ||
const hash = crypto.createHash('sha256'); | ||
|
||
hash.update(JSON.stringify(attachment)); | ||
var memoHashHex = hash.digest('hex'); | ||
``` | ||
|
||
To add the hash to your transaction use the [`TransactionBuilder.addMemo`](http://stellar.github.io/js-stellar-base/TransactionBuilder.html#addMemo) method. | ||
|
||
#### Example | ||
|
||
```js | ||
var crypto = require('crypto'); | ||
|
||
var nonce = crypto.randomBytes(16); | ||
var attachment = { | ||
"nonce": nonce.toString('hex'), | ||
"transaction": { | ||
"sender_info": { | ||
"name": "Sherlock Holmes", | ||
"address": "221B Baker Street", | ||
"city": "London NW1 6XE", | ||
"country": "UK", | ||
"date_of_birth": "1854-01-06" | ||
} | ||
}, | ||
"operations": [ | ||
// Operation #1: Payment for Dr. Watson | ||
{ | ||
"route": "watson", | ||
"note": "Payment for helping to solve murder case" | ||
}, | ||
// Operation #2: Payment for Mrs. Hudson | ||
{ | ||
"route": "hudson", | ||
"note": "Rent" | ||
} | ||
] | ||
}; | ||
|
||
var hash = crypto.createHash('sha256'); | ||
hash.update(JSON.stringify(attachment)); | ||
var memoHashHex = hash.digest('hex'); | ||
console.log(memoHashHex); | ||
``` | ||
|
||
## Test Cases | ||
|
||
Use [GoStellar](https://gostellar.org/) application to check if Compliance protocol and attachments were implemented correctly. | ||
|
||
## Reference implementations | ||
|
||
* [`github.com/stellar/go/protocols/compliance` package](https://github.com/stellar/go/blob/master/protocols/compliance). |