namecoin / namecoin-core

Namecoin full node + wallet based on the current Bitcoin Core codebase.
https://www.namecoin.org/
MIT License
460 stars 147 forks source link

Add "expires_time" and "expires_mediantime" fields to name_show response #378

Open JeremyRand opened 4 years ago

JeremyRand commented 4 years ago

Is your feature request related to a problem? Please describe.

The Namecoin-Qt Manage Names tab currently shows name expiration projections in terms of the expires_in field, which indicates the number of blocks remaining until expiration. This is not very user-friendly. I'd like to make it instead show an estimate of the date+time of expiration (which is what Electrum-NMC's GUI already does).

Describe the solution you'd like

I'd like the name_show command's response to add two fields: expires_time and expires_mediantime. If the name is expired, these are equal to the corresponding fields of getblock for the block in which the name expired. If the name is not expired, they should be equal to the corresponding getblock fields for the chain tip, plus 10 minutes for every block remaining until expiration. We can then use GUIUtil::dateTimeStr to format the result for display in Namecoin-Qt.

My preference is to use the median time for GUI display, since it's more stable, and there's no harm in showing slightly earlier expiration dates than will actually happen. But some users of the RPC API may benefit from the non-median time.

Describe alternatives you've considered

We could keep this logic in the Qt part of the codebase, but this makes it less pleasant to run integration tests on. We could implement dateTimeStr as part of the RPC API, but that doesn't match upstream best practices, and upstream has a trivially easy way to do it from Qt.

Additional context

N/A.

JeremyRand commented 4 years ago

@domob1812 Does this proposal sound reasonable? @yanmaani Is this something you might be up for implementing?

domob1812 commented 4 years ago

Yes, that sounds definitely fine to me.

yanmaani commented 3 years ago

I'm not so bullish on this. It feels odd to put this logic in name_show, and the point estimate for expiration is unlikely to be that useful. I'd rather have a RPC that takes a block height and optionally a percentile (default 0.50), and estimates what time it will happen on, as such:

You would have to add in some mathematical routines, unless they're already in Boost, but these routines would be purely mathematical, trivial to isolate and test, and are already written as C implementations.

Then, you could also use that RPC call to estimate when a transaction would reach N confirmations, which would be useful for Bitcoin Core. If we are very lucky, we might be able to upstream it.

JeremyRand commented 3 years ago

@yanmaani Trying to use any kind of statistical model seems like over-engineering. Are there any real-world use cases where users really want to know what the nth percentile date will be for a name reaching X confirmations? The name management GUI's use case is to simplify the result for end users, by giving them a rough estimate of the expiration date, especially for users who don't know that 1 block averages 10 minutes. Doing anything more complicated will actively go against the simplification goal.

I also don't see any reason why upstream would want this functionality. In Bitcoinland, if you want a human-meaningful locktime, you just use a human-meaningful locktime, which is supported everywhere. The only reason we care about this problem in Namecoin is that name expiration uses a fixed locktime, which is non-human-meaningful simply because human-meaningful locktimes weren't really a thing when Vince created the rules. Whenever we do our next hardfork, we will probably switch to using human-meaningful locktimes for name expiration (e.g. "stops resolving after 13 months, becomes available for registration after 14 months"), so this is purely a stopgap that doesn't really need any kind of precise engineering or upstreaming effort -- the simpler the better, because I'd like to rip this code back out after we do that hardfork.

yanmaani commented 3 years ago

@yanmaani Trying to use any kind of statistical model seems like over-engineering. Are there any real-world use cases where users really want to know what the nth percentile date will be for a name reaching X confirmations?

I would very much like to have a good estimate for the range of dates when a name will expire. I am implementing this in my name explorer currently.

The name management GUI's use case is to simplify the result for end users, by giving them a rough estimate of the expiration date, especially for users who don't know that 1 block averages 10 minutes. Doing anything more complicated will actively go against the simplification goal.

You could display the 95% CI, or just round it based on how good data you have: 1970-01-01 00:00:00 <- precision at least 30s 1970-01-01 00:00 <- precision at least 30m 1970-01-01 <- precision at least 15d 1970-01 <- precision at least 0.5y 1970

I also don't see any reason why upstream would want this functionality. In Bitcoinland, if you want a human-meaningful locktime, you just use a human-meaningful locktime, which is supported everywhere.

Off the top of my head: to see when a given transaction will have N confirmations, and to see when the block reward will halve.

The only reason we care about this problem in Namecoin is that name expiration uses a fixed locktime, which is non-human-meaningful simply because human-meaningful locktimes weren't really a thing when Vince created the rules. Whenever we do our next hardfork, we will probably switch to using human-meaningful locktimes for name expiration (e.g. "stops resolving after 13 months, becomes available for registration after 14 months"), so this is purely a stopgap that doesn't really need any kind of precise engineering or upstreaming effort -- the simpler the better, because I'd like to rip this code back out after we do that hardfork.

That seems like a bad idea. Checking name expiration in bulk is trivial right now (check the names registered in the last 36k blocks), that change would add lots of new logic everywhere. It would also mean SPV clients would need to keep a variable amount of history. The gain seems dubious, and not really worth it.

