-
Notifications
You must be signed in to change notification settings - Fork 63
Improve Asset Scale conversions #192
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
ac21692
to
bad3ff0
Compare
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/tests/eth_xrp_interoperable.rs
Outdated
Show resolved
Hide resolved
crates/interledger-settlement-engines/tests/eth_xrp_interoperable.rs
Outdated
Show resolved
Hide resolved
Test fails with:
I am unable to reproduce this locally. Relevant: hyperium/hyper#1757 |
The scale conversion will be performed on the engine. We must send our asset scale to the engine so that it knows how to handle the number we sent it.
…ine scale If we have configured the engine with asset scale 18, and the connector sends a body with scale 9 and amount 1, we should settle for 1e9
For the connector: if the number after conversion would still not fit in a u64, we use the u64::MAX
instead of constants
Previously the Convert trait implementation had an arithmetic error, which was forcing us to use provide it parameters in the opposite order.
This reverts commit 36a3732.
2645416
to
1f6f9a4
Compare
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/engines/ethereum_ledger/eth_engine.rs
Show resolved
Hide resolved
crates/interledger-settlement-engines/tests/eth_xrp_interoperable.rs
Outdated
Show resolved
Hide resolved
to: account.asset_scale(), | ||
}); | ||
// If we'd overflow, settle for the maximum u64 value | ||
let safe_amount = if let Some(amount) = amount.to_u64() { |
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 it's slightly less of a foot-gun to do this instead of using a different variable name:
let safe_amount = if let Some(amount) = amount.to_u64() { | |
let amount = if let Some(amount) = amount.to_u64() { |
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'd rather be explicit about the variable name here being safely scaled and leave it as safe_amount
. Why do you think it's a footgun?
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 using shadowing when doing these kind of transformations on numbers, just to make sure that I don't accidentally use the wrong one in something after applying the transformation (and to make sure that anyone working on that code later will avoid the same mistake).
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.
OK I agree with you.
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.
Overall, looks good. The only thing I'm not sure about is how the conversion functions handle overflows. It seems like it would be better to produce an error if the numbers overflow, though I could be convinced otherwise
- If exchange rate normalization fails return a reject packet - In all other places we use BigUint so the conversion should never fail, but we still handle the error graciously - prefer shadwing of variable name to avoid using the wrong variable - clarify comment about SettlementEngineDetails
aba4bce
to
4927f5d
Compare
…nge rate is applied
4927f5d
to
d227963
Compare
|
||
match outgoing_amount { | ||
Ok(outgoing_amount) => { | ||
// f64 which cannot fit in u64 gets cast as 0 |
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.
// f64 which cannot fit in u64 gets cast as 0 | |
// If an f64 is larger than the maximum value for a u64 but gets | |
// cast to a u64, it will end up being 0 |
match outgoing_amount { | ||
Ok(outgoing_amount) => { | ||
// f64 which cannot fit in u64 gets cast as 0 | ||
if outgoing_amount != 0.0 && outgoing_amount as u64 == 0 { |
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.
Will this check really work? 🤔
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.
Added a test which shows that it does
request.original_amount, request.from.asset_code(), request.from.asset_scale(), request.from.id(), | ||
outgoing_amount, request.to.asset_code(), request.to.asset_scale(), request.to.id()); | ||
} | ||
Err(_) => { |
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.
When would this return an error versus turning into 0? This code is kind of confusing so it would definitely be helpful to put some comments describing what's going on
* fix(settlement-client): do not convert scale The scale conversion will be performed on the engine. We must send our asset scale to the engine so that it knows how to handle the number we sent it. * feat(settlement): Implement asset scale conversion for u256 * feat(settlement): Normalize the amount properly when being notified by the engine * fix(eth-se): Scale the amount to settle for based on the body and engine scale If we have configured the engine with asset scale 18, and the connector sends a body with scale 9 and amount 1, we should settle for 1e9 * test(eth-se): adjust test for proper scale conversion * test(eth-xrp) Set ETHXRP exchange rate * fix(crate): Remove settlement_engine_asset_scale from account * improvement(settlement/engines): use BigUInt to handle big numbers * fix(settlement): Convert asset scale properly Previously the Convert trait implementation had an arithmetic error, which was forcing us to use provide it parameters in the opposite order. * feat(settlement/engine): Return None when idempotent data not found instead of Error * fix(settlement): Make asset scale conversions overflow-safe - If exchange rate normalization fails return a reject packet - In all other places we use BigUint so the conversion should never fail, but we still handle the error graciously - prefer shadwing of variable name to avoid using the wrong variable - clarify comment about SettlementEngineDetails * improvement(exchange-rate): make the scale conversion after the exchange rate is applied * test(exchange-rate): Add tests which verify that rate conversions fail correctly
settlement_engine_asset_scale
since it is being passed in by the engine per requestExample:
Connector is making transactions for an account with
account_scale
9 andETH
, so it denominates funds in Gwei.When the connector wants to settle, it sends the
amount
and9
to the engine.The engine is configured to use
asset_scale = 18
. The engine will proceed to make an on-chain transaction foramount * 1e9
.The receiver's engine will pick that up, and send
(1e9, 18)
to the receiver's connector. The receiver's connector will then downscale1e9
from 18 to whateverasset_scale
it uses for that account.