Skip to content
This repository has been archived by the owner on Feb 9, 2021. It is now read-only.

Change representation of Lovelace from Word64 to Natural #693

Open
wants to merge 35 commits into
base: dcoutts/lovelaceportion-simplification
Choose a base branch
from

Conversation

dcoutts
Copy link
Contributor

@dcoutts dcoutts commented Dec 23, 2019

The motivation is that by changing most of the arithmetic operations from being partial to total it simplifies Lovelace calculations in many places elsewhere in the code.

Also do a bunch of other cleaning and tidying.

This is still a draft because having changed the representation, we need to change the representation of a "compact" utxo entry to still use Word64, otherwise we'll inflate their size with the change to Natural (which cannot be unpacked since it's a two-constructor type). So that'll need another patch to adjust the compact utxo representation, and add a validation check that each tx output value is less than 2^64 so that the conversion is guaranteed (this should be a redundant check since the CBOR on-chain tx representation is already a word64).

This PR builds on #692, and should probably be re-targeted to master once that one is merged.

@dcoutts dcoutts force-pushed the dcoutts/lovelaceportion-simplification branch from 1563f93 to 9477c2a Compare December 27, 2019 11:45
@dcoutts dcoutts force-pushed the dcoutts/lovelace-as-natural branch 2 times, most recently from d0bb48f to 32cbe41 Compare December 28, 2019 22:26
The use of double in lovelacePortionToDouble is highly dubious.
We will use it instead of applyLovelacePortionDown which will help us
eliminate unnecessary uses of LovelacePortion.
Change uses of LovelacePortion to Rational.

The GenesisInitializer was using LovelacePortion for calculations for
what portion of all the money goes to the "richmen" vs everyone else.
This is unnecessary. We can simply use Rational, and use a function
for scaling a Lovelace by a Rational.

LovelacePortion is a (fixed base) representation of a rational in the
range [0..1] that we inherited for Byron compatability for the
thresholds for (mostly unused) update system protocol paramaters.

We should avoid using it for anything else.
With the intention of replacing the other constructors and conversions.
Replace with rationalToLovelacePortion
Use lovelacePortionToRational instead. It was being used in applying an
update system threshold paramater to the number of genesis keys to
determine the threshold required.

Since this was being used with the number of genesis keys, rather than
total system stake, then the use of Double was not in practice a
problem, but it's much clearer to stick to our rule that we avoid
floating point completely within the ledger and consensus rules.
Just in the pretty-printing. We can use lovelacePortionToRational and
convert for display.
Same for the LovelacePortion constructor directly.

All replaced with rationalToLovelacePortion.
Removed mkLovelacePortion, mkKnownLovelacePortion and
lovelacePortionToDouble.

Also stop exporting lovelacePortionDenominator and the LovelacePortion
consructor.

So now we only export the LovelacePortion, the conversions to/from
Rational, and of course the various instances.
@dcoutts dcoutts force-pushed the dcoutts/lovelaceportion-simplification branch from 9477c2a to 5fb1f2a Compare December 28, 2019 22:29
We will be able to eliminate a lot of the complexity involved in
manipulating Lovelace values by making most of the operations total,
where currently they are partial.

The first step is changing the internal representation, without changing
anything else. So it still does the overflow checks at this point.
Since soon it will not be bounded above.

Mainly changes in the genesis generator and tests.
The representation now cannot overflow since it uses Natural.

Stop exporting the LovelaceError constructors for the errors that are
no longer possible.

Remove the tests that check that overflows are detected.
These will be used to replace all the others, especially the partial
ones.
Legacy from cardano-sl that is no longer used anywhere.
Replace with lovelaceToNatural and naturalToLovelace.
Replace with naturalToLovelace.
We can do this now that we're using value level representations.
The add, sum, scale, div and mod operations are now pure, but not sub.

This allows a small cascade of other things to become pure.

Also remove properties for partiality of the operations that are no
longer pure, and lovelace failures that are no longer possible.
Adjust the types of a couple fields in the GenesisInitializer and
FakeAvvmOptions to make the types in the genesis generator match up
better with fewer conversions.
Including removing unsafeGetLovelace and mkLovelace (which were already
not exported but were still being used internally).

Also rename Lovelace newtype projection function from getLovelace to
unLovelace.
There is only one error for subtraction, it doesn't need a special error
enumeration.

Adjust the few users. This leaves LovelaceError unused in the Lovelace
API and only used in the reporting of tx validation errors.
And improve the error messages at the same time. LovelaceErrors are no
longer generated by the lovelace operations, after previous refactoring
steps they were being thrown locally. Replace the general use of
LovelaceError with a local error that is more specific. The error is
really that one quanity was expected to be bigger than another and it
was not.
In the next couple steps we will eliminate the type entirely. This is
just an intermediate step.

Also adjust tests.
It is now only used in one case, for when the input and output balances
of the transaction do not match (which corresponds with when doing the
lovelace subtraction operation to calculate the fee would fail).

The binary format is retained for compatability. We rename the
constructor to reflect its use. We eliminate the unused field. The
values fields are changed to Lovelace (but encoded as Word64).
The CompactTxOut type used to contain simply a Lovelace, which was fine
when it was a newtype wrapper over Word64, but when we made Lovelace a
Natural then it is no longer so small.

So we add and use a CompactLovelace type.

Why is this OK? Because the sum of the whole utxo will fit in a Word64.
For when we want just one component of the CompactTxOut without
uncompacting the other (e.g. computing the utxo balance).
@dcoutts dcoutts force-pushed the dcoutts/lovelace-as-natural branch from 32cbe41 to 4061b61 Compare December 28, 2019 22:36
@dcoutts dcoutts marked this pull request as ready for review December 28, 2019 22:36
@dcoutts dcoutts requested a review from dnadales as a code owner December 28, 2019 22:36
Copy link

@kantp kantp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!
My only question is whether we should have an overflow check at the point where we create a compact representation.

(fromCompactLovelace lovelace)

toCompactLovelace :: Lovelace -> CompactLovelace
toCompactLovelace = CompactLovelace . fromIntegral . lovelaceToNatural
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we have a check here for overflow? This is where we are converting from Natural to Word64, right?

@nc6 nc6 force-pushed the dcoutts/lovelaceportion-simplification branch from 5fb1f2a to 700181d Compare February 12, 2020 14:15
@iohk-bors iohk-bors bot closed this Feb 13, 2020
@dcoutts
Copy link
Contributor Author

dcoutts commented Feb 17, 2020

Uh, dunno why bors closed this, but it should still be open.

I cannot reopen because it's against a closed branch, but also cannot retarget it because it's closed.

@dcoutts
Copy link
Contributor Author

dcoutts commented Feb 17, 2020

Hah, ok, undeleted the target branch, now I can reopen...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants