As a c++ developer I would nope the hell out of there or spend a month fixing the warnings - depending on pay. No way would I work with something in that state long term.
> until somebody gets to fix all warnings which are not bugs.
Code that is filled with ignored warnings generally gets worse, not better. Having little to no quality standards does that.
You might even find some zero days just by addressing all the warnings.
There's a reason practically no one uses a memory-safe C++ implementation.
You can have code without any warnings in clang, gcc and msvc++ compilers and it is probably better than code tested with only one compiler.
--
[0] - even if by ignoring them, when you're absolutely sure what you're doing.
-Wall -Wextra -Werror
If these options are set before you write any code, then these problems don't arise.Also IMO you often want to explicitly disable a few of those from -Wall and -Wextra -- Looking at the last c++ project I wrote, I turned off a few things like `-Wno-unused-parameter` for example.
[0]: http://blog.schmorp.de/2016-02-27-tidbits-for-the-love-of-go...
As you get further into a project you tend to need subtler tools. But for the rough work when starting out, my preference is to be stricter, which can be relaxed as necessary, rather than starting out lax and reaching a point where tightening becomes Sisyphean.
-Weverything
Which does actually turn on all warnings (so you'll probably want to add things like -Wno-unused -Wno-padded).Under gcc, '-Wall -Wextra -Wpedantic' does not enable all warnings. There are still more than 40 flags you have to give if you really want all of them.
The reason why boggles my mind to this day.
IMO rote splitting usually doesn't simplify, it just hides the complexity.
Bitcoin was also created by someone using a Japanese pseudonym, same place anime comes from.
The bug happened in "inlined constructor" so they should check all uses of this class/struct to check if it is not copied to other places (and probably all other structs/classes).
This case specifically, a lot of the issues that allowed this to happen were logic errors which would have been valid in most languages. A functional language would not have helped very much here.
C and C++ are still used because they work, and have huge ecosystems around them. There's a lot of tooling around them, the compilers build fast, code, and are available for pretty much every planet under the sun. This particular case, it would have helped a lot if the developers looked at the warnings of the questionable code they had made, but they seem to be of the "it compiles, ship it" type that would have let those things fly regardless of the language.
I think the lesser amount of libraries and lacking the chance of fine-tuning performance (but also your risk of screwing up your performance badly) is a very low price for the provably impossibility to have a mistake like this.
I'm just thinking back on my career, which has been full of bugs of all magnitudes. If I categorise my past bugs, there are many common patterns. Famous old-timers have names, like buffer overflows or memory leaks etc etc. Just not having the possibility to make those errors is such a freeing experience.
Also what's the big problem with no independent standardisation?
I think with the types of errors you mentioned, that part of it definitely is ecosystem. Look at OpenBSD, for example. They've built things like a safer malloc and fairly extensive patches to gcc that have caught a lot of errors and bugs. I think C/C++ can definitely get safer without changing that much, the ecosystem just needs to get a bit angrier about warnings, etc.
Standardization, and multiple implementations, means you can have multiple sets of compiler eyeballs looking over things. The zcoin bug, for example, emits a warning with the default settings of clang, but doesn't emit a peep with the default settings of gcc. For someone working with a lot of embedded code, it also means that there's a better chance that there's an implementation of the language ready to go when you need to move to a different platform.
> Unfortunately when populating the denomination member variable, an equality operator was used instead of assignment, resulting in the denomination always being zero, as set in the class constructor.
So = Vs ==
Building with warnings on would also have caught it, but the fact that someone started a new project without this warning turned on shows that C++'s defaults around warnings are bad, which is an ecosystem ergonomics issue.
In Rust, x = y evaluates to (), not any of the values in x or y.
In Rust, numbers are not implicitly usable as booleans in conditionals.
I think the main advantage Rust has over OCaml is that it is syntactically more like C. But, hey, if it's what gets HM-style type inference to the masses, I'll take it.
So if you want to blame anything, blame the concept of expression statements, I guess?
The idea that you form a value by creating an uninitialized one and then filling in its fields is dumb. (I suspect the field value wasn't even 0 as such but rather undefined, and the implementation happened to make it 0?). Better languages have you initialize the value directly and you can't access it until it's fully initialized. C/C++ are just really bad at expressing nontrivial values, even value literals.
(Discarding a value ought to be an error too, though that's more cumbersome to work with)
Programming without state is something that has helped me personally make my code much better. I produce less bugs by far since I stopped relying on state for so many things. A lot of micro-optimisations are not doable for me. In exchange I guess I get to run things in parallell very easily. But mostly, I get fewer bugs, which makes my life and the lives of my customers better.
A lot of times it isn't actually any faster, and it's certainly more error prone.
So, just as in c++ there is a different operator of assignment and equality that requirs you to type a different thing. User error and testing failure.
Let's collectively put our seat belts on, colleagues!
A cryptocurrency implementation like this doesn't need a language that makes state impossible. It needs static analysis, model checking, and proofs. This would be true even if it were written in your favorite functional language.
If there was not state, the coder wouldn't had tried to set it. I don't think a language needs to have the `=` operator easy and close at hand. Had that not been the case, this bug (and oh so many others) would never had existed.
ZCash was built upon the Bitcoin codebase. This inherits a lot of bad decisions. Moral purity, demanding they start over again from scratch, just isn't practical.
The bug in question could have been solved had the simply compiled with minimal static analysis -- by which I mean -Wall.
C/C++ is memory safe if you turn on dynamic checking. Sure, it's twice as slow as C/C++, but still tons faster than nonsense languages like Ocaml or Haskell.
In any case, Zcash is also derived from Bitcoin and builds with `-Werror` (edit: not `-Wall`, but we're working on that). That kind of minimal static analysis is certainly not sufficient to catch the majority of bugs, though.
C++ is not memory safe in any meaningful sense. There have been efforts to define a memory-safe subset, but typical large codebases, including Bitcoin, do not come close to falling within that subset.
What's the option to turn that on? Which compilers is it in?
I know there were several fat-pointer patches to GCC back in the day, but I didn't think anything remotely similar had ever gone mainstream. There's just too much existing code that relies on undefined behavior last I checked.
Is anyone here doing this? Would be interesting to hear your experience.
valgrind --quiet --leak-check=full --error-exitcode=1 *binary*It's just a lot of untested code. Surely even Ocaml and Haskell need tests.
Companies exist to make money so the most responsible thing to do is make as much money as possible. If breaking the law means you will make more money then do it.
See: a x b x c = x formula from Fight Club or Uber's entire business model.
Your assumption that we don't want bugs is probably why you are asking the question. Companies don't care about bugs, they care about losing money so if the bug doesn't cost money it's not worth fixing until it costs more than the fix.
I think this is actually very short sighted but that's just how the incentives align in our current system.
I make no claim to the philosophical implications of any of this.
One reason is security - if cryptography isn't done in constant time then there is the potential for timing attacks. This is why BitCoinJ ditched BouncyCastle for their own JNI wrapper around BitCoin's libsecp256k1.
There is a rust client for Ethereum, called Parity - they do FFI calls to libsecp256k1. Similarly rust-crypto vendors most of its crypto in C that it calls through FFI. Similarly go-ethereum also uses libsecp256k1. However, I know that Tendermint uses Ed25519 instead of secp256k1, and in turn they use NaCl which does not involve FFI.
Mining for Ethereum is done on a GPU, so the miner code is necessarily written in OpenCL or CUDA.
There are a few blockchains written in functional language but they are new to the scene. There were a couple of Haskell Ethereum clients but they appear to be abandoned. I know kadena[1] and cardano[2] are written in Haskell. There is also Aeternity[3], which is the only currency I know of written in Erlang.
In the early days Charles Hoskinson apparently wanted Ethereum to be written in Scala. I don't think any of the core devs know Scala, but then again Charles Hoskinson was booted from the project so his language choice was dropped.
Synereo was to be written in Scala, but the founders (the CEO and the CTO) split in December. The CEO doesn't want Synereo to make a blockchain anymore, he wants to make some kind of escrow for ponzi schemes. I hear from the devs they want to code the thing in javascript. The CTO is making something called RChain; I heard he wants to use some pi-calculus interpreter he wrote in C90 back when he worked at Miter corporation in the 90s, but maybe he's ditching that.
From job postings I can see MaidSafe is looking for Rust programmers. MaidSafe has been in R&D for a decade, so they must have had yet another pivot recently.
To be frank, while there are functional programmers in the scene, these guys are struggling to establish themselves. There's a lot more talent in procedural programming which is why so much code is written in those languages. I'm not 100% that functional code is going to have fewer bugs which result in financial exploits.
[1] http://kadena.io/ [2] https://iohk.io/projects/cardano/ [3] https://github.com/aeternity
I gave a talk with a summary of why they switched from C++ as part of this general talk on production Rust last year: https://www.infoq.com/presentations/rust-production
æternity is a new blockchain for scalable smart contracts interfacing with real-world data via a decentralized oracle.
Smart contracts are essentially pure functions here. We have also a compiler for a Lispy language.
Check out our whitepaper (www.aeternity.com) and check out our Github ( github.com/aeternity/testnet ) (also check the /docs folder).
Disclaimer: I am the founder of aeternity.
If you make your new coin based on a functional language, there's fewer people who'll be able to jump in and code.
c++ looks similar enough to the other {} languages that many people will have the skills to give it a go.
Unfortunately it's different enough that you can really mess things up, but you already know that.
Using 'unmanaged' languages for 'performance' reasons is no longer a good reason, because the likes of C# have shown multiple times that there is no reason to choose C++ over C# if you look at performance alone (difference is neglible).
http://benchmarksgame.alioth.debian.org/u64q/compare.php?lan...
Sure, it's silly benchmarks, so I wouldn't take the results as gospel. But the fact is, nobody who writes C# managed to produce a benchmark yet that beats a C++ program.
Fast languages like Rust have managed to at least match the performance of C in some benchmarks (and even beat it in others).
http://benchmarksgame.alioth.debian.org/u64q/program.php?tes...
How should /unsafe be set with .Net CORE csproj ?
"buildOptions": {
"allowUnsafe": true
}
I was able to fake something for dotnet migrate and find the needed setting: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>No, but I've seen Haskell programs that were much faster than the C++ program they replaced, which is what matters in the real world.
Microbenchmarks measure what happens if you have the time to polish every single line to perfection. If you have infinite developer time then C++ will be faster than most languages. But infinite developer time is a negligible use case.
http://benchmarksgame.alioth.debian.org/u64q/program.php?tes... http://benchmarksgame.alioth.debian.org/u64q/program.php?tes...
I assume Rust allows for the same type of error?
Not familiar with Rust, but does the following work?:
let mut x = 0;
if x = 1 {
println!("oops, meant ==");
} error[E0308]: mismatched types
--> src/main.rs:5:6
|
5 | if x = 1 {
| ^^^^^ expected bool, found ()
|
= note: expected type `bool`
= note: found type `()`
error: aborting due to previous error
error: Could not compile `playground`.
To learn more, run the command again with --verbose. fn main() {
let mut x = false;
println!("{}", x);
if {x=true;x} {
println!("{}", x);
}
}
But stands out as pretty obvious. Not something you might easily sneak into a codebase.Isn't it true though, that with some techniques certain bugs are impossible to make? If you have not experienced it, I recommend you to seek it out and try.
Still? Since when? Last I checked it was 661kB for Rust vs 829kB for C, and that was quite a while ago.
Zero bugs around state, zero bugs around memory mgmt, zero bugs about error conditions not being handled, zero bugs due to some data being expected but not being written, etc.
The programmer admitted that he was a cryptography novice, and in fact a Haskell novice.
As a result the code he wrote is needlessly abstract - for one thing the guy uses Free monads and in turn ropes in template Haskell as part of his state model. I really have no idea what code he's generating.
The code has other features that make review challenging - for instance he doesn't qualify any of his imports so it's hard to tell where to look for the functions he's implementing.
Maybe you are better at auditing Haskell than I am. As DJ Bernstein writes in various places, one common exploit is to construct an elliptic curve Diffie Helman shared secret with input that isn't a curve point. I really can't tell if the guy is mitigating against this attack or not, but here you can have a look:
C++ is not memory-safe (no GC or whatever Rust does), it's not type safe (in the ML sense), it relies on writing to memory a lot (instead of having pure functions). Had this program been written in Ocaml or Haskell or a strongly typed functional Lisp, this bug would have been impossible to make.
Why do we do this, still? Is it not irresponsible?