Search code examples
c++gnucrypto++

Compiling bfx-cpp-api - Byte datatype undeclared


So I am looking to compile this project https://github.com/MMquant/bfx-cpp-api using the example code. I have included the cryptopp file that was suggested in the read me. It is found here: https://github.com/weidai11/cryptopp.

I am using Ubutnu version 17.10 and the GNU compiler.

Here's how I am compiling:

g++ example.cpp BitfinexAPI.cpp BitfinexAPI.hpp  -Icryptopp -I.  -o a -w -std=c++17

It seems strange that BitFinex would support broken code so I am fairly sure that the issue must be something that I am doing.

The errors I am getting are related to line 936 where the datatype 'byte' is not declared. My prediction is that I am missing a header file somewhere but any help would be appreciated.


$ g++ example.cpp BitfinexAPI.cpp BitfinexAPI.hpp  -Icryptopp -I.  -o a -w -std=c++17
BitfinexAPI.cpp: In static member function ‘static int BitfinexAPI::getBase64(const string&, std::__cxx11::string&)’:
BitfinexAPI.cpp:936:5: error: ‘byte’ was not declared in this scope
     byte buffer[1024] = {};
     ^~~~
BitfinexAPI.cpp:936:5: note: suggested alternative:
In file included from ../cryptopp/seckey.h:9:0,
                 from ../cryptopp/hmac.h:9,
                 from BitfinexAPI.cpp:37:
../cryptopp/config.h:222:23: note:   ‘CryptoPP::byte’
 typedef unsigned char byte;
                       ^~~~
BitfinexAPI.cpp:940:9: error: ‘buffer’ was not declared in this scope
         buffer[i] = content[i];
         ^~~~~~
BitfinexAPI.cpp:940:9: note: suggested alternative: ‘setbuffer’
         buffer[i] = content[i];
         ^~~~~~
         setbuffer
BitfinexAPI.cpp:943:21: error: ‘buffer’ was not declared in this scope
     StringSource ss(buffer, content.length(), true, new Base64Encoder( new StringSink(encoded), false));
                     ^~~~~~
BitfinexAPI.cpp:943:21: note: suggested alternative: ‘setbuffer’
     StringSource ss(buffer, content.length(), true, new Base64Encoder( new StringSink(encoded), false));
                     ^~~~~~
                     setbuffer
BitfinexAPI.cpp: In static member function ‘static int BitfinexAPI::getHmacSha384(const string&, const string&, std::__cxx11::string&)’:
BitfinexAPI.cpp:963:33: error: ISO C++ forbids declaration of ‘type name’ with no type [-fpermissive]
     SecByteBlock byteKey((const byte*)key.data(), key.size());
                                 ^~~~
BitfinexAPI.cpp:963:27: error: expected primary-expression before ‘const’
     SecByteBlock byteKey((const byte*)key.data(), key.size());
                           ^~~~~
BitfinexAPI.cpp:963:27: error: expected ‘)’ before ‘const’

Solution

  • Here's how I am compiling:

    g++ example.cpp BitfinexAPI.cpp BitfinexAPI.hpp  -Icryptopp -I.  -o a -w -std=c++17
    

    It seems strange that BitFinex would support broken code so I am fairly sure that the issue must be something that I am doing.

    The errors I am getting are related to line 936 where the datatype 'byte' is not declared. My prediction is that I am missing a header file somewhere but any help would be appreciated.

    @kabanus identified the problem.

    Crypto++ used to provide a byte in the global C++ namespace. It was there for two reasons. First, it was a convenience item on Linux. You could use byte instead of CryptoPP::byte. Second, it avoided compiler errors on Windows. Microsoft SDK's provide a byte in the global namespace, and if we put a byte at CryptoPP::byte then compile errors resulted from ambiguous definitions.

    C++17 came along and offered a std::byte; see P0298R0, A byte type definition. The global Crypto++ byte broke Linux when folks used a using namespace std. And it completely broke Microsoft because Microsoft SDK's provides a global byte. Ironically, the authors of P0298R0 work for Microsoft.

    Crypto++ placing a byte in the global namespace was a C++ No-No. We got away with it for years, but it jumped up and bit us in C++17. We moved it into our namespace where it belongs. The check-in occurred at Commit 00f9818b5d8e, which happened after 5.6.5 was released and prior to 6.0 release.

    Looking at the source for BitfinexAPI.cpp, this is probably the solution... open BitfinexAPI.cpp, and add the following at the top of the file:

    // CRYPTOPP_NO_GLOBAL_BYTE signals byte is at CryptoPP::byte
    #if defined(CRYPTOPP_NO_GLOBAL_BYTE)
      using CryptoPP::byte;
    #endif
    

    Also see std::byte on the Crypto++ wiki. We took the time to document it because of all the problems std::byte, Microsoft's global byte and our byte definitions are going to cause.


    Related, you don't need to specify the C++ header on the command line. The compile error is due to the changes detailed above. All you need is:

    g++ -std=c++17 example.cpp BitfinexAPI.cpp -I. ./cryptopp/libcryptopp.a -o example.exe
    

    This assumes a directory structure of:

    - bfx-api/
      |
      +- cryptopp/
    

    The cryptopp/libcryptopp.a is a convenient way to sidestep those stupid Linux path problems that have existed for years. You link against the static archive which means you don't need a library at runtime.


    Now open in the BFX issue tracker: Crypto++ byte change at Crypto++ 6.0. It should help the project engineer around the changes.