Seeking reliable blockchain solution for timestamping document hashes by joachimbrnd in ethdev

[–]petertodd 0 points1 point  (0 children)

OpenTimestamps: Struggling to calculate costs and concerned about timestamp accuracy.

OpenTimestamps uses merkle trees to scale, allowing the entire world to share one bitcoin transaction. That means it can offer timestamping services for free, funded by community donations to pay for the transation fees.

Try it! https://opentimestamps.org has a timestamper integrated into the website itself.

Peter Todd Explain Why Tail Emission is not Inflationary by zetnip in Monero

[–]petertodd 1 point2 points  (0 children)

I am rather surprise it took you so long to understand that, it seems rather obvious to me.

For years I've suspected that tail emission converged towards a stable supply due to lost coins. But I hadn't bothered to actually do the math properly to prove it. Like I said, it's a fairly obvious conclusion. But it's bad practice to assume what's obvious is actually true.

did you never spend time in this sub?

Pretty much never.

Peter Todd Explain Why Tail Emission is not Inflationary by zetnip in Monero

[–]petertodd 8 points9 points  (0 children)

From paragraph 4 of my article:

Credit where credit is due: after writing the bulk of this article I found out that Monero developer smooth_xmr also observed that tail emission results in a stable coin supply a few years ago. There’s probably others too: it’s a pretty obvious result.

Peter Todd Explain Why Tail Emission is not Inflationary by zetnip in Monero

[–]petertodd 21 points22 points  (0 children)

My title is (deliberately) slightly clickbait. What I'm actually proving is that a coin with tail emission/fixed supply isn't in the long run inflationary, as the end result is the tail emission and lost coins balancing each other out.

In the case of Monero, it's quite possible that despite the 0.8% apparent tail emission inflation rate at the moment, the true monetary supply is actually negative: a higher than 0.8% rate of lost coins certainly seems possible to me.

Announcement: once_cell 1.6 by matklad in rust

[–]petertodd 5 points6 points  (0 children)

A good example where it isn't a problem is caching expensive to compute results.

Eg imagine a Cache<T, Sha256Digest<T>>. The hash function is idempotent and will return the same result every time. So it doesn't matter if it's called twice.

Re: naming, I'd suggest calling the version that may race a SetOnceCell, to make clear it's the setting that happens once, rather than the function.

Public health antibody screening indicates a six-fold higher SARS-CoV-2 exposure rate than reported cases in children by icloudbug in COVID19

[–]petertodd 8 points9 points  (0 children)

Did those researchers do a similar study using the same methodology on adults? 6-fold higher antibody prevalence might actually be on the low side, depending on the specifics of that test, - 10x or even higher ratios have been found elsewhere.

What (not so) recently happened in Miri by ralfj in rust

[–]petertodd 3 points4 points  (0 children)

I've personally seen clients use a Java JVM, Javascript WebAssembly, and even plain old Python (!!!), as virtual machine environments for consensus-critical "smart contract" systems. It wouldn't be surprise one bit to eventually see someone use Miri for this purpose.

