-
Notifications
You must be signed in to change notification settings - Fork 155
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
cardano-ledger-core's decodeAddr
/ deserialiseAddr
fail to deserialize mainnet pointer address
#3898
Comments
This change was intentional. Deserializer for Ptrs was buggy and it had to be fixed. There were a total of 10 addresses on mainnet that contained Ptrs, only a few of them where legitimately valid pointers. @KtorZ I suspected some of those addresses were yours 😉 This particular address contains this bogus pointer (note the transaction index is invalid and SlotNo is too big):
Starting with Conway, transaction index ( Moreover, starting with Conway, Ptr address will no longer work at all for their intended purpose of delegation. We'll still allow them to be part of the address for backwards compatibility with plutus scripts, except they will have no meaning in ledger. This feature of pointer addresses was a total disaster that caused more problems than it solved, so I am really glad that it is going away. |
I am gonna close this as won't fix. Let me know if you still feel like this is a mistake and you have some strong argument for bringing this buggy behavior back. Considering that pointers are being deprecated I can't see any argument in favor of allowing nonsense like this on-chain. |
I am fully onboard with the idea of how pointer addresses were a bad (or at least prematurely pushed) idea, and yes, one of these addresses is mine (not this one though, mine is properly constructed That's not the point of debate though. Here, the API of the ledger is no longer able to parse data that exists on chain (and will forever exist). Which means that it is no longer possible to do a proper chain sync across the old eras. Pointers being dropped in Conway is no justification to drop support for them in previous era! If I may, this was the point of having a hard fork combinator to begin with. How do we expect client applications to synchronize through the old chain? Even invalid pointers are data present in blocks and should be deserialisable. |
No worries. It all works. This change has been in ledger since last year. Syncing works and ledger is still able to decode that address. Decoder only disables addresses like these to be used in new TxOuts starting from Babbage. |
Then why does the ledger fail to parse this particular address? I would expect |
Given that addresses are era independent here (only depends on crypto), how is the ledger then selecting the correct decoder for old eras? And how are client applications and consumers of the ledger library supposed to deal with that? |
If you would like a to have access to a more lenient version of
Addresses only make sense in ledger as part of transaction, which is era dependent. Binary representation of every single thing that goes on chain is era dependent.
I have no idea how client applications and consumers use ledger code, so we cannot accommodate everyone. That being said, there are two ways we can solve this particular problem:
I am leaning to the former solution, since that would be less work for us. On the other hand, I would like for ledger codebase to be more user friendly, so I would not be opposed to exporting those helper functions from |
If the function isn't meant to be used then drop it 😄! People/client consumers shouldn't need to have intrinsic knowledge of such subtleties, especially if there's another way to achieve the same operation but in a correct way. If it's available through the module API without warnings, I think it's reasonable to assume the function works in the most obvious way. |
Note: you might want to notify maintainers of Honestly, when a function from a module API that has been working fine for years suddenly stop working after a change, I don't think the change can be called "a fix". When an undesired behavior is used and permanently stored in an immutable record, it becomes -- unfortunately -- a feature. Also, it is confusing that the expected function to be used is called |
decodeAddr
fail to deserialize mainnet pointer address decodeAddr
/ deserialiseAddr
fail to deserialize mainnet pointer address
Fair enough. We'll get it fixed. |
This is necessary to support clients that would like to deal with historical data that is already on-chain. Related to #3898
I encourage you to checkout this PR with a fix: #3903 This being the most relevant commit for this issue: 31d15f1
I've deprecated
I do agree that we should not have changed semantics of that function silently. Note, that it is not the first time that function changed behavior, prior to Alonzo it had another bug where it did not fail when input was not fully consumed. You must realize that Ledger's most important client is
There is nothing confusing about it,
That is not what happens there. This is a valid property for all valid addresses:
Most obvious way for you is not necessarily most obvious way for another user. You are looking at it from the perspective of a use case that is relevant for your application, which is totally understandable. But look at at this function through the lens of someone who implements functionality for building or signing a transaction. In such scenario you do want the decoder to fail on an invalid addresses, because transaction with such an address will not be decoded by the node. Because of different usage scenarios I prefer to go the safe route and not assume that anything is obvious. I've added two functions that can do lenient decoding of all types of addresses and support both bugs that we've discovered and fixed with bunch of documentation. Feel free to choose the one that works for you 😉 |
🙏
I do realize that, and I agree. Which is why I am insisting so much. These addresses ARE on chain already. So they are by definition valid. Or at least, have been valid at some point in time. It is more than reasonable to expect that the only function given by the ledger to decode an address would be able to decode any kind of address that the ledger (or any application consuming the blockchain) may encounter.
Common 🙃 ... Addresses are encoded as raw bytes in CBOR. For example, the address I shared earlier is encoded as:
Thus,
So what is confusing with
No, I am looking at it from the perspective of ANY consumer of the cardano-ledger as a library. As stated earlier:
|
@KtorZ, it is not possible to export "the only" function like that, because it would not be correct for all use cases. We can export a function like that and that is what The key part in your statement is "or any application consuming the blockchain". Which is not every user of
Wrong! Validity definition of an address very much depends on the context the address being used in. Addresses are only considered valid for the era they are being placed on chain! For example, would you still expect addresses that contain JPEG images be included on chain? Whenever you are trying to read from the chain or query the ledger state that is a totally different context! So, please do not mix up the two!
But we are not using
Confusing as it may, that is the correct CBOR decoding. That is the function used for
|
I give up 🤷 ... Do as you please. I'll adapt. |
That's unfortunate. I was trying to reach some consensus here. |
This is necessary to support clients that would like to deal with historical data that is already on-chain. Related to #3898
This is necessary to support clients that would like to deal with historical data that is already on-chain. Related to #3898
Important
That there's no changes on the impacted module in 1.9.0.0, so while I haven't tried with 1.9.0.0 I hardly believe it fixes the problem.
It seems that since the internals of the Cardano.Ledger.Address module was reworked to utilize state transformers, something broke regarding the parsing of pointer addresses.
More specifically, trying to decode (the bech32-decoded representation of):
addr1gy5p8wv6sr8mgqjrwj7s75pft9y94ftwqey9vnlcqhew2xaumxqe2cdam3npgv60hqa
(or412813b99a80cfb4024374bd0f502959485aa56e0648564ff805f2e51bbcd9819561bddc6614
in base16) usingdecodeAddr
yields an error.https://github.com/input-output-hk/cardano-ledger/blob/45c67892540d52aa6af9972c58bb20a125ceea09/libs/cardano-ledger-core/src/Cardano/Ledger/Address.hs#L142-L143
https://github.com/input-output-hk/cardano-ledger/blob/45c67892540d52aa6af9972c58bb20a125ceea09/libs/cardano-ledger-core/src/Cardano/Ledger/Address.hs#L565-L571
However, that address is an actual mainnet address found in one of the blocks of the Mary era. It can also be properly decoded using old code as well as alternative implementations like the one from cardano-address for de-serializing pointers.
From a quick read through the ledger's code, it seems that the problem could come from how the new decoders assume a certain length for the pointers in
decodeVariableLengthWord16
anddecodeVariableLengthWord32
. This leads to always decoding the same number of bytes whereas the encoding is meant to work with variable-length naturals and thus, may end up shorter than expected here.https://github.com/input-output-hk/cardano-ledger/blob/45c67892540d52aa6af9972c58bb20a125ceea09/libs/cardano-ledger-core/src/Cardano/Ledger/Address.hs#L815
The text was updated successfully, but these errors were encountered: