-
Notifications
You must be signed in to change notification settings - Fork 63
Connector & Engine adjustments for asset scale precision loss leftovers #199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
crates/interledger-settlement-engines/src/engines/ethereum_ledger/eth_engine.rs
Outdated
Show resolved
Hide resolved
crates/interledger-settlement-engines/src/engines/ethereum_ledger/eth_engine.rs
Outdated
Show resolved
Hide resolved
crates/interledger-settlement-engines/src/stores/redis_ethereum_ledger/store.rs
Outdated
Show resolved
Hide resolved
4927f5d
to
d227963
Compare
09c89e6
to
0b8ee3f
Compare
crates/interledger-settlement-engines/src/engines/ethereum_ledger/eth_engine.rs
Outdated
Show resolved
Hide resolved
Adding a type_length_limit check at the main.rs file does not seem to allow tests to build:
Error is pretty opaque, does not indicate where we need to adjust things |
crates/interledger-settlement-engines/src/engines/ethereum_ledger/eth_engine.rs
Outdated
Show resolved
Hide resolved
crates/interledger-settlement-engines/src/stores/redis_ethereum_ledger/store.rs
Outdated
Show resolved
Hide resolved
Implement the trait for the eth engine
05dce10
to
055d365
Compare
This allows the trait implementer to choose the data type of the leftovers instead of forcing them to use BigUint
Maybe related: rust-lang/rust#54540 (comment) Turns out boxing the futures instead of returning Either's does the trick. Not sure how I feel about it, but I cannot find another workaround. In linkmauve/tokio-socks5@a532d63, they allude how they use Boxes to avoid long compilation times because the nested futures really make the compiler tired. |
Note: https://github.com/interledgerjs/settlement-xrp is not updated yet to return data for checking leftovers
488677e
to
88dc75d
Compare
@emschwartz this should be good for review again. Curious what you think on Box'ing the futures. Seems like there's no good alternative. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I still prefer load_uncredited_settlement_amount
and save_uncredited_settlement_amount
over load/pop leftovers
crates/interledger-settlement-engines/src/engines/ethereum_ledger/eth_engine.rs
Outdated
Show resolved
Hide resolved
crates/interledger-settlement-engines/src/engines/ethereum_ledger/eth_engine.rs
Outdated
Show resolved
Hide resolved
) -> Box<dyn Future<Item = (), Error = ()> + Send> { | ||
trace!("Saving leftovers {:?} {:?}", account_id, leftovers); | ||
let mut pipe = redis::pipe(); | ||
pipe.set(format!("leftovers:{}", account_id), leftovers.to_string()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be adding to that amount rather than overwriting what's there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's correct since there may be a race condition. However, the amount being written is a BigNumber, we cannot do arithmetic with these in the store, unless we store them as numbers in redis.
What should we do if the connector replies with leftovers greater than u64? Alternatively, we should explore some way to perform atomic threadsafe operations on Redis where we pull some value, operate on it and write back to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of a janky solution but we could use a list of strings in Redis. When you want to save an amount, you would add another number to the list. When you want to get the leftovers, you would load the whole list (and empty it out -- although this creates a possibility that information would get lost if the SE crashes right then) and sum up the numbers parsed from the strings using the big integer library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the list of strings idea. When we fetch the leftovers, I also think we can mitigate any risk of the SE crashing:
- Generate a new idempotency key locally
- Run a pipeline or Lua script that:
a. Gets the uncredited list (and returns right away if it's empty)
b. Sets new key(s) with the idempotency key, its expiration, and the list of amounts it corresponds to
b. Empties the uncredited list
d. Returns the list of amounts corresponding to the idempotency key - Then, the BigNumber logic locally can sum up the list of amounts for the incoming settlement request. If it crashes and comes back online, it can safely lookup all unexpired idempotency keys, and add up their list of amounts locally to compute the total amount that should be sent in each of the incoming settlement requests.
- If that idempotency key expires/the request fails after a few retries, we can atomically append its list of amounts to the list of uncredited amounts and delete the idempotency key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The list of strings logic has been added, thanks for the suggestion @emschwartz.
Ok(()) | ||
}) | ||
}) | ||
let amount = BigUint::from(100u64); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test should use numbers that are larger than u64, just to ensure it does exactly what we expect
uncredited_settlement_amount | ||
); | ||
let mut pipe = redis::pipe(); | ||
pipe.lpush( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth including a comment recording why these amounts are stored as a list
let mut pipe = redis::pipe(); | ||
// Loads the value and resets it to 0 | ||
pipe.lrange( | ||
format!("uncredited_settlement_amount:{}", account_id), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this key be prefixed with the SE type like the other keys?
db28493
to
0d5a477
Compare
Closes #185