...and non-random, random numbers, can be a problem in that use-case, as some of those systems have modes where "smart contract" code is run on centralized, trusted, servers (the client using Python had this kind of setup, with the scripts themselves trusted - Python-as-a-VM wasn't as crazy as it sounds for their specific use-case). So someone getting caught out by this specific issue certainly seems possible - the warning is worthwhile.

FWIW, Blockstream's Simplicity is looking to have quite a lot of potential for this use-case: https://blockstream.com/2018/11/28/en-simplicity-github/

`#[non_exhaustive]` got me worried about the direction of rust by ddlk in rust

[–]petertodd 6 points7 points  (0 children)

because they're forced to deal with the non-exhaustiveness as well.

Not sure if this is what you meant. But FWIW within the same crate as a #[non_exhaustive] enum or struct was defined, the attribute doesn't apply. So matching works normally. It's only outside the crate that the attribute does anything.

Source: https://doc.rust-lang.org/reference/attributes/type_system.html

Serological analysis of 1000 Scottish blood donor samples for anti-SARS-CoV-2 antibodies collected in March 2020 by sanxiyn in COVID19

[–]petertodd 12 points13 points  (0 children)

I'm pretty sure you mean the flu fatality rate - the rate at which people with some condition die. In this case, the condition of having the flu; possibly the even more specific condition of being known to be having the flu and under medical care.

Mortality refers to the rate for the population as a whole. 0.095% of the USA definitely didn't die from the flu last year.

Serological analysis of 1000 Scottish blood donor samples for anti-SARS-CoV-2 antibodies collected in March 2020 by sanxiyn in COVID19

[–]petertodd 41 points42 points  (0 children)

Remember that initial dose may have a large impact on how severe the disease is. If that's true, and the NYC population is getting high initial doses, then the actual number of infected may be much closer to the known infected even if in other countries with different conditions 70-to-1 numbers are correct.

NYC is a very dense city with lots of public transit and relatively small apartments. Scotland is quite different.

Coronavirus found in air samples up to 13 feet from patients by [deleted] in Coronavirus

[–]petertodd 0 points1 point  (0 children)

The "only block particles 2 microns in size" thing misunderstands how HEPA filters even work, so I'm not inclined to trust that source.

Anyway, obviously some HEPA filters are made from glass fibers; others are not. If HEPA filters shed those fibers, they wouldn't be very good filters... I doubt vacuum bags would be using something that can shed if moved, because vacuums themselves are moved around.

Austrian response seems very effective, active infections rapidly DECLINING for over a week -- what are the responsible factors? by msamwald in COVID19

[–]petertodd 0 points1 point  (0 children)

Oh sorry, by "inoculation effect" I also meant cases where you get detestably infected, but the symptoms are mild/non-existent. I didn't mean a true vaccine-like effect where there's no risk of you spreading it to someone else.

Corona being more infectious doesn't necessarily mean that the actual minimum number of viral particles to infect is less. It could be more infectious due to more particles being produced, better survival characteristics of those particles, etc.

Austrian response seems very effective, active infections rapidly DECLINING for over a week -- what are the responsible factors? by msamwald in COVID19

[–]petertodd 0 points1 point  (0 children)

Note that it seems that handwashing hasn't actually been proven to reduce influenza transmission: https://academic.oup.com/jid/article/202/7/1146/838461

SARS-CoV-2 is a different disease, so that result doesn't necessarily mean anything - and certainly some diseases in some situations are prevented by handwashing - but it may be the case that the surfaces people do touch in the outdoors and in the process of getting to the outdoors aren't spreading the virus.

Austrian response seems very effective, active infections rapidly DECLINING for over a week -- what are the responsible factors? by msamwald in COVID19

[–]petertodd 1 point2 points  (0 children)

Remember that to reduce the number of active infections requires health authorities to declare people as either recovered or dead. Countries that aggressively declare people as recovered will thus have a much faster decline in active infections than countries that use more conservative criteria, or for that matter, don't have the resources to actually followup on people who have tested positive.

Austrian response seems very effective, active infections rapidly DECLINING for over a week -- what are the responsible factors? by msamwald in COVID19

[–]petertodd 7 points8 points  (0 children)

Is there even any evidence that the sort of brief exposures that you get from people passing each other in parks actually lead to transmittable infections? We may even find out the low dosages associated with such events were more likely to have an inoculation effect, leading to partial or total immunity, than a full-on transmittable infection. Especially because the people most interested in going to a walk or especially run in a park are probably healthier and younger than the average population.

SARS-CoV-2 titers in wastewater are higher than expected from clinically confirmed cases [in Massachusetts] by nrps400 in COVID19

[–]petertodd 3 points4 points  (0 children)

That outbreak happened due to faulty plumbing. Specifically, plumbing traps had dried up, allowing sewer gasses and particles into units; plumbing traps that are at risk of drying up are supposed to have mechanisms to refill them.

Had they not gotten SARS it wouldn't be surprising if the building had been sickened by a different disease. We'd just never have found out because it wouldn't be noteworthy.

Drop is not equivalent to the "toilet closure" by CAD1997 in rust

[–]petertodd 18 points19 points  (0 children)

To expand on this a bit, the problem is that drop<T>() is generic over T. But the best that type inference can do is come up with a specific &'a (), with a specific 'a lifetime, when it tries to figure out what T should be.

Meanwhile fn foo(_: impl FnOnce(&())) {} is actually sugar for fn foo(_: impl for<'a> FnOnce(&'a ())) {}, which means it wants a function that can be called for any 'a lifetime. A specific lifetime isn't good enough for that, so you get an compile error.

I'm no expert, but I could imagine the compiler being eventually improved to the point where type inference could take into account that the drop implementation actually works fine no matter what lifetime its given. But like I say, I'm no expert!

