Bitcoin developer Gregory Maxwell wrote: From Reddit:
There is a design flaw in the Bitcoin protocol that allows a third party to take your valid transaction and alter it in a way that is valid and functionally identical, but with a different transaction ID. This greatly complicates writing proper wallet software, and can be abused to invalidate long chains of unconfirmed transactions that rely on non-mutant transactions (since transactions refer to each other by txid).
This problem arises from several sources. One of them is OpenSSL’s willingness to accept and understand signatures containing incorrect encoding. A typical ECDSA signature encodes two large integers, and the encoding is not of constant length. If there are leading zeros, they should be removed.
It’s easy to write software that assumes the signature is of constant length and leaves extra leading zeros.
This is a very interesting cautionary tale, and especially important because situations like this are part of the reason we made certain design decisions in our development philosophy. The problem in particular is this. Many people continue to raise the point that we are unnecessarily reinventing the wheel in many places and creating our own serialization formats. RLPInstead of using the existing protoboof And instead of “just using Lua,” we are building an application-specific scripting language. This is a very valid concern. Syndrome not invented here A commonly used derogatory expressionTherefore, this self-development requires justification.
And the cautionary tale quoted above provides exactly the perfect example of the justification I will provide. External technologies such as protobuf, Lua or OpenSSL are very good and have had years of development, but in many cases they were not designed with the perfect consensus, determinism and cryptographic integrity required by cryptocurrencies in mind. The OpenSSL situation above is a perfect example. Outside of cryptocurrencies, there’s really no situation where the fact that you can take a valid signature and replace it with another valid signature using a different hash is a critical issue, but here it’s critical. One of Ethereum’s core principles is simplicity. Protocols should be as simple as possible and should not contain black boxes. Every single feature of every single sub-protocol must be 100% accurately documented in a whitepaper or wiki, and implemented using it as a specification (i.e. test-driven development). Doing this for an existing software package is just as difficult as building an entirely new package from scratch. In fact, it may be even more difficult because existing software packages are more complex than necessary to complete their functionality, and our alternative is not. Protoboof specifications And compare them. RLP Specification To understand what I mean.
The above principles have limitations. For example, we are not so foolish as to start inventing our own hashing algorithms instead of using the universally acclaimed and well-validated SHA3. For signatures it’s using the same old secp256k1 as Bitcoin, but for storage it’s using RLP. Instead of the OpenSSL buffer protocol it is a v,r,s triple (v is an additional 2 bits for public key recovery purposes). These kinds of situations are ones where “just use X” is exactly the right thing to do. Because X has a clean, well-understood interface and there are no subtle differences between different implementations. SHA3 for an empty string is c5d2460186…a470 in C++, Python, and Javascript. There’s no debate about that. It is important to find fundamentally the right balance between these two extremes.