I do not think you should rely on the 'fact' that this will be done in the next hardfork when making decisions. There are no guarantees it will come to fruition, after all, and there's nothing more permanent than a temporary solution.

domob1812 commented 3 years ago

I agree with @yanmaani that having name expiration by timestamp (rather than block) probably means that the benefit we get for users doesn't really outweight the extra complexity. I don't think it matters too much for users when exactly their name expires. They can (and should) just renew a week before that and be fine.

That said, if we really think human-meaningful expiration times are a thing, I think it would not be that hard to implement them. Namecoin Core already has a special index which maps expiration heights to names, so it can efficiently expire names when connecting blocks. If we would base that index off median time, then we could still quite easily search for names expiring in a window of time and expire names that are past the current block's median time. (As well as make an RPC that returns all names expiring in the next X seconds.)

yanmaani commented 3 years ago

I could tolerate a softfork that prohibited other than the owner from registering a name within 8.3 months of registration, or however long the average time is. But this? A lot of work for little gain.

(It would also open the door to truly catastrophic attacks where you mine 6 blocks with mediantime far in the future, steal all the names, and then hope the miners don't validate timestamps)

If this calculation is correct, and I'm not sure it is, the 95% confidence interval is 8.06 months ± 2.2 days. So I am not sure it is needed.

https://www.wolframalpha.com/input/?i=erlang+distribution+k%3D36000+%CE%BB%3D1%2F600

JeremyRand commented 3 years ago

You could display the 95% CI, or just round it based on how good data you have: 1970-01-01 00:00:00 <- precision at least 30s 1970-01-01 00:00 <- precision at least 30m 1970-01-01 <- precision at least 15d 1970-01 <- precision at least 0.5y 1970

Whatever rounding we use in Namecoin-Qt is going to be the same as what upstream uses for displaying timestamps (because that code will be reused).

to see when a given transaction will have N confirmations

...why do Bitcoin users need to care about this?

to see when the block reward will halve.

I suppose there may exist people who want an estimate of this, but it seems like a sufficiently rare use case that I doubt upstream will want an RPC method for it.

It would also mean SPV clients would need to keep a variable amount of history.

As the author of ConsensusJ-Namecoin, I can attest that fetching blocks based on timestamp was actually less code than fetching them based on block height. I have no idea whether there's any meaningful difference between the two in the Electrum codebase, nor which direction that difference might be.

(It would also open the door to truly catastrophic attacks where you mine 6 blocks with mediantime far in the future, steal all the names, and then hope the miners don't validate timestamps)

I would ask you to please keep endorsements of the BCH pseudoscience threat model out of our issue tracker... but that's not even BCH's threat model (assuming that everyone runs SPV and only miners run full nodes), because timestamps don't even need a full node to validate; SPV nodes will reject that kind of stupidity. (Also if you think human-meaningful locktimes are dangerous, please go make your case to the Bitcoin devs, since they already support them.)

Anyway, firing the on-topic cannon -- if you think there's a reason to get some of the code for this issue upstreamed, make your case for that, but don't hijack the thread into an in-depth discussion of future hardforks. Whether Namecoin hardforks has exactly zero bearing on whether upstream will want something.

yanmaani commented 3 years ago

to see when a given transaction will have N confirmations

...why do Bitcoin users need to care about this?

To see when a transaction will have 6 confirmations and show up in the GUI with that indication, for example. I concede it's a niche use case.

discussion of future hardforks.

Yes, this should be a separate issue. Anyway, my point is that you can't assume that Namecoin will use human-readable lock times in the future and use this to guide development decisions. Personally, I think it seems as if this is in fact not going to be the case, but I digress.

Whether Namecoin hardforks has exactly zero bearing on whether upstream will want something.

Whether Namecoin hardforks is, as you have said, important, because if it's all but assured, then that feature really should be half-assed.

I think it's also unclean to clutter up the name_show response with various auxilliary and non-deterministic information for the benefit of the RPC, and would rather see this as a separate RPC call. You shouldn't have name_show be a RPC call which tells you everything there might be to know about the name, it should be split up.

Even if you're not going to have it in upstream, it seems like a good idea to have things in such a condition that they could theoretically be moved to upstream if the need arose.

yanmaani commented 2 years ago

Okay, probably the Erlang distribution thing is overkill, but I still think that this should be a separate RPC. Ideally one that just gives you a point estimate for when we'll see a certain block, which is like five lines. But also see #365 and discussion in #385.

domob1812 commented 2 years ago

Nothing specifically against that, although of course if the RPC is just "five lines", then I wonder if we need it at all (rather than just have the client software do it). The main benefit I see would be abstracting away the knowledge about the expiration period, particularly if we are going to change it with a fork in the future. (But then the RPC interface must be designed so that it will work well with forks.)

yanmaani commented 2 years ago

No, the RPC really would be that short. I think name_show already provides the registration height, so all you'd have to do is calculate NameExpirationDepth(height).

I just think that this way is preferable to bloating up name_show.

JeremyRand commented 1 year ago

Given that @domob1812 already ACKed this, I'm inclined to begin implementation. I think it's pretty clear that name_show consumers (e.g. the Namecoin-Qt GUI) are likely to want this field (at least as much as they want the expires_in field). If we want to expose this estimation logic in some other lower-level RPC method too, maybe start another issue for that and we can refactor later.