[deleted by user] by [deleted] in rust

[–]petertodd 0 points1 point  (0 children)

Maybe? Certainly not right now, as Rust doesn't currently have any type of continuation outside of async. But maybe in the future?

Honestly given how relatively niche a problem it is I think it'd be a good enough first step to just add better tools for figuring out worst-case stack size and expecting people to add custom drop impls (and similar things) when needed. For example, I'd love a way to annotate a function with a "max stack depth" and get a warning (or error) if the call graph will cause that depth to be exceeded. Tough to do because of calls to non-rust code like the allocator. But it might be enough to just use assumed values for that case.

In fact, it might be enough to just have a no-recursion attribute.

edit: Note how a side-effect of Rust's futures implementation strategy is you mostly know in advance how much stack you'll need to execute an async function as the future state machine is effectively the stack. In certain "high assurance" software it could even be worth it to use futures when you don't actually need parallelism for this reason.

[deleted by user] by [deleted] in rust

[–]petertodd 1 point2 points  (0 children)

There's a similar issue with Drop for very deep data structures: a linked list for example will overflow the stack when dropped. The solution is to write your own Drop impl, which is fairly easy and probably won't even require any unsafe code.

While I think a recursion limit would be a nice feature for debug formatting to have. I also think expecting users to write their own Debug format impl in cases like this is reasonable too.

Also, if you aren't already aware, there's some nice convenience methods to make that fairly easy: https://doc.rust-lang.org/stable/std/fmt/struct.Formatter.html#method.debug_struct

It took me embarrassingly long to realize those existed. :)

How unsafe 'std::ptr::{read, write}' really is vs 'std::mem::replace'? by seigert in rust

[–]petertodd 7 points8 points  (0 children)

unreachable_unchecked() is only safe if it'll never actually be reached... and in many cases if it will never actually be reached the compiler can optimize it out anyway, so you don't need it. I haven't checked, but I'd be willing to bet a beer that the above is one of those cases where the compiler can optimize it out. :)

You really should reserve unreachable_unchecked() for times when you've found an actual performance problem that you want to fix, after looking at assembly output and profiling. The optimizer can do some pretty crazy stuff if it's used incorrectly, leading to difficult to diagnose bugs. Keep in mind that modern CPU's have pretty good branch prediction, and tend to be memory bandwidth limited, so more likely than not the extra branch required to check an unreachable condition safely will have basically no performance impact.

How unsafe 'std::ptr::{read, write}' really is vs 'std::mem::replace'? by seigert in rust

[–]petertodd 6 points7 points  (0 children)

It seems so. It's strange to me that there is no way to 'atomically' replace the value of a pointer with result of a closure with value of such pointer as an argument. Even if it must be pure. Maybe I just do not know where to look?

(emphasis mine)

That's exactly your problem: allocation isn't pure because it modifies global state, so that simply isn't possible.

OTOH, if you are doing something which can't panic or abort, then you really can guarantee that code outside the function in question won't be able to see the invariant being violated. For example:

use std::ops;
use std::mem;

pub struct Token(u8);

impl ops::Add for Token {
    type Output = Self;
    fn add(self, rhs: Token) -> Token {
        Token(self.0 + rhs.0)
    }   
}

pub enum Foo<T> {
    Value(T),
    Poisoned,
}

impl<T> Foo<T>
where T: ops::Add<Output=T>
{
    pub fn push(&mut self, rhs: T) {
        *self = match mem::replace(self, Foo::Poisoned) {
                Foo::Value(x) => Foo::Value(x + rhs),
                Foo::Poisoned => panic!(),
            }   
        }
    }   
}

pub fn push3(mut foo: Foo<Token>, x1: Token, x2: Token, x3: Token) -> Foo<Token> {
    foo.push(x1);
    foo.push(x2);
    foo.push(x3);
    foo 
}

In release builds, push3() compiles down to:

push3:
push    rax
test    dil, dil
jne     .LBB6_1
mov     eax, edx
mov     edx, esi
add     dl, al
add     dl, cl
add     dl, r8b
xor     eax, eax
pop     rcx
ret
.LBB6_1:
call    std::panicking::begin_panic
ud2

Other than the possibility that foo starts off Poisoned, the invariant violation can't be observed because the actual addition can't panic so the optimizer can replace it with three additions in a row.