News for hackers. Stuff that matters.
Re:Bitcoin's Academic Pedigree by ChrisClark on Wednesday August 30, 2017 @04:10PM (#15135558)
Just clicked to check it out and was reminded about how much I like the base-58 scheme they used for addresses.
Re:Bitcoin's Academic Pedigree by sillysaurus3 on Wednesday August 30, 2017 @04:17PM (#15135618)
There's so much like that. I'm going to try to write a blog post highlighting all the gems.

My favorite is:

    IMPLEMENT_SERIALIZE
    (
        READWRITE(prevout);
        READWRITE(scriptSig);
        READWRITE(nSequence);
    )
It's a C++ macro that implements reading and writing member variables to/from disk/network. It uses C++ templates to figure out the sizes of everything, so it winds up packing items efficiently. We used something similar in the gamedev industry, so this was a delightful surprise.

Ohh, no, I take it back. This is my favorite:

    //
    // Compact size
    //  size <  253        -- 1 byte
    //  size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)
    //  size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)
    //  size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)
    //
    inline unsigned int GetSizeOfCompactSize(uint64 nSize)
    {
        if (nSize < UCHAR_MAX-2)     return sizeof(unsigned char);
        else if (nSize <= USHRT_MAX) return sizeof(unsigned char) + sizeof(unsigned short);
        else if (nSize <= UINT_MAX)  return sizeof(unsigned char) + sizeof(unsigned int);
        else                         return sizeof(unsigned char) + sizeof(uint64);
    }
When encoding an arbitrary value, if it's less than 253, it only uses 1 byte of space. When you read a byte off the network, if it's 253, you know there are two more bytes to read. 254 = 4 bytes, 255 = 8 bytes.

Again, it's a small thing -- very standard tactic. But there are dozens of tiny, effective decisions exactly like this all throughout the codebase.

There's a secure allocator for wiping your private key so that it doesn't hang out in memory, with hacks to work around MSVC8 problems. Which academics bother with MSVC8 hacks?

    //
    // Allocator that clears its contents before deletion
    //
    template<typename T>
    struct secure_allocator : public std::allocator<T>
    {
        // MSVC8 default copy constructor is broken
        typedef std::allocator<T> base;
        typedef typename base::size_type size_type;
        typedef typename base::difference_type  difference_type;
        typedef typename base::pointer pointer;
        typedef typename base::const_pointer const_pointer;
        typedef typename base::reference reference;
        typedef typename base::const_reference const_reference;
        typedef typename base::value_type value_type;
        secure_allocator() throw() {}
        secure_allocator(const secure_allocator& a) throw() : base(a) {}
        ~secure_allocator() throw() {}
        template<typename _Other> struct rebind
        { typedef secure_allocator<_Other> other; };

        void deallocate(T* p, std::size_t n)
        {
            if (p != NULL)
                memset(p, 0, sizeof(T) * n);
            allocator<T>::deallocate(p, n);
        }
    };
Another gem (note the comments):

   case OP_EQUAL:
   case OP_EQUALVERIFY:
   //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL
   {
       // (x1 x2 - bool)
       if (stack.size() < 2)
           return false;
       valtype& vch1 = stacktop(-2);
       valtype& vch2 = stacktop(-1);
       bool fEqual = (vch1 == vch2);
       // OP_NOTEQUAL is disabled because it would be too easy to say
       // something like n != 1 and have some wiseguy pass in 1 with extra
       // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
       //if (opcode == OP_NOTEQUAL)
       //    fEqual = !fEqual;
       stack.pop_back();
       stack.pop_back();
       stack.push_back(fEqual ? vchTrue : vchFalse);
       if (opcode == OP_EQUALVERIFY)
       {
           if (fEqual)
               stack.pop_back();
           else
               pc = pend;
       }
   }
   break;

Bitcoin is worth N billion dollars right now, and this codebase really is a billion dollar codebase. Is this really the work of a single person?
Re:Bitcoin's Academic Pedigree by virtuexru on Wednesday August 30, 2017 @04:25PM (#15135683)
I really hope you make that post highlighting your favorite parts of the C++ Bitcoin codebase; it is super interesting! Keep up the great work.
Re:Bitcoin's Academic Pedigree by userbinator on Wednesday August 30, 2017 @04:24PM (#15135678)
That was probably inspired by ASN.1 or other serialisation protocols.

The formatting of the code in that function also puzzles you for an instant, but then you realise just how much clearer it makes it over the "lame" but "consistently formatted" alternative of

    if ( )
    {
        ....
    }
    else if ( )
    {
        ...
    }
    ....
Re:Bitcoin's Academic Pedigree by kobeya on Thursday August 31, 2017 @04:25AM (#15138963)
No those weren't the work of a single person. You're quoting versions of the code base that post date the public introduction of bitcoin. Some of the things you call out were written by others, and others were written in response to public review.
Re:Bitcoin's Academic Pedigree by kobeya on Thursday August 31, 2017 @04:20AM (#15138943)
Even people working on bitcoin aren't fans of base58. Variable length serialization? Bignums in the serializer? Poor error detection? No error correction? Confused characters in alphabet? Case sensitivity? Lots of reasons to dislike.
Re:Bitcoin's Academic Pedigree by gruez on Thursday August 31, 2017 @09:23AM (#15140075)
>Poor error detection? No error correction?

It's implemented at a higher level. For bitcoin, a 32 bit check field is appended to the data to serve as a checksum. If you want parity, I'd imagine that could be done as well.

>Confused characters in alphabet? Case sensitivity?

Some look alike letters are excluded, hence why base58 rather than base62.

Re:Bitcoin's Academic Pedigree by ChrisClark on Thursday August 31, 2017 @12:19PM (#15141361)
> Confused characters in alphabet?

That's really the only reason I was saying I liked base58. Because it removes those confusing characters compared to base64 or others.

Re:Bitcoin's Academic Pedigree by kobeya on Thursday August 31, 2017 @09:19PM (#15145417)
Ah, but it doesn't do a very good job of that. It only removed a few pairings, and made some odd choices at that. Hence why I list it as one of the issues.