rocklabs-io / ic-py

Python Agent Library for the DFINITY Internet Computer
MIT License
125 stars 25 forks source link

Deduplication of identical update calls #95

Closed bodily11 closed 1 year ago

bodily11 commented 1 year ago

The Internet Computer Protocol has deduplication of update calls built into the protocol. This means if you send the same update call to the same canister with the same parameters only one request will process instead of all of them (the rest being deduplicated).

In some cases this is undesirable (for example a payment flow where you request a unique escrow address for each payment and you never want to return the same escrow address more than once).

The nonce and the expiration time are part of the call, so if we vary the nonce or the expiration time on the agent side, then you can prevent deduplication of calls.

Is there an easy way to vary the nonce or expiration time of an update call through ic-py? I saw in the agent creation that there is a nonce_factory parameter, but I couldn't find any documentation on what that is or how to modify it to make it work for me.

Thanks!

bodily11 commented 1 year ago

See here in the JS agent for their nonce logic. Looks like they might prevent deduplication by default in every call with a random nonce by default?

https://github.com/dfinity/agent-js/blob/main/packages/agent/src/agent/http/index.ts#L95

bodily11 commented 1 year ago

@Myse1f Hey, just following up here. Would love to hear your thoughts. Thanks!

Myse1f commented 1 year ago

Hi @bodily11 , I think the nonce_factory is something for extension and currently there is no implementation yet. To differentiate the call, I think varying the nonce is enough.

I will take time to look into the detail and implement a mechanism to set the nonce when I am available. Thanks for the finding.

Myse1f commented 1 year ago

In some cases this is undesirable (for example a payment flow where you request a unique escrow address for each payment and you never want to return the same escrow address more than once).

But actually, I think by default, the expiration time is different in each call. Isn't that not enough to differentiate the call?

bodily11 commented 1 year ago

Expiration time is actually not enough to differentiate the calls for whatever reason. I've tested by making 20 calls within 150 msec, and all of the calls are deduplicated and only 1 request is made. So expiration time wasn't sufficient in this case.

But yes, being able to vary the nonce I think would do the trick!

Myse1f commented 1 year ago

I think currently no need to set a random or self-define nonce. The easiest way it to use different expiry time.

Previously the minimum unit of the expiry time is truncated to second, so that it can not deduplicate your calls. I update to use the nano second time stamp in this branch and it works from my side. Can you help verify whether it works?

bodily11 commented 1 year ago

Oh nice! This makes sense. I didn't know the expiry time was truncated to the second. Updating to nanosecond expiry should work. I'll give it a try.

bodily11 commented 1 year ago

Yep, this works like a charm! Thank you!