stellar / stellar-protocol Goto Github PK
View Code? Open in Web Editor NEWDeveloper discussion about possible changes to the protocol.
Developer discussion about possible changes to the protocol.
Certain asset types aren't divisible. For those it doesn't make sense to be able to have fractional amounts.
For example for stocks you really only want to hold and trade integer amounts.
This could be done by creating a new Asset type:
Indivisible Alpha 12 character
Clients would interpret amounts of this asset as integers rather than moving over 7 decimal places.
I want to what type of open source is stellard.Like if i talk wordpress is php open souce.
The account_tx API call should allow you to enter in a destination tag to view transactions that affect an account with the specified destination tag.
If you are only interested in a specific customers account, this will allow faster lookups since each customer will have a unique destination tag.
Any reason for not attempting to migrate stellar.txt to JSON (or really any other format) before the gateway / wallet community grows to large to switch?
As far as I understand this is not used by StellarD directly, and would only require community adoption.
Since the TXT format isn't a standard that is widely adopted, this will lead to many people building custom parsers, this could lead to people using slightly incorrect results as more uses are built into the stellar.txt file, that weren't accommodated for in their version of Parser.
TXT Version:
[federation_url]
https://api.stellar.org/federation
[reverse_federation_url]
https://api.stellar.org/reverseFederation
[accounts]
gJGPgbCnaP3vypwoxtXWEn9tyoARywPE7F
gJGPgbCnaP3vypwoxtXWEn9tyoARywPE7F
[validators]
nakuKsirzNq66iejBfxKxt8Rw4t7kP5ZWSrvWzVKEVSHSkJKYd1 SDF1
n3gVwaSDBtVi4Xd2XBh7rvcwis4uBabu5aNn7WKtEqazJbLHR9n SDF2
nfozTPzMytTKuuHBJrPB9DVxPccKeNVh8vsEomUAwNWuWrNxwDB SDF3
naSBAykwFkmw6JLKqPG7HPFMK1GZqu1rdnwbhtTxyTmVX1b6b8z SDF4
nf3yCmpieMFvAbv5r5jBhGeXheuhc3boAkdmBbpXb6HC7HDkf13 SDF5
[currencies]
USD gJGPgbCnaP3vypwoxtXWEn9tyoARywPE7F
SCT gDSSa75HPagWcvQmwH7D51dT5DPmvsKL4q
JSON Version:
{
"federation_url": "https://api.stellar.org/federation",
"reverse_federation_url": "https://api.stellar.org/reverseFederation",
"accounts": [
"gJGPgbCnaP3vypwoxtXWEn9tyoARywPE7F",
"gJGPgbCnaP3vypwoxtXWEn9tyoARywPE7F"
],
"validators": {
"nakuKsirzNq66iejBfxKxt8Rw4t7kP5ZWSrvWzVKEVSHSkJKYd1": "SDF1",
"n3gVwaSDBtVi4Xd2XBh7rvcwis4uBabu5aNn7WKtEqazJbLHR9n": "SDF2",
"nfozTPzMytTKuuHBJrPB9DVxPccKeNVh8vsEomUAwNWuWrNxwDB": "SDF3",
"naSBAykwFkmw6JLKqPG7HPFMK1GZqu1rdnwbhtTxyTmVX1b6b8z": "SDF4",
"nf3yCmpieMFvAbv5r5jBhGeXheuhc3boAkdmBbpXb6HC7HDkf13": "SDF5"
},
"currencies": {
"USD": "gJGPgbCnaP3vypwoxtXWEn9tyoARywPE7F",
"SCT": "gDSSa75HPagWcvQmwH7D51dT5DPmvsKL4q"
}
}
Looking at account_lines and they way they are use by the official client, wouldn't is make more sense NOT to extend trust to EVERY issued currency for an issuer?
Taking justcoin as an example, there's 7318 trust lines right now. How many of those are ever going to be used? There's somewhere around 100 people actually holding currency.
If you, like me, think the stellar.txt approach is a rather weird design decision, then my only option today is to download the whole thing and parse it.
From a ledger bloat perspective, let the user decide what currencies to trust, and don't just default to "*"
From a client perspective, how about adding an "issued"-stanza to account_currencies?
Right now the clients have to jump through a lot of hoops to prevent accounts from getting stuck:
stellarterm/stellarterm#76
After stuck it is a really bad user experience to get the account usable again.
This mainly results from selling XLM for some other asset.
The proposal is to leave enough lumens in your account to pay the fee for 1000txs when:
This way the only way an account can get stuck is if they send/sell all the lumens they can and then do 1000 more txs.
Create a new DataEntry that is just a key/value pair.
These DataEntries are owned by accounts. The key would be a string and the value would be 32bytes.
There would be operations to add and remove DataEntries.
Each DataEntry would increase the storage cost of the account.
Could be used for things like attaching an encryption key to the account. Having the account publicly attest to some fact. If the account needs to provide other meta data about itself.
Federation is currently used for account related stuff. Maybe expand this with information about an asset that may be useful for wallets. Using the homedomain of the issuer's account it can query the federation server using the assetcode and address. After an initial request it can cache it for some time to not flood the federation server as the values probably won't change that much.
A wallet can use this metadata to show an asset as it is meant to be shown by the issuer. This can allow different wallets to have an uniform representation of the same asset.
Request:
https://api.stellar.org/federation?q=EUR*[issuers_address]&type=asset
Response:
status: 200
{
code: "EUR",
issuer: "[address]",
name: "Euro's",
symbol: "€",
ui_decimals: 2,
ui_step_increment: 0.25,
... : ?
}
Certain institutions like banks are required to approve incoming txs. They are required to know the source of incoming funds. Right now when they get a tx in from stellar they are must check the tx and if it isn't from an approved source or it isn't clear which internal account the funds are for they must return the tx.
A simpler method would be:
Add a flag to Account that says any incoming payment must also be signed by the account.
Then for bank A sending to bank B, bank A would first send the tx along with details of the sender to bank B, Bank B would sign this tx and return the signed tx to A. A would then also sign and submit the now valid tx to the network.
Not writing CAP yet, just trying to gauge interest in such feature.
Parent/Funder account creates an account with child
flag set to true
.
Child account must maintain balance higher or equal than CreateAccountOp.StartingBalance
and can only be merged with parent.
Use cases:
Rippling and offers sort of serve the same function. It seems cleaner to combine the two concepts.
You can achieve the effect of rippling if you create two offers between two currency pairs.
This would just require a new flag on the offers saying that they never expire and are always offering at the given price as long as the owner has the takerGets currency.
The time is come for us to resolve one of the niggling issues left in the new stellar network: How the API and client libraries deal with numbers that represent an "amount" in a transaction. Example amounts:
Presently, stellar-core represents these amount as a 64-bit unsigned integer and interprets the number in no other way: It's always using integer math.
However, by convention we say that uint64 is actually a fixed-place decimal number with 7 digits of precision. I'm proposing that we bake this convention into horizon and the client libraries.
To do this, and to gain the most compatibility between language-specific representations and the json representation communicated by horizon, I propose that we should encode amounts as a string containing a decimal number. Some example side effects of this change:
{
"amount": 50000000.0,
"asset_type": "native",
}
would become:
{
"amount": "5",
"asset_type": "native",
}
tx = Stellar::Transaction.create_account({
account: master,
destination: destination,
sequence: 1,
starting_balance: 50 * Stellar::ONE
})
Would become:
tx = Stellar::Transaction.create_account({
account: master,
destination: destination,
sequence: 1,
starting_balance: 50 # or '50' or BigDecimal.new(50)
})
The intention of this issue is to start a conversation around this topic; see conversation from a PR about a change in the docs for multi-sig: stellar-deprecated/docs#237 (comment)
Background:
A threshold of 0
and 1
are effectively the same since we need at least 1 key with a non-zero weight to sign a transaction. By allowing a threshold of 0
, we are creating an exception case for the logical condition sum_key_weights >= threshold
to make it more like (sum_key_weights >= threshold && threshold > 0) || (sum_key_weights > threshold && threshold == 0)
where we treat a 0-threshold differently from a non-0 threshold to account for signing transactions with a key that is weighted at 0.
Proposed solution:
If it's possible to limit the minimum threshold to be 1
, we can simplify the condition to be the former, sum_key_weights >= threshold
for all cases and more importantly, this will make it simpler for users to understand.
The tricky part here would be dealing with existing accounts and having to update all of them to use this new range (change all 0
thresholds to a 1
). There may be other approaches that could make this easier.
One of results of executing transaction in stellar protocol is txINTERNAL_ERROR - this means that server has encountered an internal bug that it could not handle (possibly an implementation error). This result is stored in history and is part of input of given ledger hash.
Current stellar protocol has only one implementation - stellar-core by stellar.org, so this is not a big issue. But in future we expect more implementations of protocol. It is hard to expect that they will have the same internal bugs and will return txINTERNAL_ERROR in the same conditions. So it will be possible that some servers will handle given transaction just right and some will return txINTERNAL_ERROR. It will result with different ledger hashes and some nodes will get desynchronized and became unusable.
Finally, these servers will have to get fixed and their history redownloaded to get in sync with other.
I think it would be better to just crash in this case (with lots of logged info, of course). In that case only internal bugs will have to get fixed, no history re-downloading will have to be done. And, what is most important, other servers will not have to reimplement that bug in case when servers returning txINTERNAL_ERROR will be a majority.
Currency codes are limited right now to 3 characters. This matches the conventions for talking about real-world currencies, but it seems like an unnecessary and arbitrary limitation when talking about stellar currencies. The restriction should be lifted.
It makes sense to put some limitations on the currency code. I'd suggest something like [a-zA-Z_][a-zA-Z0-9_./-]*
. That is, allow alphabetic characters + _
as the first letter, then add in digits, .
, /
, and -
for all remaining letters. I picked .
, /
, and -
merely because they seem like the most likely punctuation someone might want to use when e.g. building some sort of hierarchical currency code. Other punctuation should be avoided unless someone comes up with a good reason to support it.
I'd also say that if you need to restrict the length for some reason (e.g. inserting into a database), I'd suggest a 255 character limit. That's more than large enough for any reasonable purpose, while not being absurdly large.
Pros:
IOU
credit issued by two different accounts.IOU
) while still being distinct (e.g. because they represent different owed assets, or are issued to two different groups of accounts and needs to be prevented from trading between them).Cons:
TrustSet
transactions for fake currencies. However, I assume it's already possible to encode messages in e.g. destination tags on micro-payments, or perhaps SetRegularKey
transactions (depending on what sort of validation the key is given), or even a sequence of offers that cannot possibly be filled (e.g. between currencies with an issuer that is guaranteed to never issue those currencies). Expanding the currency field would only make it easier (and cheaper due to fewer fees), as opposed to enabling something that is otherwise disallowed.Currency codes are currently formatted in the long formatted like explained in the Ripple wiki: https://wiki.ripple.com/Currency_format#National_currency_.28ISO_codes.29
They could be streamlined into 4 bytes of ascii. This is assuming that we don't add demurrage, which I believe it does not belong here and belongs in here: https://www.stellar.org/api/#api-accountset like how TransferRate is set. The only thing a currency format should store is the currency code itself.
If Stellar is to become a decentralized standardized network, we need to consider the design of small details such as this.
The idea of Stellar credits is great since credits since you can track almost anything using the concept of credits. Not only can we send each other currency such as USD but we can also send each other t-shirt credits or rubber ducky credits.
It would be awesome to have precious metals (such as gold and silver) tracked as credits in the Stellar system. Current systems that hold precious metals on the behalf of a customer (like what would happen in a Stellar gateway) currently require a fee that is charged over time for holding the precious metal. In the current system of our world, it costs about 0.5-1% the value of gold per year (source: http://www.bloomberg.com/consumer-spending/2012-05-30/the-real-cost-of-owning-gold.html#slide4)
Because of what was described above, for a gateway to impose fees on ownership of gold credits, demurrage would have to be implemented in the Stellar system.
(With the blind signature implementation I have in mind, this doesnt work inside stellar, rather it works as a service from gateways, but I am putting it here, because someone might find a solution)
Blind signatures is a way to anonymously transfer credit from one account to another when both accounts trust the node that has issued the credits.
Stellar needs to implement the blind signature scheme for this to work.
How does a blind signature work?
Let U,Ua, Tu, where U is the user account that trusts Tu and Ua is the anonymous account of the user that trusts Tu.
An anonymous transfer from U to Ua happens in this way:
Ua requests a deposit slip of a sum X from stellar.
The stellar network encrypts a unique random number R and sends it to Ua.
Ua gives it to U.
U multiplies it with a specific type of random number and blinds it.
U sends it to stellar.
The ledger removes X credit from the U account and signs the blind deposit slip.
U knows R.
U gives R to Ua.
Ua gives R to stellar and the stellar ledge adds X credit to the Ua account.
For technical information, look at this: https://en.wikipedia.org/wiki/Anonymous_Internet_banking
How can one perform an anonymous transaction with blind signatures?
Let S, Sa, Ts, where S is the sender account that trusts Ts and Sa is the anonymous account of the sender that trusts Ts.
Let R, Ra, Tr, where R is the receiver account that trusts Tr and Ra is the anonymous account of the sender that trusts Tr.
The sender sends anonymously credit from S to Sa.
The sender uses the stellar network to transfer credit to the Ba account.
The recipient sends anonymously credit from Ba to B.
The switch to having timestamps as seconds after year 2000 gives only 30 years compared to unix timestamp. This doesn't significantly affect the long term timebomb of a 32-bit epoch. Using a uint32, we will run out of space in 2106 with a unix timestamp and 2136 with the 2000 timestamp.
Timestamp libraries are also complex due to the many edge cases (leap years, leap seconds). This complicates things for developers. It would be easier to be compatible with existing unix timestamp libraries.
I'm thinking that a 64-bit unix time stamp would be a better choice especially if we want to plan for long term success of Stellar.
What I mean by this is that when I create an offer with a selling asset of ABCD, my account's asset balance for ABCD is not diminished (I am referring to the asset balance returned by Horizon for the account, I assume this is the same balance that exists in the db).
This results in an individual being able to create multiple offers that sum to a greater balance than is in their account.
I tested this on the test network as follows:
I think this behavior is buggy for several reasons:
I think that an effect of manageOffer should be an adjustment to the account's asset balance.
Imagine a gateway which requires email confirmation to authorise trust lines. For such a gateway implementing the cold & hot wallet pattern would be meaningless as the issuing account private (master or regular) key would still have to be present on the servers to authorise trust-lines.
It would be nice if it was possible to limit the access granted to the regular key. A flag of what the regular key can authorise: payment, trust set, offers, etc.
So if I want the regular key to be able to only authorise trust lines, I can safely have the key on my servers without having to worry about too much damage that could be done should it be stolen.
Bump sequence allows to bump forward the sequence number of the source account of the operation.
If the specified bumpTo
sequence number is greater than the source account's sequence number,
the account's sequence number is updated with that value, otherwise it's not modified.
Threshold: Low
Note:
This operation only allows bumping the sequence number up to (current_ledger_number<<32) - 1
.
The source account's sequence number was successfully updated.
The specified bumpTo
parameter is greater than the maximum allowed, see note above.
struct BumpSequenceOp
{
SequenceNumber bumpTo;
};
/******* BumpSequence Result ********/
enum BumpSequenceResultCode
{
// codes considered as "success" for the operation
BUMP_SEQUENCE_SUCCESS = 0,
// codes considered as "failure" for the operation
BUMP_SEQUENCE_TOO_FAR = -1 // operation would bump past the maximum sequence number allowed
};
union BumpSequenceResult switch (BumpSequenceResultCode code)
{
case BUMP_SEQUENCE_SUCCESS:
void;
default:
void;
};
Currently a transaction set is processed in two phases:
The problem with this approach is that with the introduction of an operation like BumpSequenceOp
,
we have some inconsistencies in the way transactions are processed:
if a transaction bumps the sequence number of an account used in a later transaction, the second
transaction is expected to fail but with the current implementation, it won't (as sequence number
checks are performed while collecting fees).
One the reasons that BumpSequenceOp
is introduced is to invalidate ranges of transactions, and
with the current behavior it would make it difficult to reason about the correctness of sequence
of transactions.
Only process fees first:
We would not change the logic to construct or validate a transaction set:
a transaction set would still be built with transactions that have consecutive sequence numbers.
The difference is that in the event that a transaction is invalidated by an operation from
a different transaction, it would fail (collecting fees), which allows for transactions that make use of BumpSequenceOp
to be able to make clean assumptions for any operations scheduled for after the bump.
A typical use for this is to allow invalidating large ranges of transactions that were pre-shared with others when implementing complex multi-party transactions that form workflows.
This example has two such workflows:
(sequence number, tx source account)[operation1... operation b]
(1, A)[...], ... , (99, A)[...]
Some transactions may have the same transaction number, as they are logically equivalent to branches:
(5,A)(payment B->C)
(6,A)(payment B->E)
(5,A)(bumpSeq 199)
(200,A)(...), ..., (250, A)(...)
We may want to consider doing something similar to Bitcoin's BIP70. It gives several benefits to merchants such as a simpler communication method between user and merchant as well as returns.
https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki#output
http://blog.bitpay.com/2014/06/09/payment-protocol-for-wallets.html
This would be on the same level as federation: not interacting with the daemon but rather web servers and users.
This should work like account_merge
operation but before merging it'd remove all subentries. Trust lines balances are sent to:
destination
for shared trust lines.destination
does not have a trust line.Use cases:
account_merge
it would need only one.This would allow people to send private messages to accounts. We definitely need this ability for a lot of things. For example when banks are exchanging KYC info of their customers it should be encrypted.
The alternative to sticking the encryption keys in the ledger is sticking them in the stellar.toml and as federation results.
The upside of sticking in the ledger is that it is more flexible and requires people to set up less infrastructure outside of the core network. It requires less third parties.
The downside is adding more stuff in the ledger and extra complexity in the core.
Often you need to include more info with a transaction than will fit into the 32 bytes available for memos in a Stellar transaction. You can do this by including the just the hash of the longer message in the Stellar transaction using MEMO_HASH
and then providing some way for recipients to retrieve the preimage of the hash. See message server.
Memos are used for things like:
Although you can technically put anything in the hash preimage, these messages are intended to be understood by other clients. Therefore it is helpful to follow the Stellar Memo Convention.
Memos are in JSON format. They are parsed in two passes. The first pass decrypts the encrypted parts of the memo. This pass generates a new JSON object that can then be parsed by the application.
Fields with $str_
are reserved.
encrypt_v1
is https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes.html
Any JSON field can have either a normal JSON value or an encrypted object of this format:
field | description |
---|---|
$str_type | Currently only encrypt_v1 is supported. |
$str_for | (optional) hint of what public encryption key can decrypt this message. |
$str_value | The encrypted message in base64. |
{
"$str_type": "encrypt_v1",
"$str_for": "G56789",
"$str_value": "AAAAZ2VsbG8="
}
When an encrypted object is found the $str_value
field is decrypted and the JSON is changed to just the decrypted value.
empty:
packed:
{}
unpacked:
{}
no_blocks:
packed:
{"foo": 1234 }
unpacked:
{"foo": 1234 }
top_encrypted:
packed:
{
"$str_type": "encrypt_v1",
"$str_for": "G56789",
"$str_value": "AAAAZ2VsbG8="
}
unpacked:
{"foo": 1234 }
child_encrypted:
packed:
{
"foo": {
"$str_type": "encrypt_v1",
"$str_for": "G56789",
"$str_value": "AAAAZ2VsbG8="
}
}
unpacked:
{"foo": 1234 }
arrays:
packed:
{
"foo": [
"simple",
{
"$str_type": "encrypt_v1",
"$str_for": "G56789",
"$str_value": "AAAAZ2VsbG8="
}
]
}
unpacked:
{"foo": ["simple", 1234] }
After the JSON is decrypted it can be sent to the application for further processing. The following are common fields but applications are free to use their own
field | description |
---|---|
operations[] | Array of info specific to each operation. |
note | Arbitrary text attached to this transaction or operation intended to be displayed to the recipient. |
sender_info | Compliance info for the sender. See below. |
route | Gateway specific routing info for the recipient. (accountID, or username, etc) |
field | description |
---|---|
name | Full name of sender |
address | Mailing address of sender |
stellar | Payment address of sender (bob*kraken.com) |
DOB | Date of Birth |
Simple route with message
{
"note": "Hey thanks for all the Kelp."
"route": "6387622"
}
Half-Encrypted message
{
"note" : "You can read this but there is secret stuff below."
"route": {
$str_type: "encrypt_v1",
value: E( "127682" )
}
}
Transaction with 3 payments that each need route info and two of the routes are encrypted.
{
operations: [{
"route": "bob"
}, {
"route": "127682"
}, {
$str_type: "encrypt_v1",
value: E("route : 127682")
}
}]
}
Not a fully baked idea but would help people like satoshipay and stronghold that want to allow users to have accounts and trustlines but not worry they will run off with the lumens.
Transaction Meta takes up a huge amount of disk space and it doesn't seem to provide much more than can be figured out from looking at the ledger before and after. The only use I can see for it is to easily give clients their balance after each tx. But some other client serving server could figure it all out from the raw tx if need be. It doesn't really need to be stellards job.
Thoughts?
A bunch of API methods accept optional ledger_index
or ledger_hash
parameters. They fulfill the same role and since it's easy to distinguish between "current", "validated", an integer or a hash string, I think they can be merged into a single ledger
parameter which would accept any of those values.
This was decided here: stellar/stellar-core#599
Destination tags, as I understand them, are unsigned 32-bit integers. That seems like an unnecessary limitation. They should be 64-bit integers. JavaScript can use strings to represent them if that's a concern (as JavaScript can only represent integers up to 52 bits).
A few points in favor:
[email protected]
. As an example of who might need more than 4 billion tags, a gateway that converts between STR and BTC (assuming BTC also is ubiquitous) might, as BTC addresses are free to create and therefore you could have tens or hundreds of addresses per user.I can't think of any good reason against this change. 64-bit integers are easy to handle in modern software, have no real performance penalty to speak of, and as I said before, JavaScript clients can treat it as a string, they have no need to actually represent it as a number
We need some standard way for clients to load meta information for assets and tokens in the network.
Things we need:
There are two ways this could be done:
A) Set the home_domain of the issuing account and place a stellar.toml file at the given home_domain. Then add the additional info to the [[currency]] block
B) use manage_data and add an IPFS hash of to the issuing account. This hash points to some JSON file that is stored in IPFS. Like I do here: https://www.stellar.org/blog/tokens-on-stellar/
I think A makes the most sense as it will be the easiest for issuers and clients. Thoughts?
One issue we came up on when we did the signup page for the inflation pool was getting users to trust a page enough to put their private key into a form field.
The signup code itself is only 20-30 lines of code, but since we're hosting js-stellar-sdk ourselves, users will have to make sure our version is not instrumented in any way.
Having SDF host the javascript libraries would be very helpful, since the end-users ultimately have to trust SDF. (If they don't, they're in the wrong place anyway)
Something like this perhaps:
cdn.stellar.org/{version-number}}/stellar-sdk.min.js
If you also publish hashes (together w/ the github tag commit perhaps) that would be extra helpful, as web pages could just add SRI to make sure the files aren't changed on your side.
... so as to decrease the trust limit of the line in case his new limit is lower than the number of ious he currently holds.
The documentation, says that the sender should attach the refund address to the "attachment" json. What should the key be?
From Federation doc:
Your stellar.toml file should specify what parameters you expect in a forward federation request
We need to add information about it in stellar.toml doc. Probably something like:
FORWARD_FEDERATION_PARAMS=[
"forward_type", # One of "bank_account", "mobile_number"
"swift", # Bank account SWIFT code, forward_type=bank_account
"acct", # Bank account number, forward_type=bank_account
"mobile_number" # Mobile number, forward_type=mobile
]
CC: @jedmccaleb
Complying with AML laws requires financial institutions (FIs) to know not only who their customers are sending money to but who their customers are receiving money from. In some jurisdictions banks are able to trust the KYC procedures of other licensed banks. In other jurisdictions each bank must do its own sanction checking of both the sender and the receiver.
The Identity protocol handles all these scenarios.
The Identity Protocol is an additional step after federation. In this step the sending FI contacts the receiving FI to get permission to send the transaction. To do this the receiving FI creates an AUTH_SERVER
and adds it's location to the stellar.toml of the FI.
The auth endpoint handles two different request types, Auth request
and Check request
.
HTTP POST to https://AUTH_SERVER?data=<json>&sig=<sender sig of data>
data is a block of JSON that contains the following fields:
Name | Description |
---|---|
sender | The stellar address of the customer that is initiating the send. |
need_info | If the caller needs the recipient's KYC info in order to send the payment. |
tx | The transaction that the sender would like to send in XDR format. This transaction is unsigned. |
memo | The full text of the memo the hash of this memo is included in the transaction. The memo field follows the Stellar memo convention and should contain at least enough KYC info of the sender to allow the receiving financial institution to do their sanction check. |
sig is the signature of the data block made by the sending financial institution. The receiving institution should check that this signature is valid against the public key that is posted in the sending financial institution's stellar.toml.
The auth request will return a JSON object with the following fields:
Name | Description |
---|---|
info_status | If this FI is willing to share KYC info or not. {ok, denied, pending} |
tx_status | If this FI is willing to accept this transaction. {ok, denied, pending} |
dest_info | (only present if info_status is ok) JSON of the recipient's KYC info. in the Stellar memo convention |
pending | (only present if info_status or tx_status is pending) Estimated number of seconds till the sender can check back for a change in status. See [check request](#Check request) below. |
Reply Example
{
info_status: "ok",
tx_status: "pending",
dest_info: {
type: "encrypt",
value: "TGV0IHlvdXIgaG9wZXMsIG5vdCB5b3VyIGh1cnRzLCBzaGFwZSB5b3VyIGZ1dHVyZS4="
},
pending: 3600
}
Check request is used by the sender to follow up if the initial [Auth request](#Auth request) wasn't able to complete in real time, i.e. either info_status
or tx_status
returned pending.
HTTP GET to https://AUTH_SERVER?checkreq=<tx_id>
checkreq tells the AUTH_SERVER that the caller wants an update on the status of the given tx_id
. The tx_id is simply the hash of transaction that was auth requested initially.
Check request has the same reply format as [auth request](#Auth request). It should update the status or tell the caller to continue to wait.
In this example, Aldi aldi*bankA.com
wants to send to Bogart bogart*bankB.com
1) BankA gets the info needed to interact with BankB
BankA -> fetches bankB.com/.well-known/stellar.toml
from this .toml file it pulls out the following info for BankB:
2) BankA gets the routing info for Joe so it can build the transaction
BankA -> https://FEDERATION_SERVER?type=name&q=bogart*bankB.com[&simple_kyc=true]
See Federation for a complete description. The returned fields of interest here are:
3) BankA makes the Auth Request to BankB
This request will ask BankB for Bogart's KYC info and for permission to send to Bogart.
BankA -> https://AUTH_SERVER?data=<json>&sig=<bankA sig of data>
Example data JSON
{
sender: "aldi*bankA.com",
need_info: "true",
tx: <base64 encoded xdr of the tx>,
memo:
{
type: "encrypt"
value: encrypted(
{
route: <Bogart's routing info>
sender_info:
{
stellar: aldi*bankA.com
name: Aldi Dobbs
address: <blah>
}
})
}
}
4) BankB handles the Auth request
bankA.com/.well-known/stellar.toml
tx_status
.info_status: "pending"
in the Auth request reply to give Bogart time to accept the payment or not.See [Auth Request](#Auth Request) for potential return values.
5) BankA handles the reply from the Auth request
If the call to the auth request returned pending
, BankA must check again after the estimated number of seconds.
BankA -> https://AUTH_SERVER?checkreq=tx_id
6) BankA does the sanction checks
Once BankA has been given the dest_info
from BankB, BankA does the sanction check using this KYC info of Bogart. If the sanction check passes, BankA signs and submits the transaction to the Stellar network.
7) BankB handles the incoming payment.
Right now, the only standard way to generate a secret key is through using a secret key. Thats not very user friendly. It'd be nice to have a standard for either:
It would be nice to have something standardized and well thought out and secure.
It would be nice if the freezing of IOUs would be back-ported from Ripple to Stellar. I think it will play a crucial role when trying to convince current financial establishments to start using Stellar.
Currently the only way to ensure the ability to freeze funds is for the GW to create authorised accounts and give the user access to the regular key only. It would be fine, until several GWs started using this practice. Having two gateways doing this would mean it would be very hard to trade between IOUs issued by those GWs.
Having the freezing option would mean the GW can just release the IOUs to any Stellar account - knowing they can freeze them whenever there is real need for it.
Need an API to get the count of login attempts failure for a stellar account ID. This API should retrive the data collected by the function loginFailureTracker.record(req.ip).
This will be a good alternative similar to the feature offered by web based email providers who notify us when there are failed login attempts. This is a must have feature until 2FA is implemented.
function actuallyLogin() {
wallet.get(id).then(function(wallet) {
if(typeof wallet === "undefined") {
//TODO: confirm this works well behind cloudflare
loginFailureTracker.record(req.ip);
fail();
} else {
res.send({
"status" : "success",
"data" : _.omit(wallet, ['recoveryId', 'recoveryData'])
});
}
});
}
Right now you can only specify how much they will receive and how much you ultimately send varies. There are use cases where you really want to do it the other way, specify how much you send and vary how much is received.
The ability to authorize certain transactions by approving their hash under the account signers is quite a powerful concept. It also has the potential to cater for a certain subset of smart contracts, if used creatively. A state machine can be constructed with the prepared transactions that make up a chain of valid actions that can be executed.
For example, a near-zero-trust escrow account contract could be constructed using those principles. In an escrow smart contract we need 3 parties: the sender, the recipient and the 3rd party dispute resolver. The contract needs to support the following state flows:
This can be achieved by preparing the following transactions:
In order for all parties to trust the contract, the transactions which produce the pre-authorized hashes need to be known by all parties. In effect those transactions can be considered well-known and public knowledge.
In order to setup the transactions in that way we need to rely on couple of assumptions:
My first attempt at limiting transactions to certain signers was to add the signer and increasing the required weights at the start of the transaction and remove them at the end. But apparently the transaction signature validation happens too early for this kind of approach to work (stellar/stellar-core#1329). My second attempt at this was to add the signers to the account and remove the disallowed signers at the beginning of the transaction which results in the transaction failing for wrong users, which by transaction ACID promises made by documentation should work fine. See below for example code of constructing the transactions.
But in reality even the failed transaction manages to increase the account sequence number according to stellar/stellar-core#1330 . Which basically makes well-known public transactions useless as anyone can try to execute them and make them invalid for the future. For example, in our previous escrow example the sender could take the transaction meant for the recipient, submit it with the wrong signatures and the recipient wouldn't ever be able to use that transaction themselves.
In stellar/stellar-core#1330 vogel suggested proposing changes to the protocol that would allow transactions with flexible sequence number to be preauthorized. However, I personally feel that the whole sequence number incremented when the actual transaction failed to apply makes more sense to "fix".
Though, of course, I'm not that versed in the nitty-gritty of the protocol to know why this kind of design decision was made in the first place. Maybe it's for a good reason (protecting against spammy behaviour or some such). Though in that case claiming that the transaction are ACID is somewhat false and the actual usecases for the pre-authorized transaction hashes drops significantly.
I would like to start a discussion around how to make such contracts possible on the Stellar network. And if such usecase is even something that the core team considers worthwhile?
function prepareEscrowTransactions(escrowKeypair, escrowSequence, escrowExpires, senderSignKeypair, recipientSignKeypair) {
var escrowSequence = new BigNumber(escrowSequence);
var completeEscrowTx = new StellarSdk.TransactionBuilder(new StellarSdk.Account(escrowKeypair.publicKey(), escrowSequence.add(1).toString()), {
timebounds: {
minTime: 0,
maxTime: escrowExpires,
},
})
// Remove keys that aren't allowed to perform this transaction
.addOperation(StellarSdk.Operation.setOptions({
signer: {
ed25519PublicKey: recipientSignKeypair.publicKey(),
weight: 0,
},
}))
// Complete escrow payment
.addOperation(StellarSdk.Operation.payment({
destination: recipientKeypair.publicKey(),
asset: StellarSdk.Asset.native(),
amount: escrowAmount.toString(),
}))
.addOperation(StellarSdk.Operation.payment({
destination: providerKeypair.publicKey(),
asset: StellarSdk.Asset.native(),
amount: providerFeeAmount.toString(),
}))
// Hand over account access back to the provider
.addOperation(StellarSdk.Operation.setOptions({
masterWeight: 1,
lowThreshold: 1,
medThreshold: 1,
highThreshold: 1,
signer: {
ed25519PublicKey: senderSignKeypair.publicKey(),
weight: 0,
},
}))
.build();
var refundEscrowTx = new StellarSdk.TransactionBuilder(new StellarSdk.Account(escrowKeypair.publicKey(), escrowSequence.add(1).toString()), {
timebounds: {
minTime: 0,
maxTime: escrowExpires,
}
})
// Remove keys that aren't allowed to perform this transaction
.addOperation(StellarSdk.Operation.setOptions({
signer: {
ed25519PublicKey: senderSignKeypair.publicKey(),
weight: 0,
},
}))
// Cancel the escrow payment
.addOperation(StellarSdk.Operation.payment({
destination: senderKeypair.publicKey(),
asset: StellarSdk.Asset.native(),
amount: escrowAmount.toString(),
}))
.addOperation(StellarSdk.Operation.payment({
destination: providerKeypair.publicKey(),
asset: StellarSdk.Asset.native(),
amount: providerFeeAmount.toString(),
}))
// Hand over account access back to the provider
.addOperation(StellarSdk.Operation.setOptions({
masterWeight: 1,
lowThreshold: 1,
medThreshold: 1,
highThreshold: 1,
signer: {
ed25519PublicKey: recipientSignKeypair.publicKey(),
weight: 0,
},
}))
.build();
var completeDisputedEscrowTx = new StellarSdk.TransactionBuilder(new StellarSdk.Account(escrowKeypair.publicKey(), escrowSequence.add(2).toString()))
.addOperation(StellarSdk.Operation.payment({
destination: recipientKeypair.publicKey(),
asset: StellarSdk.Asset.native(),
amount: (escrowAmount - disputeFeeAmount).toString(),
}))
.addOperation(StellarSdk.Operation.payment({
destination: providerKeypair.publicKey(),
asset: StellarSdk.Asset.native(),
amount: (providerFeeAmount + disputeFeeAmount).toString(),
}))
// Hand over account access back to the provider
.addOperation(StellarSdk.Operation.setOptions({
masterWeight: 1,
lowThreshold: 1,
medThreshold: 1,
highThreshold: 1,
}))
.build();
var refundDisputedEscrowTx = new StellarSdk.TransactionBuilder(new StellarSdk.Account(escrowKeypair.publicKey(), escrowSequence.add(2).toString()))
.addOperation(StellarSdk.Operation.payment({
destination: senderKeypair.publicKey(),
asset: StellarSdk.Asset.native(),
amount: (escrowAmount - disputeFeeAmount).toString(),
}))
.addOperation(StellarSdk.Operation.payment({
destination: providerKeypair.publicKey(),
asset: StellarSdk.Asset.native(),
amount: (providerFeeAmount + disputeFeeAmount).toString(),
}))
// Hand over account access back to the provider
.addOperation(StellarSdk.Operation.setOptions({
masterWeight: 1,
lowThreshold: 1,
medThreshold: 1,
highThreshold: 1,
}))
.build();
var beginDisputeTx = new StellarSdk.TransactionBuilder(new StellarSdk.Account(escrowKeypair.publicKey(), escrowSequence.add(1).toString()), {
timebounds: {
minTime: 0,
maxTime: escrowExpires,
},
})
// Remove keys that aren't allowed to perform this transaction
.addOperation(StellarSdk.Operation.setOptions({
signer: {
ed25519PublicKey: senderSignKeypair.publicKey(),
weight: 0,
},
}))
// Prepare the dispute transactions
.addOperation(StellarSdk.Operation.setOptions({
signer: {
preAuthTx: completeDisputedEscrowTx.hash(),
weight: 2,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
signer: {
preAuthTx: refundDisputedEscrowTx.hash(),
weight: 2,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
masterWeight: 1,
lowThreshold: 3,
medThreshold: 3,
highThreshold: 3,
signer: {
ed25519PublicKey: recipientSignKeypair.publicKey(),
weight: 0,
},
}))
.build();
var unlockExpiredEscrowTx = new StellarSdk.TransactionBuilder(new StellarSdk.Account(escrowKeypair.publicKey(), escrowSequence.add(1).toString()), {
timebounds: {
minTime: escrowExpires,
maxTime: 0,
}
})
// Hand over account access back to the provider
.addOperation(StellarSdk.Operation.setOptions({
signer: {
ed25519PublicKey: senderSignKeypair.publicKey(),
weight: 0,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
signer: {
ed25519PublicKey: recipientSignKeypair.publicKey(),
weight: 0,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
masterWeight: 1,
lowThreshold: 1,
medThreshold: 1,
highThreshold: 1,
}))
.build();
return {
completeEscrow: completeEscrowTx,
refundEscrow: refundEscrowTx,
beginDispute: beginDisputeTx,
completeDisputedEscrow: completeDisputedEscrowTx,
refundDisputedEscrow: refundDisputedEscrowTx,
unlockExpiredEscrow: unlockExpiredEscrowTx,
}
}
var txs = prepareEscrowTransactions(escrowKeypair, escrowSequence, escrowExpires, senderSignKeypair, recipientSignKeypair);
var tx = new StellarSdk.TransactionBuilder(escrowAccount)
.addOperation(StellarSdk.Operation.setOptions({
signer: {
ed25519PublicKey: senderSignKeypair.publicKey(),
weight: 1,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
signer: {
ed25519PublicKey: recipientSignKeypair.publicKey(),
weight: 1,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
signer: {
preAuthTx: txs.completeEscrow.hash(),
weight: 2,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
signer: {
preAuthTx: txs.refundEscrow.hash(),
weight: 2,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
signer: {
preAuthTx: txs.beginDispute.hash(),
weight: 2,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
signer: {
preAuthTx: txs.unlockExpiredEscrow.hash(),
weight: 2,
},
}))
.addOperation(StellarSdk.Operation.setOptions({
masterWeight: 0,
lowThreshold: 3,
medThreshold: 3,
highThreshold: 3,
}))
.build();
tx.sign(escrowKeypair);
server.submitTransaction(tx);
SEP: Not assigned
Title: Stellar BIP32 (Hierarchical Deterministic Wallet) Support
Author: zulucrypto
Status: Draft
Created: 2017-11-03
Defines a convention for using BIP32 paths to generate Stellar accounts.
This allows users of wallets that follow BIP39 (Mnemonic code for generating deterministic keys)
to use their same wallet for managing their Stellar accounts.
This is especially relevant to hardware wallets such as the Ledger Nano and Trezor.
BIP44 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) defines
a BIP32 path for multiple coin types:
m / purpose' / coin_type' / account' / change / address_index
This specification follows BIP44 to build the initial path:
m/44'/
The coin_type
is 148'
as defined by Satoshi Labs in SLIP-0044 (https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
m/44'/148'/
This specification now diverges from BIP44 since the remaining fields are not
applicable to Stellar.
Instead, the fields are defined as follows:
m / 44' / 148' / primary_asset' / account'
This field defaults to 0'
for XLM but can be set to one of the following values
for users that wish to store assets in separate addresses.
Using a different value for this field is optional and exists to help users organize
their accounts. Storing all assets in the default account should be supported by
all applications.
BIP32 Index | Asset | Description |
---|---|---|
0' |
XLM |
Stellar Lumens |
1' |
ZuluCoin |
Example asset. TODO: assets would need some way of registering their constants here |
TODO: It might be better to generate the BIP32 index by hashing the issuing address
somehow? This would also remove the requirement for assets to register themselves
in this document.
A user-defined index for the user to create multiple accounts.
Simple Example
A brand new user would start with the following path:
m/44'/148'/0'/0'
The key at this path would determine their Stellar public address.
For most users, this would be all they need and multiple Assets could be stored
in this account.
User with multiple Assets
A user desiring to separate their assets into multiple accounts may use a path like:
m/44'/148/1'/0'
This would generate the first account for asset 1'
(see Primary Asset section).
I've been working with account data lately which is currently a straight kvp.
It would help tremendously if there was a third field as part of this record to host a "field revision id".
It would aid in syncing with outside third party apps and as part of a field encryption key.
Each time the data field was written to, this value would change. This value is part "field sequence number" and part "data hash".
By comparing this "revision id" value to a value the external systems have stored locally for the field, these external applications would be able to determine (a) if they have the most recent value for a record, or (b) if the data value needs updating from their own local values. Just comparing to see if the two values are different doesn't help in determining which of the two values is the more current value.
Also, because the value changes every update, it can be part of preventing reusing the same encryption key twice by incorporating it as part of the symmetric key value that encrypts the field data.
Thanks,
Mike
To summarize this post, I'm describing a system where we use "Accounts as Objects" to store metadata about Assets, to show a hierarchy of links between Assets, to track "service records" for real objects, and otherwise announce and distribute public information generally and encrypted information privately between parties regarding assets they have a shared interest in.
This does not require much, if any, software change, it's mostly a convention for how to use passphrases.
An Asset Holding entry in an account is typically representative of some other thing. Shares of IBM for example represent some portion of distributions from the company IBM; and an Index Fund/Mutual Fund represents holding some percentage of a "collection" of other things.
I'm proposing/have begun to use accounts to describe what's in the collection for that Asset.
For example, "The Vanguard Group" issues their "Vanguard 500 Index Fund" (NASDAQ ticker VFIAX).
Assuming I owned some of that, I'd look in my wallet and I'd see a balance, say 50 units, on a line with, most likely, its ISIN based on current practices as the asset identifier (even though ISIN isn't globally unique enough to represent the same share class from a company, nor is it technically legal to distribute through public channels (because of the SEDOL/CUSIP that are embedded within it); but that's a different discussion entirely ;) ).
But the question is what's actually in that Mutual Fund? What does that mutual fund asset actually hold?
In other words: http://www.marketwatch.com/investing/fund/VFIAX/holdings
Here's a WIP (work in progress) proposal:
Concatenate "/ + [issuer id] + "/" + [Asset identifier] + ":Asset" and hash that to get a keypair.
Use that keypair to access an account, controlled by the issuer, representing the holdings for that asset.
Each asset balance record (including XLM) has an issuer and an asset identifier. This is using only that information (plus the keyword ":Asset") to look up that "Asset Object" in the ledger database. (It's just called an "Account" at the moment.)
To look up the Asset Object for XLM (because the issuer is null) would be the passphrase "//XLM:Asset"
The passphrase for the Vanguard example above "/[somepublicaccountid]/US9229087104:Asset"
By retrieving the balances from that account I can see what that account holds. By looking at the KVP store I can see the set of issued metadata about the Asset Object.
If that account holds another mutual fund (like 401ks do); then I can recursively look that up again. A wallet can navigate my entire tree of holdings this way (and yes it needs to look out for cycles, which it can do by keeping a hash table of the asset passphrases it's processed so far).
Let's look at a derivative, like a group of mortgages; it's notoriously difficult to figure out exactly who owns your bank loan if you have a mortgage (sure your bank is collecting the checks, but they sold the loan off and are now just "servicing the account" for the actual owner(s)).
Each mortgage loan would be identified on the system by its own asset id issued by the original issuer, a collection of those assets would get bundled into another asset and sold as a group, those groups can even be bundled again and sold off as an investment fund or outright ownership transfer.
Using this scheme, the system could store metadata about, and the contents of, each asset and asset collection. Through the derived public account address, it's a well-known location every interested party can look.
Again it'd just be hashing the passphrase: "/[assetissueraddress]/[assetidentifier]:Asset"
Your wallet could dig through the derivatives and, at least to the degree public information has been populated/updated by the issuer, see what's in there (and hopefully derive better info).
I could easily see "automated services" which collect monthly/quarterly published information and files and then associate it with an asset object using the KVPs; using some appropriate key_name, and then some IPFS (or similar) address as the value. Assuming the Stellar node was also running IPFS, it could even retrieve the data if requested/required.
Lastly, let's look at real world objects; specifically manufactured ones with a Serial Number and a Product Code.
Imagine a laptop manufacturer creates a new Account to hold metadata about their new Product.
passphrase: "/" + [manufacturersaccountid] + "/Laptops/" + [ProductCode] + ":Asset"
It now has a shiny new account at address: [ManufacturersProductAccount]
Further, everytime a new laptop rolls off the production line it makes another asset account
passphrase: "/" + [ManufacturersProductAccount] + "/" + [LaptopSerialNumber] + ":Asset"
The manufacturer now controls another account: [SpecificLaptopInstanceAccount]
Inside that account are holdings of all the specific serial numbers for each part that went into making that laptop. This specific laptop instance can now be sold, bundled into a pallet account with a bunch of other laptops for shipping, and theoretically tracked from manufacturer all the way to third hand owner.
This same concept can be applied to cars and VIN numbers, books and ISBN numbers, and UPC codes.
Stellar has the framework for globally and publicly creating and tracking each "instance" of an asset or the asset as a total collection.
A manufacturer can make an "Announcement" about the product line, like a recall, a product manual or product manual update, upcoming press release, software updates, or communicate about the product line in general by attaching new KVP entries to the Product Line issuer account. The "value" of the KVP in these cases would be a pointer to where the actual data can be retrieved (limit of 64 bytes) presumably something like an IPFS address (or other suitable OOB address) .
Now let's say I bought one and registered that specific laptop in one of my Asset Accounts.
I could have some local software that periodically checked the Product Line account and SpecificLaptopAccount for any updates posted by the manufacturer and let me know.
Finally, using the "encrypted data" proposal from issue #26, when I take my laptop in to Best Buy to get serviced; they have a mechanism for creating an account with the combined "BestBuy" + "MikeFair" +"SpecificLaptopSerialNumber" accounts passphrase.
Now BestBuy and I have a "Service Record Account" where we can share information about services performed, problems encountered, replacement parts used, and in general any other useful information about our combined interest in this latop (perhaps even using the account to track an invoice request and a payment txn?). Further because the [SpecificLaptopSerialNumber] account is also part of the trio, there's potential there for directly looping in the manufacturer on the case if required (like perhaps tracking a ticket number or something similar).
Hi all,
I'd really like to formally link accounts and assets, especially into hierarchies.
Think of something like a Chart of Accounts, Parts List / Bill of Materials, Purchase Order, Paper Portfolio, or Index Fund.
This would be a new object type that links two addresses or assets in the system via a from/to.
The two link fields could done as "trust_lines" (a from line and a to line).
Setting the AssetCode to "" or null would represent an account link, otherwise an asset.
This object has "type" and "name" strings and Managed Data fields for properties of the "relationship".
Using this "Link" object is completely user defined and has no formalized in-system meaning.
The operations I see are of the standard CRUD fare; but a convenience API to also return the linked Accounts (if they are Accounts) would save from a couple trips back to the servers.
Thanks,
Mike
Adding support for natively addressing objects stored within ipfs (https://ipfs.io/) would allow, in my opinion, many novel systems that use the combined power of ipfs's "permanant web" and the Stellar network's "financial web".
Ipfs uses multihash (https://github.com/jbenet/multihash) to address objects and peers, and adding support to the stellar memo union would allow it to natively address objects stored within ipfs.
MemoType
enum would receive two new definitions: MEMO_MULTIHASH
and MEMO_MULTIRETURN
Memo
union would incorporate these new enum definitions, and the value for each new discriminant would be of type Multihash
Multihash
struct would be introduced.A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.