interledger-deprecated / five-bells-ledger

Open-source reference ledger optimized for use with the Interledger protocol
Other
27 stars 21 forks source link

Signed, timestamped receipt of fulfillment #149

Open emschwartz opened 8 years ago

emschwartz commented 8 years ago

When the ledger receives a fulfillment, the entity submitting it will want to know whether the event they were trying to trigger happened (e.g. the connector in Universal mode wants to know the source transfers were executed). There are two ways of achieving this:

@justmoon and I discussed this and agreed that the second option is the better, more general solution to the problem. If the submitter of a condition fulfillment gets a signed, timestamped receipt they can check that that the timestamp is before the expiry of whatever they wanted to trigger and be sure that the receiving system should trigger that event.

This means that the ledger must ensure that if it says that a fulfillment was received before the expiry time of a transfer that it fulfills, that transfer will be executed (even if the ledger only gets to processing the transfer / marking it as executed after the expiry time).

In the case of the connector in Universal mode submitting the fulfillments to the source transfers, the basic behavior is that the connector will check for the HTTP 200 status code and timestamp on the fulfillment it gets back from the ledger to make sure it is before the transfer's expires_at time. This gives the connector proof that the transfer will be executed.

If the connector wants an explicit acknowledgement that the specific transfer was executed, they can request the transfer resource from the ledger. To improve the performance of this, the ledger can use HTTP/2 Server Push to push the transfer resource to the connector after the transfer is processed and (potentially) before the connector requests it.

clark800 commented 8 years ago

Sounds good. I'm not sure if server push is necessary though; don't we want the ledger to be as passive as possible?

sentientwaffle commented 8 years ago

Instead of HTTP/2 push it could use the existing notification architecture.

MatthewPhinney commented 8 years ago

When the ledger receives a fulfillment, the entity submitting it will want to know whether the event they were trying to trigger happened

Isn't this already the case? When a ledger receives a fulfillment, it first validates that it fulfills a condition (execution or cancellation) on the specified transfer, then validates that the transfer is in an appropriate state for the fulfillment (you can't reject an executed transfer, or execute an expired transfer), then executes/rejects and returns a success code. If the client gets a success from the fulfillment endpoint, they should trust that the transfer has been updated.

Can you clarify why this is necessary?

emschwartz commented 8 years ago

Let's say a ledger has two transfers that depend on the same condition, but they have different expiry times. I'm the connector that needs to get paid back by the transfer that expires earlier. I submit the fulfillment to the ledger after my transfer's expiry date but before that of the other one, it executes the transfer that's not already expired, doesn't do anything with mine because it's already expired, and returns an HTTP 200. (Note that right now you submit the fulfillment to /transfers/:id/fulfillment but that should move in the future to an endpoint unrelated to a specific transfer that will trigger all events that depend on a given event)

MatthewPhinney commented 8 years ago

OK, in light of that use case, this makes perfect sense.

Is this change required for atomic mode?

emschwartz commented 8 years ago

In atomic mode there are (probably) no timeouts on the transfers, so this feature isn't as needed on the ledger. However, the notary should behave in the same manner described for the ledger here. If the recipient needs to submit the receipt to the notary or notaries before a specific expiry time, they will also want proof that they submitted it in time.

Arguably, we should think of this as a general behavior for any system using crypto conditions and fulfillments. A common behavior will be requiring that a condition is fulfilled before some time. In order for the submitter to be assured that they've met the condition in time they'll want a signed, timestamped acknowledgement of receipt.

clark800 commented 8 years ago

should move in the future to an endpoint unrelated to a specific transfer that will trigger all events that depend on a given event

Can you explain the reasoning for this?

emschwartz commented 8 years ago

Both ledgers and notaries are systems that respond to cryptographic conditions/fulfillments and enforce timeouts. @justmoon could probably explain this better than I but the general idea is that a lot more systems than just ledgers and notaries could be set up to communicate and coordinate actions between them using this primitive of the cryptographic conditions and fulfillments. This would enable atomic or semi-atomic actions to take place across widely disparate systems (e.g. a shipping company delivers physical goods, some banks execute some payments, digital titles are transferred, all based on the cryptographic "green light" given by a smart contract enforcing some multi-sig agreement between different people).

In order for this more general principle to apply we'll need to move further away from the coupling of transfers and crypto conditions. The main change to the ledger to make that happen would be to give crypto conditions deterministic IDs (@justmoon is already working on this), make a generic endpoint for posting fulfillments for any type of condition, and make the ledger look up the things that must be triggered by the incoming fulfillment and act accordingly.

clark800 commented 8 years ago

So would the request still contain some kind of reference to the list of conditions that it is supposed to fulfill? It seems important to avoid checking every condition in the ledger for each fulfillment.

emschwartz commented 8 years ago

No, but that should be easy to address with a database index

clark800 commented 8 years ago

I don't follow, how would a database index help here?

justmoon commented 8 years ago

Suppose a transfer has the condition "cc:1:Aml_0BgDRVk32fXTVMQ6V1SSKFrxAF7XHegeI16vTaexsgI". Now someone submits the fulfillment "cf:1:AoABYTEyNWNiZGFmNWI3NDk0MzQ5YjE2NGUxMmRjZTRiNDBkMTI4MTNkYTY1ZDM4YTEyOTNmZDFhOWMwMTk2YzJlZjRmYWRhNjI2OWNjYzFhNzdjMTZhYjc2NmRhMGU0NzYxYzQ4Mjc1Y2U4MzNmOGE5MzdkOWMyOWQzZDVlNmQyZTkMSGVsbG8gd29ybGQhFSBDb25kaXRpb25zIGFyZSBoZXJlIUFLExFQC5PXoLli_CBpIEE0WOypkZL7wCf_eIWExJJEmdrt00ubso94DO7gIOLUTh5sRCuij29Yos1b_yE79gwA" to the ledger.

Having a fulfillment means you can 1) verify that the fulfillment is valid and 2) generate the condition that it is fulfilling. So the ledger does 1) and if the fulfillment is valid it does 2) and gets back "cc:1:Aml_0BgDRVk32fXTVMQ6V1SSKFrxAF7XHegeI16vTaexsgI". Then it does a database query: Give me any transfers that have an execution|cancellation_condition of "cc:1:Aml_0BgDRVk32fXTVMQ6V1SSKFrxAF7XHegeI16vTaexsgI". Then it can process them all accordingly.

So all it needs for that flow is an index that maps conditions -> transfers.

clark800 commented 8 years ago

Ah, I didn't realize that you could generate the condition from the fulfillment, I think I get it now.

I still have many questions on this topic in general. I'm not sure how developed this proposal is, but it would be helpful to see a design rationale document at some point so that we could understand better the use cases and design goals.