Why Not Just Use X? An Instructive Example from Bitcoin

Bitcoin developer Gregory Maxwell writes: On Reddit:

There is a design flaw in the Bitcoin protocol that allows a third party to take your valid transaction and change it to a different transaction ID, leaving it valid and functionally identical. . This greatly complicates writing correct wallet software and can be exploited to invalidate long chains of unconfirmed transactions that depend on non-mutant transactions (as transactions are cross-referenced by txid) .

This issue arises from several reasons. One of them is that OpenSSL accepts and tries to make sense of invalid encoding signatures. A typical ECDSA signature encodes two large integers. Encoding is not constant length. If there are leading zeros, you need to remove them.

It’s easy to write software that assumes the signature is a certain length and leaves extra leading zeros.

This is a very interesting lesson, especially important because this situation is part of why we made certain design decisions in our development philosophy. Specifically, the problem is: Many people keep pointing out that in many places we are unnecessarily reinventing the wheel or creating our own serialized formats. RLPinstead of using the existing one, protobuf And we’re building application-specific scripting languages ​​rather than “just using Lua.” This is a very valid concern. Syndromes not invented here are commonly used derogatory wordsTherefore, there must be a good reason for such in-house development.

And the cautionary tale quoted above provides a perfect example of exactly the justification I am about to offer. While external technologies such as protobuf, Lua, and OpenSSL are very good and have been in development for many years, they are often designed with the perfect consensus, determinism, and cryptographic integrity required in cryptocurrencies in mind. It wasn’t designed for you. The OpenSSL situation above is a perfect example. Outside of cryptocurrencies, there is no other situation where the fact that you can take a valid signature and convert it to another valid signature with a different hash is a serious problem, but here it is fatal. One of our core principles at Ethereum is simplicity. The protocol should be as simple as possible, and the protocol should not contain any black boxes. All functionality of all sub-protocols 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 almost as difficult as building a completely new package from scratch. In fact, while existing software packages are often more complex than necessary for complete functionality, our replacement packages are not, and can actually be even more difficult. Protobuffer specifications and compare it with RLP specifications To understand what I mean.

Please note that the above principles have limitations. For example, we are not stupid enough to start inventing our own hashing algorithms. Instead, we use the widely acclaimed and well-vetted SHA3. It also uses the same old secp256k1 as Bitcoin for signatures, but uses RLP to store the signatures. An alternative to the OpenSSL buffer protocol is a v, r, s triple (where v is an additional 2 bits for public key recovery purposes). In these situations, “just use X” is exactly the right thing to do. This is because X has a clean, well-understood interface, and there are no subtle differences between different implementations. The SHA3 of an empty string is c5d2460186…a470 in C++, Python, and JavaScript. There’s no debate about that. It’s basically about finding the right balance between these two extremes.

Related Article


Leave a Comment