interledgerjs / ilp-protocol-stream Goto Github PK
View Code? Open in Web Editor NEWMoved to monorepo in interledgerjs/interledgerjs
Home Page: https://github.com/interledger/rfcs/blob/master/0029-stream/0029-stream.md
Moved to monorepo in interledgerjs/interledgerjs
Home Page: https://github.com/interledger/rfcs/blob/master/0029-stream/0029-stream.md
1.0.2
to 1.1.0
.π¨ View failing branch.
This version is covered by your current version range and after updating it in your project the build failed.
ilp-logger is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.
The new version differs by 5 commits.
5253753
1.1.0
c2d9bb0
feat: upgrade to TypeScript (#8)
65d0941
Merge pull request #5 from interledgerjs/greenkeeper/initial
fdd0711
chore: add greenkeeper-lockfile to CI
d27e32f
docs(readme): add Greenkeeper badge
See the full diff
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
If there are connection problems and temporary errors, the exponential backoff continues doubling (here:
ilp-protocol-stream/src/connection.ts
Line 1191 in c736e92
TimeoutOverflowWarning: 1.915619426082361e+55 does not fit into a 32-bit signed integer.
Timeout duration was set to 1.
And this continues until the 64-bit double is overflowed and the connection logic likely stops.
In this situation we should either throw an error or simply cap the timeout length
Curious if this would provide any performance benefits: https://github.com/AssemblyScript/assemblyscript
Like QUIC, STREAM is going to have connection- and stream-level flow control (so both sides will be able to control both the amount of data they're getting for each stream and for the connection as a whole).
The proper behavior for determining the packet amount is to have stream figure out how much money it can have in flight at a given time. This is a little complicated to implement so for the time being we should just make the default behavior for temporary errors be to reduce the packet amount (especially on T04 errors).
Related to interledgerjs/ilp-plugin-xrp-asym-server#39
If the user sets the sendMax
amount before knowing the exchange rate, should the packets sent to determine the exchange rate carry money (and be fulfillable)? This would potentially reduce the latency for the first bit of money to get through, because it wouldn't be waiting for multiple round-trips with test packets before sending real money.
On the one hand, this opens things up for connectors to take a larger share of that money, because the sender will set a minimum destination amount of 0. On the other hand, though, connectors that want to do that could just take the same amount of the test packet to influence the minimum exchange rate the sender will set, so it might not make much of a difference.
If a user doesn't want to send money with a minimum acceptable amount of 0, they could just wait until the exchange rate is known before setting the sendMax
.
So that's it uses proper OER
When I split example.js into server and client I get the error:
Error: Error connecting: Unable to establish connection, no packets meeting the minimum exchange precision of 3 digits made it through the path.
I run the server the server and wait for connections and from a different client.js file I put the part to connect and stream. The error is generated here:
const clientConn = await IlpStream.createConnection({
plugin: clientPlugin,
destinationAccount,
sharedSecret
})
Right now the test section titled "Exchange Rate Handling" is empty and it would be good to add some tests to make sure it is behaving properly.
The minimum acceptable rate is determined when the stream connects by using a test (unfulfillable) packet (see here). When each subsequent packet is sent, the sender indicates the minimum amount the receiver should accept (which they check here) in the STREAM packet.
A couple of things that would be worth testing:
There are a lot of different versions of bignumber.js
and oer-utils
floating around our modules. It would be good to clean those up and get them all using the same versions so we don't need to install all of them.
ilp-protocol-stream git:es-docs β― npm ls --production
[email protected] .../ilp-protocol-stream
βββ @types/[email protected]
βββ [email protected]
βββ¬ [email protected]
β βββ [email protected]
βββ¬ [email protected]
β βββ [email protected]
β βββ [email protected]
β βββ [email protected]
β βββ [email protected]
βββ¬ [email protected]
β βββ¬ [email protected]
β βββ [email protected]
β βββ¬ [email protected]
β β βββ [email protected] deduped
β β βββ [email protected]
β β βββ [email protected]
β β βββ [email protected]
β β βββ [email protected]
β βββ [email protected] deduped
β βββ [email protected]
β βββ¬ [email protected]
β βββ [email protected]
β βββ [email protected]
β βββ [email protected]
βββ¬ [email protected]
β βββ [email protected] deduped
β βββ [email protected]
βββ¬ [email protected]
β βββ [email protected] deduped
βββ¬ [email protected]
βββ [email protected]
5.0.5
to 5.0.6
.π¨ View failing branch.
This version is covered by your current version range and after updating it in your project the build failed.
@types/sinon is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
The client and server should either try reconnecting or close if the underlying plugin disconnects
As @dappelt pointed out in interledger/rfcs#417 (comment), AES-GCM can only be used to encrypt 2^32 messages with a single key. Connections should automatically be dropped when either side has sent ~2^31 messages, or ideally some time before that.
On the connection and the stream we should match how node works with write() and only throw errors if there is not an error
emitter present. Right now we throw errors regardless of the emitter being present and we do not emit errors if one is present.
if(this._events.error){
this.safeEmit('error', streamClosedError)
}
Could be used to check if the error listener is present.
I was testing a pull payment script that had:
await stream.receiveTotal(amount)
//exit
This resulted in receiveTotal
resolving but the outgoing_money
event never happening on the sender's side. According to the logs, the fulfillment (nor a rejection) was never sent by the receiver.
I think this is due to the fact that the money
event is emitted (inside _addToIncoming
) before doing the fulfillment, leaving a window of opportunity to fail to fulfill the payment despite having indicated that the amount was received.
https://github.com/interledgerjs/ilp-protocol-stream/blob/master/src/connection.ts#L556-L595
As of right now we are sending out packet amounts of 1, 1000, 1000000, and 1000000000 in an attempt to determine an exchange rate with an amount of precision as quickly as possible.
At the high level it seems that if we send the following amounts that we have a precision to at least 3 digits and a determined exchange rate:
Amount Sent | Prepare Amount | Exchange Rate |
---|---|---|
1000 | 1000 | 1 |
10000 | 1100 | .11 |
However this does not take into account what is actually happening at the connector level. There could be multiple connectors which are changing the rate but since we only know the amount sent and the prepare amount that comes back we cannot see that they have a very different exchange rate so the 1 and .1 are not valid.
Suppose we have the connectors, where their exchange rate is represented in the ():
Conn A <---> (.001) Conn B <---> (1.6) Conn C <---> (1000) Conn D
1000 ----------------> 1 --------------> 1 ---------------> 1000 == 1
In reality the exchange should have been 1000 * .001 * 1.6 * 1000 = 1600
with a rate of 1.6 but on this path the rate calculated was 1. A similar issue could occur with larger amounts as well.
Conn A <---> (.001) Conn B <---> (1.14) Conn C <---> (1000) Conn D
10000 ----------------> 10 --------------> 11 -------------> 1100 == .11
This should have been 10000 * .001 * 1.14 * 1000 = 11400
with a rate of 1.14 but was calculated as 1.11.
The issue is that connector C is using a 1.6/1.14 exchange rate but connector B is using a very large exchange rate which effectively takes the value down to 1 and connector D is ramping that back up.
How can stream determine without having knowledge about the Conn C exchange rate that in these scenarios the calculated exchange rate is incorrect and needs further clarification?
How does this relate to https://github.com/emschwartz/ilp-protocol-paystream and https://github.com/interledgerjs/ilp-protocol-psk2?
All the debug statements in the stream library use string interpolation with backticks. This means that the objects are serialized for logging before they're passed to debug, and may not be printed if debug is turned off. We should make sure that these unnecessary string operations don't happen unless debug is actually enabled.
Currently, this module waits for the response to each Prepare packet before sending the next one. If the path can support sending multiple packets at the same time, the module should fire off as many as possible so that the money and data is sent as quickly as possible.
To do this, STREAM would need to keep track of:
If ilp-protocol-stream could keep connection state in a data store like redis, we could run sharded STREAM servers. This would make it operationally simpler to scale STREAM servers, allowing us to do away with stateful sets and the two-layered architecture for scaling STREAM servers (a statefulset of connectors + STREAM servers behind a deployment of connectors).
7.1.1
to 7.1.2
.π¨ View failing branch.
This version is covered by your current version range and after updating it in your project the build failed.
@types/chai-as-promised is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
If you call end
on a Node TCP socket, it will:
'finish'
when it has finished sending all of the data'end'
when the other side has indicated it is finished sending data'close'
when the underlying socket is closedIf the other side isn't reading data from the socket and the reading side's buffer is full, the sending side will stay open until the consumer is finished. (See this gist if you want to play around with different possibilities)
The question is what the behavior should be for a DataAndMoneyStream
if you call end
or destroy
when it's still trying to send money? Should it close the stream immediately, wait until the money is sent, or close the stream only if the other side is currently blocking it from sending more money?
Right now STREAM sends a test packet of 1000 source units to determine the exchange rate. If the amount that arrives is 0, the sender will assume that the path exchange rate is 0 and won't try to send anything through it. We should probably support paths in which the sender and receiver have very different scales.
I think the way to handle this would be:
F08: Amount Too Large
error before any money gets to the receiver, then the sender can conclude that no money will be able to be sent through the pathWe should have a configurable timeout on both of those functions and a default of something like 60 seconds so that the promise doesn't hang forever
3.0.1
to 3.1.0
.π¨ View failing branch.
This version is covered by your current version range and after updating it in your project the build failed.
oer-utils is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.
The new version differs by 5 commits.
4a0fd30
3.1.0
e0813c4
fix: reject variable integers of length zero
3cdb8ab
chore: re-enable code coverage reporting
c072342
chore: update dependencies
f3dc629
feat: allow using JS numbers instead of BigNumbers
See the full diff
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
10.11.0
to 10.11.1
.π¨ View failing branch.
This version is covered by your current version range and after updating it in your project the build failed.
@types/node is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
let receipt: Receipt
try {
const receiptBytes = Buffer.from(body.toString(), 'base64')
receipt = decodeReceipt(receiptBytes)
verifyReceipt(receiptBytes, generateReceiptSecret(this.config.receiptSeed, receipt.nonce))
} catch (error) {
ctx.throw(400, error.message)
}
verifyReceipt takes a secret to verify the hmac, but in practice that secret is generated from the receipt nonce
as can be seen above, that can lead to inefficient double decodes
could the verifyReceipt function optionally take a function with the decoded receipt as an argument and return the secret to be used ?
Sending money from the server doesn't work well right now. The connection
event is emitted before connection.handlePrepare
is called, so the connection hasn't processed the request frames (that include the other party's ILP address) yet. As a result, if you call setSendMax
synchronously, it will stop because it doesn't know the destination address.
I think we could address the sending money issue by making sure to restart the send loop once the connect
event is emitted. However, it's still strange that the connection.destinationAccount
is undefined
on the server side, so it feels like we should solve this in a better way.
I'm not sure about the best way to do this right now so open to suggestions.
A question was raised by an implementer
Is there any way native to the Stream protocol or ILP to allow us to individually identify a micropayment?
This can be achieved by raising a unique id within each money
event. @justmoon pointed out this id could be the SHA256 hash of the ILP packet. It will be a breaking change on the money event though as currently the value returned is an amount value as a string. The newer structure would be along the lines of
{
"id": "a6f7b874ea69329372ad75353314d7bcacd8c0be365023dab195bcac015d6009",
"amount": "123"
}
Another question is should we amend the spec to mandate this type of functionality for STREAM implementations?
CC @adrianhopebailie @sharafian @sentientwaffle @wilsonianb @justmoon @kincaidoneil
STREAM should work even if only one side is capable of sending money. Right now the connection will error out, however, if it is unable to send the first test packet. We should make it work under these conditions by going into some kind of "receive-only" mode.
The spec should be updated to reflect the latest protocol
To figure out if the other side got a data frame, we can either:
Note that QUIC uses ACK frames to acknowledge receipt of whole packets rather than specific frames or blocks of data.
In some use cases on top of STREAM, bidirectional communication isn't necessary. In Web Monetization, for instance, the sender repeatedly sends money to the receiver but does not expect data or money in return.
If we were able to turn on a feature in the STREAM client that stops the sender from sending their ILP address to the other side and also enable a feature that would allow the server to function in a half-open mode like this, we could simplify the infrastructure required for WM sending.
Instead of using a bidirectional communication like BTP, we could use HTTP/HTTP2, simplifying WM sending infrastructure and the WM sending code.
CC @kincaidoneil @wilsonianb @sentientwaffle if one of you is interested in looking into this, feel free to assign yourself on this issue.
@kincaidoneil I noticed you worked on the code for receive-only mode on the server, are there any considerations with this feature that I missed?
Proposal: Allow logic enforcing minimum exchange rates to be completely disabled, including:
To determine the initial packet size to send, STREAM could send a single very large packet (e.g., maybe the maximum uint64 an ILP packet allows the total amount remaining to send). F08s (which connectors should be configured to trigger before T04s) should quickly reduce it to a reasonable amount. (Alternatively, STREAM could be more aware of settlement/how much credit exists with the upstream peer, but I'm guessing that'd be more contentious).
βοΈ Important announcement: Greenkeeper will be saying goodbye π and passing the torch to Snyk on June 3rd, 2020! Find out how to migrate to Snyk and more at greenkeeper.io
4.41.10
to 4.41.11
.π¨ View failing branch.
This version is covered by your current version range and after updating it in your project the build failed.
@types/webpack is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
Ideas for obscuring which transport protocol is being used:
It's an interesting question whether any of this is worth doing, because connectors can probably figure out which transport protocols (or even which implementations of transport protocols) are being used just by looking at the timing of packets and behavior in response to certain kinds of errors.
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.