[
  {
    "path": ".gitignore",
    "content": ".vscode\nbuild"
  },
  {
    "path": ".mbedignore",
    "content": "examples/*\ntests/*\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Stepan Snigirev\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Micro-Bitcoin\n\nC++ Bitcoin library for 32-bit microcontrollers. The library supports [Arduino IDE](https://www.arduino.cc/), [ARM mbed](https://www.mbed.com/en/) and bare metal.<br>\nIt provides a collection of convenient classes for Bitcoin: private and public keys, HD wallets, generation of the recovery phrases, PSBT transaction formats, scripts — everything required for a hardware wallet or other bitcoin-powered device.\n\nThe library should work on any decent 32-bit microcontroller, like esp32, riscV, stm32 series and others. It *doesn't work* on 8-bit microcontrollers like a classic Arduino as these microcontrollers are not powerful enough to run complicated crypto algorithms.\n\nWe use elliptic curve implementation from [trezor-crypto](https://github.com/trezor/trezor-firmware/tree/master/crypto). API is inspired by [Jimmy Song's](https://github.com/jimmysong/) Porgramming Blockchain class and the [book](https://github.com/jimmysong/programmingbitcoin).\n\n## Documentation\n\nCheck out our [tutorial](https://micro-bitcoin.github.io/#/tutorial/README) where we write a minimal hardware wallet, or browse the [API docs](https://micro-bitcoin.github.io/#/api/README). We also have a collection of [recepies](https://micro-bitcoin.github.io/#/recepies/README) for some common use-cases.\n\nTelegram group: https://t.me/arduinoBitcoin\n\n## Alternative libraries\n\n[DIY Bitcoin Hardware website](https://diybitcoinhardware.com/) has a nice collection of bitcoin-related projects, resources and libraries for makers.\n\nA few bitcoin libraries:\n\n- [secp256k1](https://github.com/bitcoin-core/secp256k1) — elliptic curve library  from Bitcoin Core and a [version](https://github.com/diybitcoinhardware/secp256k1-embedded) working with Arduino IDE & Mbed out of the box.\n- [libwally](https://github.com/ElementsProject/libwally-core/) - bitcoin library from Blockstream and a [version](https://github.com/diybitcoinhardware/libwally-embedded) working with Arduino IDE.\n- [f469-disco](https://github.com/diybitcoinhardware/f469-disco) - micropython bitcoin bundle for STM Discovery board and other platforms.\n\n## Installation\n\nThe library is [available](https://www.arduino.cc/reference/en/libraries/ubitcoin/) in the Arduino Library manager, or you can download and install it manually.\n\n[Download](https://github.com/micro-bitcoin/uBitcoin/archive/master.zip) the zip file from our [repository](https://github.com/micro-bitcoin/uBitcoin/) and select in Arduino IDE `Sketch` → `Include library` → `Add .ZIP library...`.\n\nOr clone it into your `Documents/Arduino/libraries` folder:\n\n```sh\ngit clone https://github.com/micro-bitcoin/uBitcoin.git\n```\n\nWhen installed you will also see a few examples in `File` → `Examples` → `Bitcoin` menu.\n\n## Basic usage example\n\nFirst, don't forget to include necessary headers:\n\n```cpp\n// we use these two in our sketch:\n#include \"Bitcoin.h\"\n#include \"PSBT.h\"       // if using PSBT functionality\n// other headers of the library\n#include \"Conversion.h\" // to get access to functions like toHex() or fromBase64()\n#include \"Hash.h\"       // if using hashes in your code\n```\n\nNow we can write a simple example that does the following:\n\n1. Creates a master private key from a recovery phrase and empty password\n2. Derives account and prints master public key for a watch-only wallet (`zpub` in this case)\n3. Derives and print first segwit address\n4. Parses, signs and prints signed PSBT transaction\n\n```cpp\n// derive master private key\nHDPrivateKey hd(\"add good charge eagle walk culture book inherit fan nature seek repair\", \"\");\n// derive native segwit account (bip-84) for tesnet\nHDPrivateKey account = hd.derive(\"m/84'/1'/0'/\");\n// print xpub: vpub5YkPqVJTA7gjK...AH2rXvcAe3p781G\nSerial.println(account.xpub());\n// or change the account type to UNKNOWN_TYPE to get tpub\nHDPublicKey xpub = account.xpub();\nxpub.type = UNKNOWN_TYPE;\n// this time prints tpubDCnYy4Ty...dL4fLKsBFjFQwz\nSerial.println(xpub);\n// set back correct type to get segwit addresses by default\nxpub.type = P2WPKH;\nSerial.println(hd.fingerprint());\n\n// print first address: tb1q6c8m3whsag5zadgl32nmhuf9q0qmtklws25n6g\nSerial.println(xpub.derive(\"m/0/0\").address());\n\nPSBT tx;\n// parse unsigned transaction\ntx.parseBase64(\"cHNidP8BAHECAAAAAUQS8FqBzYocPDpeQmXBRBH7NwZHVJF39dYJDCXxq\"\n\"zf6AAAAAAD+////AqCGAQAAAAAAFgAUuP0WcSBmiAZYi91nX90hg/cZJ1U8AgMAAAAAABYAF\"\n\"C1RhUR+m/nFyQkPSlP0xmZVxlOqAAAAAAABAR/gkwQAAAAAABYAFNYPuLrw6igutR+Kp7vxJ\"\n\"QPBtdvuIgYDzkBZaAkSIz0P0BexiPYfzInxu9mMeuaOQa1fGEUXcWIYoyAeuFQAAIABAACAA\"\n\"AAAgAAAAAAAAAAAAAAiAgMxjOiFQofq7l9q42nsLA3Ta4zKpEs5eCnAvMnQaVeqsBijIB64V\"\n\"AAAgAEAAIAAAACAAQAAAAAAAAAA\");\n// sign with the root key\ntx.sign(hd);\n// print signed transaction\nSerial.println(tx.toBase64());\n```\n\nReady for more? Check out the [tutorial](https://micro-bitcoin.github.io/#/tutorial/README) and start writing your very own hardware wallet!\n"
  },
  {
    "path": "examples/cpp/Makefile",
    "content": "TARGET ?= main\n\nifeq ($(OS),Windows_NT)\nEXT ?= .exe\nelse\nEXT ?= \nendif\n\nTARGET_EXEC ?= $(TARGET)$(EXT)\n\n# Paths\n# to make sure addprefix to LIB_DIR doesn't go out from build directory\nBUILD_DIR = build\nSRC_DIR = .\n# uBitcoin library\nLIB_DIR = ../../src\n\n# Tools\nifeq ($(OS),Windows_NT)\nTOOLCHAIN_PREFIX ?= x86_64-w64-mingw32-\nMKDIR_P = mkdir\nRM_R = rmdir /s /q\nelse\nTOOLCHAIN_PREFIX ?= \nMKDIR_P = mkdir -p\nRM_R = rm -r\nendif\n\n# compilers\nCC := $(TOOLCHAIN_PREFIX)gcc\nCXX := $(TOOLCHAIN_PREFIX)g++\n\n# main.cpp\nCXX_SOURCES = $(wildcard $(SRC_DIR)/*.cpp)\nC_SOURCES =\n\n# uBitcoin sources\nCXX_SOURCES += $(wildcard $(LIB_DIR)/*.cpp)\nC_SOURCES += $(wildcard $(LIB_DIR)/utility/trezor/*.c) \\\n\t\t\t$(wildcard $(LIB_DIR)/utility/*.c) \\\n\t\t\t$(wildcard $(LIB_DIR)/*.c)\n\n# include lib path, don't use mbed or arduino config (-DUSE_STDONLY), debug symbols, all warnings as errors\nFLAGS = -I$(LIB_DIR) -g -Wall -Werror -ldl\nCFLAGS = $(FLAGS)\nCPPFLAGS = $(FLAGS) -DUSE_STDONLY -DUBTC_EXAMPLE\n\nOBJS = $(patsubst $(SRC_DIR)/%, $(BUILD_DIR)/src/%.o, \\\n\t\t$(patsubst $(LIB_DIR)/%, $(BUILD_DIR)/lib/%.o, \\\n\t\t$(C_SOURCES) $(CXX_SOURCES)))\n\nvpath %.cpp $(SRC_DIR)\nvpath %.cpp $(LIB_DIR)\nvpath %.c $(LIB_DIR)\n\n.PHONY: clean all run\n\nall: $(BUILD_DIR)/$(TARGET_EXEC)\n\nrun: $(BUILD_DIR)/$(TARGET_EXEC)\n\t$(BUILD_DIR)/$(TARGET_EXEC)\n\n$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)\n\t$(CXX) $(OBJS) $(CPPFLAGS) -o $@\n\n# lib c sources\n$(BUILD_DIR)/lib/%.c.o: %.c\n\t$(MKDIR_P) $(dir $@)\n\t$(CC) -c $(CFLAGS) $< -o $@\n\n# lib cpp sources\n$(BUILD_DIR)/lib/%.cpp.o: %.cpp\n\t$(MKDIR_P) $(dir $@)\n\t$(CXX) -c $(CPPFLAGS) $< -o $@\n\n# cpp sources\n$(BUILD_DIR)/src/%.cpp.o: %.cpp\n\t$(MKDIR_P) $(dir $@)\n\t$(CXX) -c $(CPPFLAGS) $< -o $@\n\nclean:\n\t$(RM_R) $(BUILD_DIR)\n"
  },
  {
    "path": "examples/cpp/README.md",
    "content": "# C++ example\n\nrun with `make run`\n"
  },
  {
    "path": "examples/cpp/main.cpp",
    "content": "/*\n * A simple example showing how to work with uBitcoin in c++ on a PC\n */\n\n// only compile when UBTC_EXAMPLE flag is provided\n// to not clash with platformio's compile-everything approach\n#ifdef UBTC_EXAMPLE\n\n#include <iostream>\n#include \"Bitcoin.h\"\n#include \"PSBT.h\"\n\n#include <stdint.h>\n#include <stdlib.h>\n\n// You can define your random function to improve side-channel resistance\nextern \"C\" {\n\n    // use system random function\n    uint32_t random32(void){\n        return (uint32_t)rand();\n    }\n\n}\n\nusing namespace std;\n\nchar mnemonic[] = \"flight canvas heart purse potato mixed offer tooth maple blue kitten salute almost staff physical remain coral clump midnight rotate innocent shield inch ski\";\n\nint main() {\n    // convert mnemonic to xprv\n    cout << \"Your mnemonic: \" << endl << mnemonic << endl;\n    HDPrivateKey hd(mnemonic, \"\");\n    cout << \"Your xprv: \" << endl << string(hd) << endl;\n    // derive account xpub\n    char derivation[] = \"m/84h/1h/0h\";\n    HDPublicKey xpub = hd.derive(derivation).xpub();\n    // set network to regtest, otherwise default addresses will be for testnet\n    xpub.network = &Regtest;\n    cout << \"Account xpub at path \" << derivation << \":\" << endl;\n    cout << string(xpub) << endl;\n    // print first 5 receiving addresses\n    HDPublicKey recv_xpub = xpub.child(0);\n    for (uint32_t i = 0; i < 5; i++)\n    {\n        cout << \"Address #\" << i << \": \" << recv_xpub.child(i).address() << endl;\n    }\n\n    // signing PSBT transaction with 2 inputs\n    PSBT psbt;\n    psbt.parseBase64(string(\"cHNidP8BAJoCAAAAAqQW9JR6TFv46IXybtf9tKAy5WsYusr6O4rsfN8DIywEAQAAAAD9////9YKXV2aJad3wScN70cgZHMhQtwhTjw95loZfUB57+H4AAAAAAP3///8CwOHkAAAAAAAWABQzSSTq9G6AboazU3oS+BWVAw1zp21KTAAAAAAAFgAU2SSg4OQMonZrrLpdtTzcNes1MthDAQAAAAEAcQIAAAAB6GDWQUAnmq5s8Nm68qPp3fHnpARmx67Q5ZRHGj1rCjgBAAAAAP7///8CdIv2XwAAAAAWABRozVhYn14Pmv8XoAJePV7AQggf/4CWmAAAAAAAFgAUcOVKtnxrbE7ragGagzMqQ7kJsZkAAAAAAQEfgJaYAAAAAAAWABRw5Uq2fGtsTutqAZqDMypDuQmxmSIGA3s6OgE8GCKOcHDJe7XY0q/i/XSe6e933ErCDCCKR5WoGARkI4xUAACAAQAAgAAAAIAAAAAAAAAAAAABAHECAAAAAaH0XE8I0jQHvCDfdDTUbHrm9+oHbq1yt5ansxoaeeNjAQAAAAD+////AoCWmAAAAAAAFgAUQZD8n6hVi91tRSlWl4WkMwuBnoXsVTuMAAAAABYAFMbknFZNyqOzappeWfZi2+EP0asDAAAAAAEBH4CWmAAAAAAAFgAUQZD8n6hVi91tRSlWl4WkMwuBnoUiBgKNwymEX374HvJHU9FIT4YmCn8CuNteCOxtw7bJXGfscxgEZCOMVAAAgAEAAIAAAACAAAAAAAEAAAAAACICA9OwnpVPPgWAC/O7SuxHNPjX46Iz2Qv9dcI033AqEyv+GARkI4xUAACAAQAAgAAAAIABAAAAAAAAAAA=\"));\n    // check parsing is ok\n    if(!psbt){\n        cout << \"Failed parsing transaction\" << endl;\n        exit(EXIT_FAILURE);\n        return EXIT_FAILURE;\n    }\n    cout << \"Transactions details:\" << endl;\n    // going through all outputs\n    cout << \"Outputs:\" << endl;\n    for(unsigned int i = 0; i < psbt.tx.outputsNumber; i++){\n        // print addresses\n        cout << psbt.tx.txOuts[i].address(&Regtest);\n        if(psbt.txOutsMeta[i].derivationsLen > 0){ // there is derivation path\n            // considering only single key for simplicity\n            PSBTDerivation der = psbt.txOutsMeta[i].derivations[0];\n            HDPublicKey pub = hd.derive(der.derivation, der.derivationLen).xpub();\n            pub.network = &Regtest;\n            if(pub.address() == psbt.tx.txOuts[i].address(&Regtest)){\n                cout << \" (change) \";\n            }\n        }\n        cout << \" -> \" << psbt.tx.txOuts[i].btcAmount()*1e3 << \" mBTC\" << endl;\n    }\n    cout << \"Fee: \" << psbt.fee() << \" sat\" << endl;\n\n    // sign using our key\n    psbt.sign(hd);\n    cout << \"Signed transaction:\" << endl << psbt.toBase64() << endl; // now you can combine and finalize PSBTs in Bitcoin Core\n\n    return 0;\n}\n\n#endif // UBTC_EXAMPLE\n"
  },
  {
    "path": "examples/ecdh/ecdh.ino",
    "content": "/*\n * This example shows how to use ECDH algorithm\n * to get shared secret between two parties.\n * It is useful if you want to establish\n * secure communication with someone else.\n * You can use ECDH to create symmetric key\n * and then use AES in CBC mode to encrypt/decrypt data.\n */\n#include <Bitcoin.h>\n#include <Hash.h>\n\nvoid setup(){\n  Serial.begin(9600);\n  while(!Serial){\n    ; // wait for serial port to open\n  }\n  // generate random private keys and corresponding pubkeys\n  byte secret1[32];\n  byte secret2[32];\n  for(int i=0; i<sizeof(secret1); i++){\n    secret1[i] = random(256); // TODO: use good hardware randomness here!!!\n    secret2[i] = random(256);\n  }\n  PrivateKey pk1(secret1);\n  PrivateKey pk2(secret2);\n  PublicKey pub1 = pk1.publicKey();\n  PublicKey pub2 = pk2.publicKey();\n\n  // now each party does ecdh on it's private key with public key of the other party\n  // we calculate it twice here to make sure we get the same shared secret\n  byte shared_secret1[32];\n  byte shared_secret2[32];\n  // party 1 needs pubkey of party 2\n  pk1.ecdh(pub2, shared_secret1);\n  // party 2 needs pubkey of party 1\n  pk2.ecdh(pub1, shared_secret2);\n  // check they are the same\n  if(memcmp(shared_secret1, shared_secret2, 32)!=0){\n    Serial.println(\"Error in key negotiation! Something went wrong :(\");\n    return;\n  }\n  Serial.println(\"Key negotiation completed.\");\n  Serial.println(\"Symmetric key:\");\n  Serial.println(toHex(shared_secret1, sizeof(shared_secret1)));\n  // Makes sense to calculate human-readable fingerprint of the secret\n  // so user can check on both devices that it's the same - no man in the middle.\n  // It can be for example Base58(sha256(secret)[:6]) (6 bytes of sha256 of the secret)\n  byte h[32];\n  sha256(shared_secret1, 32, h);\n  String fingerprint = toBase58(h, 6);\n  Serial.print(\"Key fingerprint: \");\n  Serial.println(fingerprint);\n}\n\nvoid loop(){\n  delay(10);\n}\n"
  },
  {
    "path": "examples/hash/hash.ino",
    "content": "#include <Hash.h>  // all single-line hashing algorithms\n#include <Conversion.h> // to print byte arrays in hex format\n\nvoid setup() {\n  Serial.begin(9600);\n  while(!Serial){\n    ; // wait for serial port to open\n  }\n  String message = \"Hello world!\"; // message to hash\n  byte hash[64] = { 0 }; // hash\n  int hashLen = 0;\n\n  // sha-256\n  hashLen = sha256(message, hash);\n  Serial.println(\"SHA-256:   \" + toHex(hash, hashLen));\n  Serial.println(\"Should be: c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a\");\n\n  // you can also pass byte arrays to the hash function\n  // and update piece by piece\n  byte msg2[] = {1, 2, 3, 4, 5, 0xFA, 0xB0, 0x0B, 0x51};\n  // hash in one line\n  sha256(msg2, sizeof(msg2), hash);\n  // you can also create a class instance and use .write method\n  SHA256 h;\n  h.begin();\n  h.write(msg2, 5); // add first 5 bytes to hash\n  h.write(msg2+5, 4); // add another 4 bytes\n  h.end(hash); // result will be stored in the hash array\n\n  // ripemd-160\n  hashLen = rmd160(message, hash);\n  Serial.println(\"RMD-160:   \" + toHex(hash, hashLen));\n  Serial.println(\"Should be: 7f772647d88750add82d8e1a7a3e5c0902a346a3\");\n\n  // hash160(msg) = rmd160(sha256(message))\n  hashLen = hash160(message, hash);\n  Serial.println(\"Hash160:   \" + toHex(hash, hashLen));\n  Serial.println(\"Should be: 621281c15fb62d5c6013ea29007491e8b174e1b9\");\n\n  // sha256(sha256(message))\n  hashLen = doubleSha(message, hash);\n  Serial.println(\"DoubleSha: \" + toHex(hash, hashLen));\n  Serial.println(\"Should be: 7982970534e089b839957b7e174725ce1878731ed6d700766e59cb16f1c25e27\");\n\n  // sha512\n  hashLen = sha512(message, hash);\n  Serial.println(\"Sha512:    \" + toHex(hash, hashLen));\n  Serial.println(\"Should be: f6cde2a0f819314cdde55fc227d8d7dae3d28cc556222a0a8ad66d91ccad4aad6094f517a2182360c9aacf6a3dc323162cb6fd8cdffedb0fe038f55e85ffb5b6\");\n\n  // sha512-hmac\n  // here we use more c-style approach\n  char key[] = \"Bitcoin seed\";\n  hashLen = sha512Hmac((byte*)key, strlen(key), (byte*)message.c_str(), message.length(), hash);\n  Serial.println(\"Sha512-HMAC: \" + toHex(hash, hashLen));\n  Serial.println(\"Should be:   f7fc496a2c17bd09a6328124dc6edebed987e7e93903deee0633a756f1ee81da0753334f6cfe226b5c712d893a68c547d3a5497cd73e1d010670c1e0e9d93a8a\");\n}\n\nvoid loop() {\n\n}\n"
  },
  {
    "path": "examples/mnemonic/mnemonic.ino",
    "content": "/*\n * This example shows how to derive master private key from the recovery seed\n * Generate a random recovery seed i.e. on https://iancoleman.io/bip39/\n * and check the master private key, account private key, account public key\n * and first address.\n */\n#include \"Bitcoin.h\"\n\nvoid printHD(String mnemonic, String password = \"\"){\n\n  HDPrivateKey hd(mnemonic, password);\n\n  if(!hd){ // check if it is valid\n    Serial.println(\"Invalid xpub\");\n    return;\n  }\n  Serial.println(\"Mnemonic:\");\n  Serial.println(mnemonic);\n  Serial.print(\"Password: \\\"\");\n  Serial.println(password+\"\\\"\");\n  Serial.println(\"Root private key:\");\n  Serial.println(hd);\n\n  Serial.println(\"bip84 master private key:\");\n  HDPrivateKey account = hd.derive(\"m/84'/0'/0'/\");\n  Serial.println(account);\n  \n  Serial.println(\"bip84 master public key:\");\n  Serial.println(account.xpub());\n  \n  Serial.println(\"first address:\");\n  Serial.println(account.derive(\"m/0/0/\").address());\n  \n  Serial.println(\"\\n\");\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  printHD(\"arch volcano urge cradle turn labor skin secret squeeze denial jacket vintage fix glad lemon\", \"my secret password\");\n\n  // entropy bytes to mnemonic\n  uint8_t arr[] = {'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'};\n  String mn = mnemonicFromEntropy(arr, sizeof(arr));\n  Serial.println(mn);\n  uint8_t out[16];\n  size_t len = mnemonicToEntropy(mn, out, sizeof(out));\n  Serial.println(toHex(out, len));\n\n}\n\nvoid loop() {\n  delay(100);\n}\n"
  },
  {
    "path": "examples/multisig/multisig.ino",
    "content": "/*\n * A simple example showing how to derive multisig addresses\n */\n\n#include \"Bitcoin.h\"\n\n// 2 of 3 multisig\n#define NUM_KEYS 3\n#define THRESHOLD 2\n\n// cosigners\nHDPublicKey xpubs[] = {\n    // [73c5da0a/48h/1h/0h/2h] abandon * 11 + about\n    HDPublicKey(\"Vpub5n95dMZrDHj6SeBgJ1oz4Fae2N2eJNuWK3VTKDb2dzGpMFLUHLmtyDfen7AaQxwQ5mZnMyXdVrkEaoMLVTH8FmVBRVWPGFYWhmtDUGehGmq\"),\n    // [fb7c1f11/48h/1h/0h/2h] ability * 11 + acid\n    HDPublicKey(\"Vpub5mpiGVPWYfDWqZAvCtJihfU559GdwhNC5gwCa9xjSBp4Bvr1DnqXYTtAogkjvWYN1LGTyKo5Yjhfz7mNAqVmw7KG66CM4mDd8vGH3zPQmBH\"),\n    // [47fc1ba1/48h/1h/0h/2h] able * 11 + acid\n    HDPublicKey(\"Vpub5nRyr5ptHEvisEDuWRMY3rgQ99B1CU21wfkuXEekTi8jCshCWseGqBWWZ8U3Wgv4jDj2fizxBNZmpFjo56Ffu49Efpu4vAj5XErHyBEQoN9\"),\n};\n\nvoid setup() {\n  Serial.begin();\n\n  // print first 5 addresses\n  for(int idx = 0; idx < 5; idx++){\n    // get derivation path\n    String derivation = String(\"m/0/\")+String(idx);\n    Serial.println(derivation);\n    // generate individual public keys and put them into array\n    PublicKey pubkeys[NUM_KEYS];\n    for(int i=0; i<NUM_KEYS; i++){\n      // it will automatically convert to pubkey\n      pubkeys[i] = xpubs[i].derive(derivation);\n    }\n\n    // create multisig witness script from pubkeys above \n    Script witness_script = sortedmulti(THRESHOLD, pubkeys, NUM_KEYS);\n    // native segwit script-pubkey from witness script\n    Script script_pubkey = wsh(witness_script);\n    // address on regtest\n    Serial.print(\"address \");\n    Serial.print(idx);\n    Serial.print(\": \");\n    Serial.println(script_pubkey.address(&Regtest));\n  }\n}\n\nvoid loop() {\n  // put your main code here, to run repeatedly:\n}\n"
  },
  {
    "path": "examples/psbt/psbt.ino",
    "content": "/*\n * This example shows how parse and sign PSBT transaction\n */\n\n#include \"Bitcoin.h\"\n#include \"PSBT.h\"\n\nHDPrivateKey hd(\"flight canvas heart purse potato mixed offer tooth maple blue kitten salute almost staff physical remain coral clump midnight rotate innocent shield inch ski\", \"\");\nPSBT psbt;\n\nvoid setup() {\n  Serial.begin(115200);\n  // 2-input psbt\n  psbt.parseBase64(\"cHNidP8BAJoCAAAAAqQW9JR6TFv46IXybtf9tKAy5WsYusr6O4rsfN8DIywEAQAAAAD9////9YKXV2aJad3wScN70cgZHMhQtwhTjw95loZfUB57+H4AAAAAAP3///8CwOHkAAAAAAAWABQzSSTq9G6AboazU3oS+BWVAw1zp21KTAAAAAAAFgAU2SSg4OQMonZrrLpdtTzcNes1MthDAQAAAAEAcQIAAAAB6GDWQUAnmq5s8Nm68qPp3fHnpARmx67Q5ZRHGj1rCjgBAAAAAP7///8CdIv2XwAAAAAWABRozVhYn14Pmv8XoAJePV7AQggf/4CWmAAAAAAAFgAUcOVKtnxrbE7ragGagzMqQ7kJsZkAAAAAAQEfgJaYAAAAAAAWABRw5Uq2fGtsTutqAZqDMypDuQmxmSIGA3s6OgE8GCKOcHDJe7XY0q/i/XSe6e933ErCDCCKR5WoGARkI4xUAACAAQAAgAAAAIAAAAAAAAAAAAABAHECAAAAAaH0XE8I0jQHvCDfdDTUbHrm9+oHbq1yt5ansxoaeeNjAQAAAAD+////AoCWmAAAAAAAFgAUQZD8n6hVi91tRSlWl4WkMwuBnoXsVTuMAAAAABYAFMbknFZNyqOzappeWfZi2+EP0asDAAAAAAEBH4CWmAAAAAAAFgAUQZD8n6hVi91tRSlWl4WkMwuBnoUiBgKNwymEX374HvJHU9FIT4YmCn8CuNteCOxtw7bJXGfscxgEZCOMVAAAgAEAAIAAAACAAAAAAAEAAAAAACICA9OwnpVPPgWAC/O7SuxHNPjX46Iz2Qv9dcI033AqEyv+GARkI4xUAACAAQAAgAAAAIABAAAAAAAAAAA=\");\n  // check parsing is ok\n  if(!psbt){\n    Serial.println(\"Failed parsing transaction\");\n    return;\n  }\n  Serial.println(\"Transactions details:\");\n  // going through all outputs to print info\n  Serial.println(\"Outputs:\");\n  for(int i=0; i<psbt.tx.outputsNumber; i++){\n    // print addresses\n    Serial.print(psbt.tx.txOuts[i].address(&Regtest));\n    if(psbt.txOutsMeta[i].derivationsLen > 0){ // there is derivation path\n      // considering only single key for simplicity\n      PSBTDerivation der = psbt.txOutsMeta[i].derivations[0];\n      HDPublicKey pub = hd.derive(der.derivation, der.derivationLen).xpub();\n      if(pub.address() == psbt.tx.txOuts[i].address()){\n        Serial.print(\" (change) \");\n      }\n    }\n    Serial.print(\" -> \");\n    Serial.print(psbt.tx.txOuts[i].btcAmount()*1e3);\n    Serial.println(\" mBTC\");\n  }\n  Serial.print(\"Fee: \");\n  Serial.print(float(psbt.fee())/100); // Arduino can't print 64-bit ints\n  Serial.println(\" bits\");\n  \n  psbt.sign(hd);\n  Serial.println(psbt.toBase64()); // now you can combine and finalize PSBTs in Bitcoin Core\n}\n\nvoid loop() {\n}\n"
  },
  {
    "path": "examples/schnorr/schnorr.ino",
    "content": "/*\n * A simple example showing how to work with uBitcoin in c++ on a PC\n */\n#include \"Bitcoin.h\"\n#include \"Hash.h\"\n\nchar mnemonic[] = \"flight canvas heart purse potato mixed offer tooth maple blue kitten salute almost staff physical remain coral clump midnight rotate innocent shield inch ski\";\n// convert mnemonic to xprv\nHDPrivateKey hd(mnemonic, \"\");\n\nvoid setup() {\n  Serial.begin(115200);\n\n  Serial.println(\"Your mnemonic: \");\n  Serial.println(mnemonic);\n\n  // derive private key you want to use for schnorr\n  PrivateKey prv = hd.derive(\"m/86h/0h/0h/0/1\");\n  // print corresponding public key - schnorr keys are x-only 32-byte keys\n  PublicKey pub = prv.publicKey();\n  Serial.print(\"Private key: \");\n  Serial.println(prv);\n  Serial.print(\"X-only public key: \");\n  Serial.println(pub.x());\n  // sign message\n  uint8_t msg[32];\n  sha256(\"hello world!\", msg);\n  // sign using Schnorr algorithm\n  SchnorrSignature sig = prv.schnorr_sign(msg);\n  // Unlike ECDSA, Schnorr signature is always 64-bytes long\n  Serial.println(\"Signature for message 'hello world!':\");\n  Serial.println(sig);\n  // verify signatures\n  if(pub.schnorr_verify(sig, msg)){\n    Serial.println(\"All good, signature is valid\");\n  }else{\n    Serial.println(\"Something is wrong! Signature is invalid.\");\n  }\n}\n\nvoid loop() {\n}\n"
  },
  {
    "path": "examples/tx/tx.ino",
    "content": "#include <Arduino.h>\n#include \"Bitcoin.h\"\n\nvoid setup() {\n  Serial.begin(9600);\n  while(!Serial){\n    ;\n  }\n\n  // Single private key for testnet\n  PrivateKey privateKey(\"cQwxqQwCwGoirnTkVnNt4XqJuEv24HYBvVWCTLtL5g1kx9Q1AEhE\");\n  Serial.println(privateKey.address());\n\n  TxIn txIn(\"fbeae5f43d76fc3035cb4190baaf8cc123dd04f11c98c8f19a8b12cb4ce90db0\", 0);\n\n  // addresses to send bitcoins\n  char destination[] = \"n3DN9cswq5jnXXUmLP3bXtR89yfDNWrie9\";\n  String change = privateKey.address();\n\n  // amounts to send\n  // unsigned long can store up to 4294967295 satoshi (42.9 BTC)\n  // for larger amounts use uint64_t\n  unsigned long availableAmount = 2000000; // 58 mBTC\n  unsigned long fee = 1500;\n  unsigned long sendAmount = 1000000; // 20 mBTC\n  unsigned long changeAmount = availableAmount - sendAmount - fee;\n\n  TxOut txOutDestination(sendAmount, destination);\n  TxOut txOutChange(changeAmount, change.c_str());\n\n  Serial.println(txOutDestination);\n\n  // constructing actual transaction\n  Tx tx;\n  tx.addInput(txIn);\n  tx.addOutput(txOutDestination);\n  tx.addOutput(txOutChange);\n  \n  // Printing transaction information\n  Serial.print(\"Tx length: \");\n  Serial.println(tx.length());\n\n  Serial.print(\"Version: \");\n  Serial.println(tx.version);\n  Serial.print(\"Inputs:  \");\n  Serial.println(tx.inputsNumber);\n  for(int i=0; i< tx.inputsNumber; i++){\n    TxIn txin = tx.txIns[i];\n    Serial.print(\"\\tHash:          \");\n    Serial.println(toHex(txin.hash, 32));\n    Serial.print(\"\\tOutput index:  \");\n    Serial.println(txin.outputIndex);\n    Serial.print(\"\\tScript length: \");\n    Serial.println(txin.scriptSig.length());\n    Serial.print(\"\\tScript:        \");\n    Serial.println(txin.scriptSig);\n    Serial.print(\"\\tSequence:      \");\n    Serial.println(txin.sequence);\n    if(tx.isSegwit()){\n      Serial.println(\"\\tSEGWIT!\");\n    }\n  }\n  Serial.print(\"Outputs: \");\n  Serial.println(tx.outputsNumber);\n\n  for(int i=0; i< tx.outputsNumber; i++){\n    Serial.print(tx.txOuts[i].address());\n    Serial.print(\": \");\n    Serial.print(((float)tx.txOuts[i].amount)/100000);\n    Serial.println(\" mBTC\");\n  }\n\n  Serial.println(\"Unsigned transaction:\");\n  Serial.println(tx);\n\n  // signing transaction\n  Serial.println(\"Signing transaction...\");\n  Signature sig = tx.signInput(0, privateKey);\n  Serial.println(sig);\n\n  Serial.println(\"Signed transaction:\");\n  Serial.println(tx);\n\n  Serial.println(\"Transaction id:\");\n  Serial.println(tx.txid());\n  \n  Serial.println(\"Done\");\n}\n\nvoid loop() {\n  // put your main code here, to run repeatedly:\n  delay(100);\n}\n"
  },
  {
    "path": "examples/xpubs/xpubs.ino",
    "content": "/*\n * This example shows how to derive bitcoin addresses from the master public key (bip32)\n * Enter account master public key to the serial console and get the addresses\n * Use this tool to check: https://iancoleman.io/bip39/\n */\n#include \"Bitcoin.h\"\n\nvoid printAddresses(String pub){\n\n  HDPublicKey hd(pub);\n\n  if(!hd){ // check if it is valid\n    Serial.println(\"Invalid xpub\");\n    return;\n  }\n\n  Serial.println(\"Master public key:\");\n  Serial.println(hd);\n  \n  Serial.println(\"First 5 receiving addresses:\");\n  for(int i=0; i<5; i++){\n    String path = String(\"m/0/\")+i;\n    Serial.print(\"Path:\");\n    Serial.println(path);\n    Serial.print(\"Address: \");\n    Serial.println(hd.derive(path).address());\n    // Serial.print(\"Legacy: \");\n    // Serial.println(hd.derive(path).legacyAddress());\n    // Serial.print(\"Nested segwit: \");\n    // Serial.println(hd.derive(path).nestedSegwitAddress());\n    // Serial.print(\"Native segwit: \");\n    // Serial.println(hd.derive(path).segwitAddress());\n  }\n  \n  Serial.println(\"\\n\");\n}\n\nvoid setup() {\n  Serial.begin(115200);\n  // bip 44\n  printAddresses(\"xpub6BoiLSuHTDytgQejDauyXkBqQ4xTw2tSFKgkHfmZky7jDQQecUKwbFocxZXSJMCSp8gFNBbD9Squ3etZbJkE2qQqVBrypLjWJaWUNmHh3LT\");\n  // bip 49\n  printAddresses(\"ypub6XMsccDqTfZCUz5m4VjbRLebnjFTLDpeKTgRJuUtAxkpQicB7p4ZwHdmimRuMTcunPfdpzgpVt7DCDKRRffsgmWavWLXccumbyYazC3wh5N\");\n  // bip 84\n  printAddresses(\"zpub6rcGDMmj82CUJT1uV2mCcsN4EPTgBnJjciDWpYv12yCAPi9TEG5KLPF5iPtqzL6hNmaa5ZGfhJCHctoex7cGgqVxsyWcCDUNUDhjaYRQXzV\");\n  Serial.println(\"Enter your master public key:\");\n}\n\nvoid loop() {\n  if(Serial.available()){\n    String pub = Serial.readStringUntil('\\n');\n    Serial.println(pub);\n    if(pub.length() > 0){\n      printAddresses(pub);\n    }\n  }\n  delay(100);\n}\n"
  },
  {
    "path": "keywords.txt",
    "content": "#######################################\n# Syntax Coloring Map\n#######################################\n\n#######################################\n# Hash.h Methods and Functions (KEYWORD2)\n#######################################\n\nrmd160\tKEYWORD2\nsha256\tKEYWORD2\nhash160\tKEYWORD2\ndoubleSha\tKEYWORD2\nsha512\tKEYWORD2\nsha512Hmac\tKEYWORD2\n\n#######################################\n# Datatypes and classes (KEYWORD1)\n#######################################\n\nBitcoin\tKEYWORD1\nHash\tKEYWORD1\nConversion\tKEYWORD1\nOpCodes\tKEYWORD1\n\nScalar\tKEYWORD1\nPoint\tKEYWORD1\nPrivateKey\tKEYWORD1\nPublicKey\tKEYWORD1\nHDPrivateKey\tKEYWORD1\nHDPublicKey\tKEYWORD1\nScript\tKEYWORD1\nSignature\tKEYWORD1\nSchnorrSignature\tKEYWORD1\nTx\tKEYWORD1\nTxIn\tKEYWORD1\nTxOut\tKEYWORD1\nElectrumTx\tKEYWORD1\nPSBT\tKEYWORD1\n\n#######################################\n# Methods and Functions (KEYWORD2)\n#######################################\n\nparse\tKEYWORD2\nparseHex\tKEYWORD2\nparseBase64\tKEYWORD2\ntoBase64\tKEYWORD2\nserialize\tKEYWORD2\nbin\tKEYWORD2\nder\tKEYWORD2\n\ntype\tKEYWORD2\nlength\tKEYWORD2\nscriptLength\tKEYWORD2\nserializeScript\tKEYWORD2\npush\tKEYWORD2\nscriptPubkey\tKEYWORD2\naddress\tKEYWORD2\n\npow\tKEYWORD2\nsign\tKEYWORD2\nschnorr_sign\tKEYWORD2\nverify\tKEYWORD2\nschnorr_verify\tKEYWORD2\nfromSeed\tKEYWORD2\nfromMnemonic\tKEYWORD2\nxpub\tKEYWORD2\nxprv\tKEYWORD2\nchild\tKEYWORD2\nhardenedChild\tKEYWORD2\nderive\tKEYWORD2\nlegacyAddress\tKEYWORD2\nsegwitAddress\tKEYWORD2\nnestedSegwitAddress\tKEYWORD2\nparse\tKEYWORD2\nfromWIF\tKEYWORD2\npublicKey\tKEYWORD2\nsec\tKEYWORD2\nfromHex\tKEYWORD2\ntoHex\tKEYWORD2\ntoString\tKEYWORD2\ngenerateMnemonic\tKEYWORD2\ncheckMnemonic\tKEYWORD2\n\nlittleEndianToInt\tKEYWORD2\nintToLittleEndian\tKEYWORD2\nbigEndianToInt\tKEYWORD2\nintToBigEndian\tKEYWORD2\n\nlenVarInt\tKEYWORD2\nreadVarInt\tKEYWORD2\nreadVarInt\tKEYWORD2\nwriteVarInt\tKEYWORD2\nwriteVarInt\tKEYWORD2\n\naddInput\tKEYWORD2\naddOutput\tKEYWORD2\nsignInput\tKEYWORD2\nsignSegwitInput\tKEYWORD2\nsigHash\tKEYWORD2\n\n######################################\n# Constants (LITERAL1)\n#######################################\n\nPRIME\tLITERAL1\n\nP2PKH\tLITERAL1\nP2SH\tLITERAL1\nP2WPKH\tLITERAL1\nP2WSH\tLITERAL1\nP2SH_P2WPKH\tLITERAL1\nP2SH_P2WSH\tLITERAL1\nSIGHASH_ALL\tLITERAL1\nSIGHASH_NONE\tLITERAL1\nSIGHASH_SINGLE\tLITERAL1\n\n######################################\n# Opcodes (LITERAL1)\n#######################################\n\nOP_0\tLITERAL1\nOP_PUSHDATA1\tLITERAL1\nOP_PUSHDATA2\tLITERAL1\nOP_PUSHDATA4\tLITERAL1\nOP_1NEGATE\tLITERAL1\nOP_RESERVED\tLITERAL1\nOP_1\tLITERAL1\nOP_2\tLITERAL1\nOP_3\tLITERAL1\nOP_4\tLITERAL1\nOP_5\tLITERAL1\nOP_6\tLITERAL1\nOP_7\tLITERAL1\nOP_8\tLITERAL1\nOP_9\tLITERAL1\nOP_10\tLITERAL1\nOP_11\tLITERAL1\nOP_12\tLITERAL1\nOP_13\tLITERAL1\nOP_14\tLITERAL1\nOP_15\tLITERAL1\nOP_16\tLITERAL1\nOP_NOP\tLITERAL1\nOP_VER\tLITERAL1\nOP_IF\tLITERAL1\nOP_NOTIF\tLITERAL1\nOP_VERIF\tLITERAL1\nOP_VERNOTIF\tLITERAL1\nOP_ELSE\tLITERAL1\nOP_ENDIF\tLITERAL1\nOP_VERIFY\tLITERAL1\nOP_RETURN\tLITERAL1\nOP_TOALTSTACK\tLITERAL1\nOP_FROMALTSTACK\tLITERAL1\nOP_2DROP\tLITERAL1\nOP_2DUP\tLITERAL1\nOP_3DUP\tLITERAL1\nOP_2OVER\tLITERAL1\nOP_2ROT\tLITERAL1\nOP_2SWAP\tLITERAL1\nOP_IFDUP\tLITERAL1\nOP_DEPTH\tLITERAL1\nOP_DROP\tLITERAL1\nOP_DUP\tLITERAL1\nOP_NIP\tLITERAL1\nOP_OVER\tLITERAL1\nOP_PICK\tLITERAL1\nOP_ROLL\tLITERAL1\nOP_ROT\tLITERAL1\nOP_SWAP\tLITERAL1\nOP_TUCK\tLITERAL1\nOP_CAT\tLITERAL1\nOP_SUBSTR\tLITERAL1\nOP_LEFT\tLITERAL1\nOP_RIGHT\tLITERAL1\nOP_SIZE\tLITERAL1\nOP_INVERT\tLITERAL1\nOP_AND\tLITERAL1\nOP_OR\tLITERAL1\nOP_XOR\tLITERAL1\nOP_EQUAL\tLITERAL1\nOP_EQUALVERIFY\tLITERAL1\nOP_RESERVED1\tLITERAL1\nOP_RESERVED2\tLITERAL1\nOP_1ADD\tLITERAL1\nOP_1SUB\tLITERAL1\nOP_2MUL\tLITERAL1\nOP_2DIV\tLITERAL1\nOP_NEGATE\tLITERAL1\nOP_ABS\tLITERAL1\nOP_NOT\tLITERAL1\nOP_0NOTEQUAL\tLITERAL1\nOP_ADD\tLITERAL1\nOP_SUB\tLITERAL1\nOP_MUL\tLITERAL1\nOP_DIV\tLITERAL1\nOP_MOD\tLITERAL1\nOP_LSHIFT\tLITERAL1\nOP_RSHIFT\tLITERAL1\nOP_BOOLAND\tLITERAL1\nOP_BOOLOR\tLITERAL1\nOP_NUMEQUAL\tLITERAL1\nOP_NUMEQUALVERIFY\tLITERAL1\nOP_NUMNOTEQUAL\tLITERAL1\nOP_LESSTHAN\tLITERAL1\nOP_GREATERTHAN\tLITERAL1\nOP_LESSTHANOREQUAL\tLITERAL1\nOP_GREATERTHANOREQUAL\tLITERAL1\nOP_MIN\tLITERAL1\nOP_MAX\tLITERAL1\nOP_WITHIN\tLITERAL1\nOP_RIPEMD160\tLITERAL1\nOP_SHA1\tLITERAL1\nOP_SHA256\tLITERAL1\nOP_HASH160\tLITERAL1\nOP_HASH256\tLITERAL1\nOP_CODESEPARATOR\tLITERAL1\nOP_CHECKSIG\tLITERAL1\nOP_CHECKSIGVERIFY\tLITERAL1\nOP_CHECKMULTISIG\tLITERAL1\nOP_CHECKMULTISIGVERIFY\tLITERAL1\nOP_NOP1\tLITERAL1\nOP_CHECKLOCKTIMEVERIFY\tLITERAL1\nOP_CHECKSEQUENCEVERIFY\tLITERAL1\nOP_NOP4\tLITERAL1\nOP_NOP5\tLITERAL1\nOP_NOP6\tLITERAL1\nOP_NOP7\tLITERAL1\nOP_NOP8\tLITERAL1\nOP_NOP9\tLITERAL1\nOP_NOP10\tLITERAL1\nOP_NULLDATA\tLITERAL1\nOP_PUBKEYHASH\tLITERAL1\nOP_PUBKEY\tLITERAL1\nOP_INVALIDOPCODE\tLITERAL1\n"
  },
  {
    "path": "library.json",
    "content": "{\n  \"name\": \"uBitcoin\",\n  \"version\": \"0.2.0\",\n  \"description\": \"Brings Bitcoin to embedded devices. Write your own hardware wallet, vending machine or any other bitcoin-powered device. Supports public and private keys, HD wallets, transactions and scripts. Everything required to start working with Bitcoin on microcontrollers.\",\n  \"keywords\": \"bitcoin, cryptography\",\n  \"repository\":\n  {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/micro-bitcoin/uBitcoin.git\"\n  },\n  \"authors\":\n  [\n    {\n      \"name\": \"Stepan Snigirev\",\n      \"email\": \"snigirev.stepan@gmail.com\",\n      \"url\": \"https://stepansnigirev.com\"\n    }\n  ],\n  \"license\": \"MIT\",\n  \"homepage\": \"https://micro-bitcoin.github.io\",\n  \"dependencies\": {\n  },\n  \"frameworks\": \"*\",\n  \"platforms\": \"*\"\n}\n"
  },
  {
    "path": "library.properties",
    "content": "name=uBitcoin\nversion=0.2.0\nauthor=Stepan Snigirev\nmaintainer=Stepan Snigirev <snigirev.stepan@gmail.com>\nsentence=Brings Bitcoin to embedded devices\nparagraph=Write your own hardware wallet, vending machine or any other bitcoin-powered device. Supports public and private keys, HD wallets, transactions and scripts. Everything required to start working with Bitcoin on microcontrollers.\ncategory=Data Processing\nurl=https://github.com/micro-bitcoin/uBitcoin\narchitectures=*\n"
  },
  {
    "path": "src/BaseClasses.cpp",
    "content": "#include \"uBitcoin_conf.h\"\n#include \"BaseClasses.h\"\n#include <cstdlib>\n\n#if USE_STD_STRING\nusing std::string;\n#define String string\n#endif\n\nsize_t SerializeStream::serialize(const Streamable * s, size_t offset){\n    return s->to_stream(this, offset);\n}\n\nsize_t ParseStream::parse(Streamable * s){\n    return s->from_stream(this);\n}\n/************ Parse Byte Stream Class ************/\n\nParseByteStream::ParseByteStream(const uint8_t * arr, size_t length, encoding_format f){\n    last = -1;\n    format = f;\n    cursor = 0;\n    len = (arr == NULL) ? 0 : length;\n    buf = arr;\n}\n// TODO: call prev constructor\nParseByteStream::ParseByteStream(const char * arr, encoding_format f){\n    last = -1;\n    format = f;\n    cursor = 0;\n    len = (arr == NULL) ? 0 : strlen(arr);\n    buf = (const uint8_t *) arr;\n}\nParseByteStream::~ParseByteStream(){\n    buf = NULL;\n}\nsize_t ParseByteStream::available(){\n    if(format == HEX_ENCODING){\n        return (len - cursor)/2;\n    }else{\n        return len-cursor;\n    }\n};\nint ParseByteStream::read(){\n    if(format == HEX_ENCODING){\n        if(cursor < len-1){\n            uint8_t c1 = hexToVal(buf[cursor]);\n            uint8_t c2 = hexToVal(buf[cursor+1]);\n            if(c1 < 0x10 && c2 < 0x10){\n                cursor +=2;\n                last = (c1<<4) + c2;\n                return last;\n            }\n        }\n    }else{\n        if(cursor < len){\n            uint8_t c = buf[cursor];\n            cursor ++;\n            last = c;\n            return c;\n        }\n    }\n    return -1;\n}\nint ParseByteStream::getLast(){\n    return last;\n}\nsize_t ParseByteStream::read(uint8_t *arr, size_t length){\n    size_t cc = 0;\n    while(cc<length){\n        int b = read();\n        if(b<0){\n            return cc;\n        }\n        arr[cc] = (uint8_t)b & 0xFF;\n        cc++;\n    }\n    return cc;\n}\n\n/************ Serialize Byte Stream Class ************/\n\nSerializeByteStream::SerializeByteStream(uint8_t * arr, size_t length, encoding_format f){\n    format = f; cursor = 0; buf = arr; len = length;\n    memset(arr, 0, length);\n}\n// TODO: should length be here? See above - we used strlen\nSerializeByteStream::SerializeByteStream(char * arr, size_t length, encoding_format f){\n    format = f; cursor = 0; buf = (uint8_t *)arr; len = length;\n    memset(arr, 0, length);\n};\nsize_t SerializeByteStream::available(){\n    size_t a = len-cursor;\n    if(format == HEX_ENCODING){\n        a = a/2;\n    }\n    return a;\n};\nsize_t SerializeByteStream::write(uint8_t b){\n    if(available() > 0){\n        if(format == HEX_ENCODING){\n            buf[cursor] = ((b >> 4) & 0x0F) + '0';\n            if(buf[cursor] > '9'){\n                    buf[cursor] += 'a'-'9'-1;\n            }\n            cursor++;\n            buf[cursor] = (b & 0x0F) + '0';\n            if(buf[cursor] > '9'){\n                    buf[cursor] += 'a'-'9'-1;\n            }\n            cursor++;\n        }else{\n            buf[cursor] = b;\n            cursor++;\n        }\n        return 1;\n    }\n    return 0;\n};\nsize_t SerializeByteStream::write(const uint8_t *arr, size_t length){\n    size_t l = 0;\n    while(available()>0 && l < length){\n        write(arr[l]);\n        l++;\n    }\n    return l;\n};\n\n/************ Readable Class ************/\n\n#ifdef ARDUINO\nsize_t Readable::printTo(Print& p) const{\n    size_t len = this->stringLength()+1;\n    char * arr = (char *)calloc(len, sizeof(char));\n    toString(arr, len);\n    p.print(arr);\n    free(arr);\n    return len-1;\n}\n#endif\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString Readable::toString() const{\n    size_t len = this->stringLength()+1;\n    char * arr = (char *)calloc(len, sizeof(char));\n    toString(arr, len);\n    String s = arr;\n    free(arr);\n    return s;\n};\n#endif\n\n/************ Streamable Class ************/\n\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString Streamable::serialize(size_t offset, size_t len) const{\n    if(len == 0){\n        len = (length()-offset);\n    }\n    char * arr = (char *)calloc(2*len+1, sizeof(char));\n    serialize(arr, 2*len, offset, HEX_ENCODING);\n    String s = arr;\n    free(arr);\n    return s;\n};\n#endif\n\nsize_t Streamable::serialize(uint8_t * arr, size_t len, size_t offset, encoding_format format) const{\n    SerializeByteStream s(arr, len, format);\n    return to_stream(&s, offset);\n}\n\n"
  },
  {
    "path": "src/BaseClasses.h",
    "content": "#ifndef __BITCOIN_BASE_CLASSES_H__\n#define __BITCOIN_BASE_CLASSES_H__\n\n#include \"uBitcoin_conf.h\"\n#include \"Conversion.h\"\n\n#include <stdint.h>\n#include <string.h>\n\nenum encoding_format{\n    RAW = 0,\n    HEX_ENCODING = 16\n    // TODO: would be nice to have base64 encoding here\n};\n\nenum parse_status{\n    PARSING_DONE = 0,\n    PARSING_INCOMPLETE = 1,\n    PARSING_FAILED = 2\n};\n// error codes struct / class?\n\nclass Streamable;\n\nclass ParseStream{\npublic:\n    virtual size_t available(){ return 0; };\n    virtual int read(){ return -1; };\n    virtual size_t read(uint8_t *arr, size_t length){ return 0; };\n    virtual int getLast(){ return -1; };\n    size_t parse(Streamable * s);\n};\n\n// TODO: skip leading non-hex if it's hex format\nclass ParseByteStream: public ParseStream{\nprivate:\n    const uint8_t * buf;\n    size_t cursor;\n    size_t len;\n    encoding_format format;\n    int last;\npublic:\n    ParseByteStream(const uint8_t * arr, size_t length, encoding_format f=RAW);\n    ParseByteStream(const char * arr, encoding_format f=HEX_ENCODING);\n    ~ParseByteStream();\n    size_t available();\n    int read();\n    size_t read(uint8_t *arr, size_t length);\n    virtual int getLast();\n};\n\nclass SerializeStream{\npublic:\n    virtual size_t available(){ return 0; };\n    virtual size_t write(uint8_t b){ return 0; };\n    virtual size_t write(const uint8_t *arr, size_t len){ return 0; };\n    size_t serialize(const Streamable * s, size_t offset);\n};\n\nclass SerializeByteStream: public SerializeStream{\nprivate:\n    uint8_t * buf;\n    size_t cursor;\n    size_t len;\n    encoding_format format;\npublic:\n    SerializeByteStream(uint8_t * arr, size_t length, encoding_format f=RAW);\n    explicit SerializeByteStream(char * arr, size_t length, encoding_format f=HEX_ENCODING);\n    size_t available();\n    size_t write(uint8_t b);\n    size_t write(const uint8_t *arr, size_t length);\n};\n\n/** Abstract Readable class that can be encoded as a string and displayed to the user\n *  Can be converted to and from a string (char *, Arduino String and std::string)\n *  In Arduino it can be directly printed to the serial port, display or other Print device\n */\n#ifdef ARDUINO\nclass Readable: public Printable{\n#else\nclass Readable{\n#endif\nprivate:\nprotected:\n    /* override these functions in your class */\n    virtual size_t to_str(char * buf, size_t len) const = 0;\n    virtual size_t from_str(const char * buf, size_t len) = 0;\npublic:\n    /* override these function in your class */\n    virtual size_t stringLength() const = 0;\n\n    size_t toString(char * buf, size_t len) const{ return this->to_str(buf, len); };\n    size_t fromString(const char * buf, size_t len){ return this->from_str(buf, len); };\n    size_t fromString(const char * buf){ return this->from_str(buf, strlen(buf)); };\n#ifdef ARDUINO\n    size_t printTo(Print& p) const;\n#endif\n#if USE_ARDUINO_STRING\n    String toString() const;\n    operator String(){ return this->toString(); };\n#endif\n#if USE_STD_STRING\n    std::string toString() const;\n    operator std::string(){ return this->toString(); };\n#endif\n};\n\n/** Abstract Streamable class that can be serialized to/from a sequence of bytes\n *  and sent to Stream (File, Serial, Bluetooth) without allocating extra memory\n *  Class can be parsed and serialized in raw and hex formats\n */\nclass Streamable: public Readable{\n    friend class SerializeStream;\n    friend class ParseStream;\nprivate:\nprotected:\n    virtual size_t from_stream(ParseStream *s) = 0;\n    virtual size_t to_stream(SerializeStream *s, size_t offset) const = 0;\n    virtual size_t to_str(char * buf, size_t len) const{\n        return serialize(buf, len);\n    }\n    virtual size_t from_str(const char * buf, size_t len){\n        return parse(buf, len);\n    }\n    parse_status status;\n    size_t bytes_parsed;\npublic:\n    Streamable() { status = PARSING_DONE; bytes_parsed = 0; };\n    virtual void reset(){ status = PARSING_DONE; bytes_parsed = 0; }; // used to reset parsing and mb object\n    virtual size_t length() const = 0;\n    virtual size_t stringLength() const{ return 2*length(); };\n    /** \\brief Gets parsing status. \n     *         PARSING_DONE - everything is ok, \n     *         PARSING_INCOMPLETE - some data is still missing\n     *         PARSING_FAILED - something went wrong, the data is probably incorrect.\n     */\n    parse_status getStatus(){ return status; };\n    /** \\brief Sets parsing status. Should be used with care. */\n    void setStatus(parse_status s){ status = s; };\n    size_t parse(const uint8_t * arr, size_t len, encoding_format format=RAW){\n        ParseByteStream s(arr, len, format);\n        return from_stream(&s);\n    }\n#if USE_ARDUINO_STRING\n    size_t parse(String arr, encoding_format format=HEX_ENCODING){\n        return parse(arr.c_str(), strlen(arr.c_str()), format);\n    }\n#endif\n#if USE_STD_STRING\n    size_t parse(std::string arr, encoding_format format=HEX_ENCODING){\n        return parse(arr.c_str(), strlen(arr.c_str()), format);\n    }\n#endif\n#if !(USE_ARDUINO_STRING  || USE_STD_STRING)\n    size_t parse(const char * arr, encoding_format format=HEX_ENCODING){\n        return parse(arr, strlen(arr), format);\n    }\n#endif\n    size_t serialize(uint8_t * arr, size_t len, size_t offset = 0, encoding_format format=RAW) const;\n    size_t parse(const char * arr, size_t len, encoding_format format=HEX_ENCODING){\n        return parse((const uint8_t *) arr, len, format);\n    }\n    size_t serialize(char * arr, size_t len, size_t offset = 0, encoding_format format=HEX_ENCODING) const{\n        return serialize((uint8_t *)arr, len, offset, format);\n    }\n#if USE_ARDUINO_STRING\n    String serialize(size_t offset=0, size_t len=0) const;\n#endif\n#if USE_STD_STRING\n    std::string serialize(size_t offset=0, size_t len=0) const;\n    std::string serialize(int offset, int len) const{\n        return serialize((size_t)offset, (size_t)len);\n    };\n    std::string serialize(size_t offset, int len) const{\n        return serialize((size_t)offset, (size_t)len);\n    };\n#endif\n};\n\n#endif // __BITCOIN_BASE_CLASSES_H__\n"
  },
  {
    "path": "src/Bitcoin.cpp",
    "content": "#include \"Bitcoin.h\"\n#include \"Hash.h\"\n#include \"Conversion.h\"\n\n#include <stdint.h>\n#include <string.h>\n#include \"utility/trezor/sha2.h\"\n#include \"utility/trezor/rfc6979.h\"\n#include \"utility/trezor/ecdsa.h\"\n#include \"utility/trezor/secp256k1.h\"\n#include \"utility/segwit_addr.h\"\n#include \"utility/trezor/bip39.h\"\n#include \"utility/trezor/memzero.h\"\n\n#if USE_STD_STRING\nusing std::string;\n#define String std::string\n#endif\n\n// error code when parsing fails\nint ubtc_errno = 0;\n\nconst char * generateMnemonic(uint8_t numWords){\n    if(numWords<12 || numWords > 24 || numWords % 3 != 0){\n        return NULL;\n    }\n    int strength = numWords*32/3;\n    return mnemonic_generate(strength);\n}\nconst char * generateMnemonic(uint8_t numWords, const uint8_t * entropy_data, size_t dataLen){\n    if(numWords<12 || numWords > 24 || numWords % 3 != 0){\n        return NULL;\n    }\n    uint8_t hash[32];\n    sha256(entropy_data, dataLen, hash);\n    size_t len = numWords*4/3;\n    return mnemonic_from_data(hash, len);\n}\n\nconst char * mnemonicFromEntropy(const uint8_t * entropy_data, size_t dataLen){\n    return mnemonic_from_data(entropy_data, dataLen);\n}\nsize_t mnemonicToEntropy(const char * mnemonic, size_t mnemonicLen, uint8_t * output, size_t outputLen){\n    int num_words = 1;\n    for (size_t i = 0; i < strlen(mnemonic); i++){\n        if(mnemonic[i] == ' '){\n            num_words ++;\n        }\n    }\n    size_t entropy_len = (num_words*4)/3;\n    if(outputLen < entropy_len){\n        return 0;\n    }\n    uint8_t res[33] = {0};\n    int r = mnemonic_to_entropy(mnemonic, res);\n    if(r == 0){\n        return 0;\n    }\n    memcpy(output, res, entropy_len);\n    return entropy_len;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nsize_t mnemonicToEntropy(String mnemonic, uint8_t * output, size_t outputLen){\n    return mnemonicToEntropy(mnemonic.c_str(), mnemonic.length(), output, outputLen);\n}\n#else\nsize_t mnemonicToEntropy(char * mnemonic, uint8_t * output, size_t outputLen){\n    return mnemonicToEntropy(mnemonic, strlen(mnemonic), output, outputLen);\n}\n#endif\n\nconst char * generateMnemonic(const uint8_t * entropy_data, size_t dataLen){\n    return generateMnemonic(24, entropy_data, dataLen);\n}\n#if !(USE_ARDUINO_STRING || USE_STD_STRING)\nconst char * generateMnemonic(uint8_t numWords, const char * entropy_string){\n    return generateMnemonic(numWords, (uint8_t*)entropy_string, strlen(entropy_string));\n}\nconst char * generateMnemonic(const char * entropy_string){\n    return generateMnemonic(24, entropy_string);\n}\nbool checkMnemonic(const char * mnemonic){\n    return mnemonic_check(mnemonic);\n}\n#else\nconst char * generateMnemonic(uint8_t numWords, const String entropy_string){\n    return generateMnemonic(numWords, (uint8_t*)entropy_string.c_str(), strlen(entropy_string.c_str()));\n}\nconst char * generateMnemonic(const String entropy_string){\n    return generateMnemonic(24, entropy_string);\n}\nbool checkMnemonic(const String mnemonic){\n    return mnemonic_check(mnemonic.c_str());\n}\n#endif\n\n// ---------------------------------------------------------------- Signature class\n\nSignature::Signature(){\n    memzero(tot, 3); index = 0;\n    memzero(r, 32);\n    memzero(s, 32);\n}\nSignature::Signature(const uint8_t r_arr[32], const uint8_t s_arr[32]){\n    memzero(tot, 3); index = 0;\n    memcpy(r, r_arr, 32);\n    memcpy(s, s_arr, 32);\n}\nSignature::Signature(const uint8_t * der){\n    memzero(tot, 3); index = 0; memzero(r, 32); memzero(s, 32);\n    fromDer(der, der[1]+2);\n}\nSignature::Signature(const uint8_t * der, size_t derLen){\n    memzero(tot, 3); index = 0; memzero(r, 32); memzero(s, 32);\n    fromDer(der, derLen);\n}\nSignature::Signature(const char * der){\n    memzero(tot, 3); index = 0; memzero(r, 32); memzero(s, 32);\n    ParseByteStream s(der);\n    Signature::from_stream(&s);\n}\nsize_t Signature::from_stream(ParseStream *stream){\n    // der encoding is probably the most uneffective way to encode signatures...\n    // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S]\n    // * total-length: 1-byte length descriptor of everything that follows\n    // * R-length: 1-byte length descriptor of the R value that follows.\n    // * R: arbitrary-length big-endian encoded R value. It must use the shortest\n    //   possible encoding for a positive integers (which means no null bytes at\n    //   the start, except a single one when the next byte has its highest bit set).\n    // * S-length: 1-byte length descriptor of the S value that follows.\n    // * S: arbitrary-length big-endian encoded S value. The same rules apply.\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n        memzero(tot, 3);\n        memzero(r, 32);\n        memzero(s, 32);\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    uint8_t c = 0;\n    if(stream->available() && bytes_parsed+bytes_read < 1){\n        c = stream->read();\n        bytes_read++;\n        if(c!=0x30){\n            status = PARSING_FAILED;\n            return bytes_read;\n        }\n    }\n    if(stream->available() && bytes_parsed+bytes_read < 2){\n        tot[0] = stream->read();\n        bytes_read++;\n        if(tot[0] > 70){ status = PARSING_FAILED; return bytes_read; }\n    }\n    // r\n    if(stream->available() && bytes_parsed+bytes_read < 3){\n        c = stream->read();\n        bytes_read++;\n        if(c != 0x02){ status = PARSING_FAILED; return bytes_read; }\n    }\n    if(stream->available() && bytes_parsed+bytes_read < 4){\n        tot[1] = stream->read();\n        bytes_read++;\n        if(tot[1] > 33){ status = PARSING_FAILED; return bytes_read; }\n    }\n    if(stream->available() && tot[1]==33 && bytes_parsed+bytes_read < 5){\n        c = stream->read();\n        bytes_read++;\n        if(c != 0){ status = PARSING_FAILED; return bytes_read; }\n    }\n    while(stream->available() && bytes_parsed+bytes_read < (size_t)4+tot[1]){\n        r[bytes_parsed+bytes_read-4+32-tot[1]] = stream->read();\n        bytes_read++;\n    }\n    if(rlen() != tot[1]){ status = PARSING_FAILED; return bytes_read; }\n    // s\n    if(stream->available() && bytes_parsed+bytes_read < (size_t)4+tot[1]+1){\n        c = stream->read();\n        bytes_read++;\n        if(c != 0x02){ status = PARSING_FAILED; return bytes_read; }\n    }\n    if(stream->available() && bytes_parsed+bytes_read < (size_t)4+tot[1]+2){\n        tot[2] = stream->read();\n        bytes_read++;\n        if(tot[2] > 33){ status = PARSING_FAILED; return bytes_read; }\n    }\n    if(stream->available() && tot[2]==33 && bytes_parsed+bytes_read < (size_t)4+tot[1]+3){\n        c = stream->read();\n        bytes_read++;\n        if(c != 0){ status = PARSING_FAILED; return bytes_read; }\n    }\n    while(stream->available() && bytes_parsed+bytes_read < (size_t)4+tot[1]+2+tot[2]){\n        s[bytes_parsed+bytes_read-4-tot[1]-2-tot[2]+32] = stream->read();\n        bytes_read++;\n    }\n    if(slen() != tot[2]){ status = PARSING_FAILED; return bytes_read; }\n    if(bytes_parsed+bytes_read == (size_t)4+tot[1]+2+tot[2]){\n        status = PARSING_DONE;\n    }\n    bytes_parsed+=bytes_read;\n    return bytes_read;\n}\n\nsize_t Signature::to_stream(SerializeStream *stream, size_t offset) const{\n    uint8_t arr[72];\n    der(arr, sizeof(arr));\n    size_t l = Signature::length();\n    size_t bytes_written = 0;\n    while(stream->available() && offset+bytes_written < l){\n        stream->write(arr[offset+bytes_written]);\n        bytes_written++;\n    }\n    return bytes_written;\n}\n\nsize_t Signature::rlen() const{\n    uint8_t len = 33;\n    for(int i=0; i<32; i++){\n        if(r[i] > 0){\n            if(r[i] < 0x80){\n                len --;\n            }\n            break;\n        }else{\n            len--;\n        }\n    }\n    return len;\n}\nsize_t Signature::slen() const{\n    uint8_t len = 33;\n    for(int i=0; i<32; i++){\n        if(s[i] > 0){\n            if(s[i] < 0x80){\n                len --;\n            }\n            break;\n        }else{\n            len--;\n        }\n    }\n    return len;\n}\nsize_t Signature::length() const{\n    return rlen()+slen()+6;\n}\n\nsize_t Signature::fromDer(const uint8_t * raw, size_t rawLen){\n    ParseByteStream stream(raw, rawLen);\n    return Signature::from_stream(&stream);\n}\nsize_t Signature::der(uint8_t * bytes, size_t len) const{\n    memzero(bytes, len);\n    uint8_t _rlen = rlen();\n    uint8_t _slen = slen();\n    bytes[0] = 0x30;\n    bytes[1] = 4+_rlen+2+_slen-2;\n    bytes[2] = 0x02;\n    bytes[3] = _rlen;\n    if(_rlen == 33){\n        memcpy(bytes+5, r, 32);\n    }else{\n        memcpy(bytes+4, r+32-_rlen, _rlen);\n    }\n\n    bytes[4+_rlen] = 0x02;\n    bytes[4+_rlen+1] = _slen;\n    if(_slen == 33){\n        memcpy(bytes+4+_rlen+3, s, 32);\n    }else{\n        memcpy(bytes+4+_rlen+2, s+32-_slen, _slen);\n    }\n    return 4+_rlen+2+_slen;\n}\nvoid Signature::bin(uint8_t * arr, size_t len) const{\n    size_t l = len;\n    if(l > 32){\n        l = 32;\n    }\n    memcpy(arr, r, l);\n    if(len > 32){\n        l = len-32;\n        if(l > 32){\n            l = 32;\n        }\n        memcpy(arr+32, s, l);\n    }\n    if(len > 64){\n        arr[64] = index;\n    }\n}\nvoid Signature::fromBin(const uint8_t * arr, size_t len){\n    size_t l = len;\n    if(l > 32){\n        l = 32;\n    }\n    memcpy(r, arr, l);\n    if(len > 32){\n        l = len-32;\n        if(l > 32){\n            l = 32;\n        }\n        memcpy(s, arr+32, l);\n    }\n    if(len > 64){\n        index = arr[64];\n    }\n}\n\n// ---------------------------------------------------------------- SchnorrSignature\n\nSchnorrSignature::SchnorrSignature(){\n    memzero(r, 32);\n    memzero(s, 32);\n}\nSchnorrSignature::SchnorrSignature(const uint8_t r_arr[32], const uint8_t s_arr[32]){\n    memcpy(r, r_arr, 32);\n    memcpy(s, s_arr, 32);\n}\nSchnorrSignature::SchnorrSignature(const uint8_t rs_arr[64]){\n    memcpy(r, rs_arr, 32);\n    memcpy(s, rs_arr+32, 32);\n}\nSchnorrSignature::SchnorrSignature(const char * rs){\n    memzero(r, 32); memzero(s, 32);\n    ParseByteStream s(rs);\n    SchnorrSignature::from_stream(&s);\n}\nsize_t SchnorrSignature::from_stream(ParseStream *stream){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n        memzero(r, 32);\n        memzero(s, 32);\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    while(stream->available() && bytes_parsed+bytes_read < 32){\n        r[bytes_read+bytes_parsed] = stream->read();\n        bytes_read++;\n    }\n    while(stream->available() && bytes_parsed+bytes_read < 64){\n        s[bytes_read+bytes_parsed-32] = stream->read();\n        bytes_read++;\n    }\n    if(bytes_parsed+bytes_read == 64){\n        status = PARSING_DONE;\n    }\n    bytes_parsed+=bytes_read;\n    return bytes_read;\n}\n\nsize_t SchnorrSignature::to_stream(SerializeStream *stream, size_t offset) const{\n    uint8_t arr[64];\n    memcpy(arr, r, 32);\n    memcpy(arr+32, s, 32);\n    size_t l = sizeof(arr);\n    size_t bytes_written = 0;\n    while(stream->available() && offset+bytes_written < l){\n        stream->write(arr[offset+bytes_written]);\n        bytes_written++;\n    }\n    return bytes_written;\n}\n\n// ---------------------------------------------------------------- PublicKey class\n\nint PublicKey::legacyAddress(char * address, size_t len, const Network * network) const{\n    memzero(address, len);\n\n    uint8_t buffer[20];\n    uint8_t sec_arr[65] = { 0 };\n    int l = sec(sec_arr, sizeof(sec_arr));\n    hash160(sec_arr, l, buffer);\n\n    uint8_t addr[21];\n    addr[0] = network->p2pkh;\n    memcpy(addr+1, buffer, 20);\n\n    return toBase58Check(addr, 21, address, len);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString PublicKey::legacyAddress(const Network * network) const{\n    char addr[40] = { 0 };\n    legacyAddress(addr, sizeof(addr), network);\n    return String(addr);\n}\n#endif\nint PublicKey::segwitAddress(char address[], size_t len, const Network * network) const{\n    memzero(address, len);\n    if(len < 76){ // TODO: 76 is too much for native segwit\n        return 0;\n    }\n    uint8_t hash[20];\n    uint8_t sec_arr[65] = { 0 };\n    int l = sec(sec_arr, sizeof(sec_arr));\n    hash160(sec_arr, l, hash);\n    segwit_addr_encode(address, network->bech32, 0, hash, 20);\n    return 76;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString PublicKey::segwitAddress(const Network * network) const{\n    char addr[76] = { 0 };\n    segwitAddress(addr, sizeof(addr), network);\n    return String(addr);\n}\n#endif\nint PublicKey::nestedSegwitAddress(char address[], size_t len, const Network * network) const{\n    memzero(address, len);\n    uint8_t script[22] = { 0 };\n    // script[0] = 0x00; // no need to set - already zero\n    script[1] = 0x14;\n    uint8_t sec_arr[65] = { 0 };\n    int l = sec(sec_arr, sizeof(sec_arr));\n    hash160(sec_arr, l, script+2);\n\n    uint8_t addr[21];\n    addr[0] = network->p2sh;\n    hash160(script, 22, addr+1);\n\n    return toBase58Check(addr, 21, address, len);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString PublicKey::nestedSegwitAddress(const Network * network) const{\n    char addr[40] = { 0 };\n    nestedSegwitAddress(addr, sizeof(addr), network);\n    return String(addr);\n}\n#endif\nScript PublicKey::script(ScriptType type) const{\n    return Script(*this, type);\n}\nbool PublicKey::verify(const Signature sig, const uint8_t hash[32]) const{\n    uint8_t signature[64] = {0};\n    sig.bin(signature, 64);\n    uint8_t pub[65];\n    serialize(pub, 65);\n    return (ecdsa_verify_digest(&secp256k1, pub, signature, hash)==0);\n}\nbool PublicKey::schnorr_verify(const SchnorrSignature sig, const uint8_t hash[32]) const{\n    PublicKey pub = *this;\n    if(!pub.isEven()){\n        pub = -pub;\n    }\n    uint8_t rs[64];\n    sig.serialize(rs, sizeof(rs));\n    PublicKey R;\n    R.from_x(rs, 32);\n    // calculate hash using tagged hash with \"BIP0340/challenge\" prefix\n    uint8_t e[32];\n    uint8_t tmp[32];\n    TaggedHash tch(\"BIP0340/challenge\");\n    // write R\n    tch.write(rs, 32);\n    // write xonly pubkey\n    pub.x(tmp, sizeof(tmp));\n    tch.write(tmp, sizeof(tmp));\n    // write message\n    tch.write(hash, 32);\n    tch.end(e);\n    PrivateKey challenge(e);\n    PublicKey S = challenge*pub + R;\n    S.x(tmp, sizeof(tmp));\n    PrivateKey s(rs+32);\n    s.publicKey().x(e, 32);\n    return memcmp(tmp, e, 32) == 0;\n};\n\n// ---------------------------------------------------------------- PrivateKey class\n\nsize_t PrivateKey::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    while(s->available() > 0 && bytes_parsed+bytes_read < 32){\n        num[bytes_parsed+bytes_read] = s->read();\n        bytes_read++;\n    }\n    if(bytes_parsed+bytes_read == 32){\n        status = PARSING_DONE;\n        uint8_t zero[32] = { 0 };\n        if(memcmp(num, zero, 32)==0){ // should we add something else here?\n            status = PARSING_FAILED;\n        }\n        bignum256 n;\n        bn_read_be(num, &n);\n        bn_mod(&n, &secp256k1.order);\n        bn_write_be(&n, num);\n        pubKey = *this * GeneratorPoint;\n    }\n    bytes_parsed += bytes_read;\n    return bytes_read;\n}\nPrivateKey::PrivateKey(void){\n    reset();\n    memzero(num, 32); // empty key\n    network = &DEFAULT_NETWORK;\n}\nPrivateKey::PrivateKey(const uint8_t * secret_arr, bool use_compressed, const Network * net){\n    reset();\n    memcpy(num, secret_arr, 32);\n    network = net;\n    pubKey = *this * GeneratorPoint;\n    pubKey.compressed = use_compressed;\n}\nPrivateKey::PrivateKey(const ECScalar other){\n    reset();\n    other.getSecret(num);\n    pubKey = *this * GeneratorPoint;\n    pubKey.compressed = true;\n    network = &DEFAULT_NETWORK;\n}\n/*PrivateKey &PrivateKey::operator=(const PrivateKey &other){\n    if (this == &other){ return *this; } // self-assignment\n    reset();\n    other.getSecret(num);\n    network = other.network;\n    pubKey = *this * GeneratorPoint;\n    pubKey.compressed = other.pubKey.compressed;\n    return *this;\n};*/\nPrivateKey::~PrivateKey(void) {\n    reset();\n    // erase secret key from memory\n    memzero(num, 32);\n}\nint PrivateKey::wif(char * wifArr, size_t wifSize) const{\n    memzero(wifArr, wifSize);\n\n    uint8_t wifHex[34] = { 0 }; // prefix + 32 bytes secret (+ compressed )\n    size_t len = 33;\n    wifHex[0] = network->wif;\n    memcpy(wifHex+1, num, 32);\n    if(pubKey.compressed){\n        wifHex[33] = 0x01;\n        len++;\n    }\n    size_t l = toBase58Check(wifHex, len, wifArr, wifSize);\n\n    memzero(wifHex, sizeof(wifHex)); // secret should not stay in RAM\n    return l;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString PrivateKey::wif() const{\n    char wifString[53] = { 0 };\n    wif(wifString, sizeof(wifString));\n    return String(wifString);\n}\n#endif\nint PrivateKey::fromWIF(const char * wifArr, size_t wifSize){\n    uint8_t arr[40] = { 0 };\n    size_t l = fromBase58Check(wifArr, wifSize, arr, sizeof(arr));\n    if( (l < 33) || (l > 34) ){\n        memzero(num, 32);\n        return 0;\n    }\n    bool compressed;\n    network = &DEFAULT_NETWORK;\n    bool found = false;\n    for(int i=0; i<networks_len; i++){\n        if(arr[0] == networks[i]->wif){\n            network = networks[i];\n            found = true;\n            break;\n        }\n    }\n    if(!found){\n        return 0;\n    }\n\n    if(l == 34){\n        compressed = (arr[33] > 0);\n    }\n    if(l == 33){\n        compressed = false;\n    }\n    memcpy(num, arr+1, 32);\n    memzero(arr, 40); // clear memory\n\n    pubKey = *this * GeneratorPoint;\n    pubKey.compressed = compressed;\n    return 1;\n}\nint PrivateKey::fromWIF(const char * wifArr){\n    return fromWIF(wifArr, strlen(wifArr));\n}\n\nPublicKey PrivateKey::publicKey() const{\n    return pubKey;\n}\n\nint PrivateKey::address(char * address, size_t len) const{\n    return pubKey.address(address, len, network);\n}\nint PrivateKey::legacyAddress(char * address, size_t len) const{\n    return pubKey.legacyAddress(address, len, network);\n}\nint PrivateKey::segwitAddress(char * address, size_t len) const{\n    return pubKey.segwitAddress(address, len, network);\n}\nint PrivateKey::nestedSegwitAddress(char * address, size_t len) const{\n    return pubKey.nestedSegwitAddress(address, len, network);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString PrivateKey::address() const{\n    return pubKey.address(network);\n}\nString PrivateKey::legacyAddress() const{\n    return pubKey.legacyAddress(network);\n}\nString PrivateKey::segwitAddress() const{\n    return pubKey.segwitAddress(network);\n}\nString PrivateKey::nestedSegwitAddress() const{\n    return pubKey.nestedSegwitAddress(network);\n}\n#endif\n\nint PrivateKey::ecdh(const PublicKey pub, uint8_t shared_secret[32], bool use_hash){\n    // calculate pk * pub, serialize as uncompressed point and hash <x><y>\n    ECPoint mult = *this * pub;\n    mult.compressed = false;\n    uint8_t sec[65];\n    mult.sec(sec, sizeof(sec));\n    if(use_hash){\n        sha256(sec+1, 64, shared_secret);\n    }else{\n        // just copy x\n        memcpy(shared_secret, sec+1, 32);\n    }\n    return 1;\n}\n\nstatic int is_canonical(uint8_t by, uint8_t sig[64]){\n  return 1;\n}\n\nSignature PrivateKey::sign(const uint8_t hash[32]) const{\n    uint8_t signature[65] = {0};\n    uint8_t i = 0;\n    ecdsa_sign_digest(&secp256k1, num, hash, signature, &i, &is_canonical);\n    Signature sig(signature, signature+32);\n    sig.index = i;\n    return sig;\n}\n\nSchnorrSignature PrivateKey::schnorr_sign(const uint8_t hash[32]) const{\n    PrivateKey prv = *this;\n    PublicKey pub = prv.publicKey();\n    // check if pubkey is even, if not - negate\n    if(!pub.isEven()){\n        prv = -prv;\n        pub = -pub;\n    }\n    uint8_t r[32];\n    uint8_t s[32];\n    uint8_t tmp[32];\n    // generate k using tagged hash with \"BIP0340/nonce\" prefix\n    uint8_t nonce[32];\n    TaggedHash tnonce(\"BIP0340/nonce\");\n    prv.getSecret(tmp);\n    tnonce.write(tmp, sizeof(tmp));\n    pub.x(tmp, sizeof(tmp));\n    tnonce.write(tmp, sizeof(tmp));\n    tnonce.write(hash, 32);\n    tnonce.end(nonce);\n    PrivateKey k(nonce);\n    PublicKey R = k.publicKey();\n    // flip k if r is not even\n    if(!R.isEven()){\n        k = -k;\n        R = -R;\n    }\n\n    // calculate hash using tagged hash with \"BIP0340/challenge\" prefix\n    uint8_t e[32];\n    TaggedHash tch(\"BIP0340/challenge\");\n    R.x(r, sizeof(r));\n    tch.write(r, sizeof(r));\n    pub.x(tmp, sizeof(tmp));\n    tch.write(tmp, sizeof(tmp));\n    tch.write(hash, 32);\n    tch.end(e);\n    PrivateKey challenge(e);\n    // calculate s\n    PrivateKey S = k + challenge*prv;\n    S.getSecret(s);\n\n    SchnorrSignature sig(r, s);\n    return sig;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nPrivateKey::PrivateKey(const String wifString){\n    fromWIF(wifString.c_str());\n}\n#else\nPrivateKey::PrivateKey(const char * wifArr){\n    fromWIF(wifArr);\n}\n#endif\n"
  },
  {
    "path": "src/Bitcoin.h",
    "content": "/** @file Bitcoin.h\n */\n\n#ifndef __BITCOIN_H__\n#define __BITCOIN_H__\n\n#include \"uBitcoin_conf.h\"\n#include \"BaseClasses.h\"\n#include \"BitcoinCurve.h\"\n#include \"Conversion.h\"\n#include \"Networks.h\"\n#include \"utility/trezor/rand.h\"\n#include <stdint.h>\n#include <string.h>\n\n/* TODO:\n   - autodetect mnemonic w/o passwd or xprv\n   - HD.derive()\n   - accept strings instead of char arrays for txout (address) and other things\n   - fail if script or witness is too large\n   - fix is_canonical function\n   - refactor fromWIF to return bytes read\n   - fix all warnings\n   - psbt\n   - docs\n   - publish on arduino libs and mbed\n   - operators +, += in script - concatenation\n   - signature & everything from char array might be not a bright idea\n   - tests (egde cases!)\n   - sidechannel for pubkey calculation - use rng\n */\n\nextern int ubtc_errno;\n\n// number of rounds for mnemonic to seed conversion\n#define PBKDF2_ROUNDS 2048\n#define HARDENED_INDEX 0x80000000\n\n/** \\brief Common script types */\nenum ScriptType{\n    UNKNOWN_TYPE,\n    /**  \\brief a script directly in ScriptPubkey and not one of below */\n    DIRECT_SCRIPT,\n    /**  \\brief default script for signing */\n    P2PKH,\n    P2SH,\n    P2WPKH,\n    P2WSH,\n    P2SH_P2WPKH,\n    P2SH_P2WSH,\n    MULTISIG\n};\n\n/** \\brief SigHash types */\nenum SigHashType{\n    SIGHASH_ALL = 1,\n    SIGHASH_NONE = 2,\n    SIGHASH_SINGLE = 3\n};\n\n/* forward declarations */\nclass Signature;\nclass SchnorrSignature;\nclass PublicKey;\nclass PrivateKey;\nclass HDPublicKey;\nclass HDPrivateKey;\nclass Script;\nclass TxIn;\n\nconst char * generateMnemonic(uint8_t numWords);\nconst char * generateMnemonic(uint8_t numWords, const uint8_t * entropy_data, size_t dataLen);\nconst char * generateMnemonic(const uint8_t * entropy_data, size_t dataLen);\n#if USE_ARDUINO_STRING\nconst char * generateMnemonic(uint8_t numWords, const String entropy_string);\nconst char * generateMnemonic(const String entropy_string);\nbool checkMnemonic(const String mnemonic);\n#elif USE_STD_STRING\nconst char * generateMnemonic(uint8_t numWords, const std::string entropy_string);\nconst char * generateMnemonic(const std::string entropy_string);\nbool checkMnemonic(const std::string mnemonic);\n#else\nconst char * generateMnemonic(uint8_t numWords, const char * entropy_string);\nconst char * generateMnemonic(const char * entropy_string);\nbool checkMnemonic(const char * mnemonic);\n#endif\n\nconst char * mnemonicFromEntropy(const uint8_t * entropy_data, size_t dataLen);\nsize_t mnemonicToEntropy(const char * mnemonic, size_t mnemonic_len, uint8_t * output, size_t outputLen);\n#if USE_ARDUINO_STRING\nsize_t mnemonicToEntropy(String mnemonic, uint8_t * output, size_t outputLen);\n#elif USE_STD_STRING\nsize_t mnemonicToEntropy(std::string mnemonic, uint8_t * output, size_t outputLen);\n#else\nsize_t mnemonicToEntropy(char * mnemonic, uint8_t * output, size_t outputLen);\n#endif\n\n/**\n *  PublicKey class.\n *\n *  Derived from ECPoint class, therefore you can add or substract them, multiply by ECScalar or PrivateKey.\n *\n *  `compressed` flag determines what public key sec format to use by default:\n *  - `compressed = false` will use 65-byte representation (`04<x><y>`)\n *  - `compressed = true` will use 33-byte representation (`03<x>` if y is odd, `02<x>` if y is even)\n */\nclass PublicKey : public ECPoint{\npublic:\n    PublicKey(){ reset(); };\n    PublicKey(const uint8_t pubkeyArr[64], bool use_compressed){ reset(); memcpy(point, pubkeyArr, 64); compressed=use_compressed; };\n    PublicKey(const uint8_t * secArr){ reset(); parse(secArr, 33 + ((uint8_t)(secArr[0]==0x04))*32); };\n    explicit PublicKey(const char * secHex){ reset(); from_str(secHex, strlen(secHex)); };\n    PublicKey(const ECPoint p){ reset(); memcpy(point, p.point, 64); compressed=p.compressed; };\n    /**\n     *  \\brief Fills `addr` with legacy Pay-To-Pubkey-Hash address (P2PKH, `1...` for mainnet)\n     */\n    int legacyAddress(char * addr, size_t len, const Network * network = &DEFAULT_NETWORK) const;\n    /**\n     *  \\brief Fills `addr` with native segwit address (P2WPKH, `bc1...` for mainnet)\n     */\n    int segwitAddress(char * addr, size_t len, const Network * network = &DEFAULT_NETWORK) const;\n    /**\n     *  \\brief Fills `addr` with nested segwit address (P2SH-P2WPKH, `3...` for mainnet)\n     */\n    int nestedSegwitAddress(char * addr, size_t len, const Network * network = &DEFAULT_NETWORK) const;\n    /**\n     *  \\brief Alias for `legacyAddress`\n     */\n    int address(char * address, size_t len, const Network * network = &DEFAULT_NETWORK) const{ return legacyAddress(address, len, network); };\n#if USE_ARDUINO_STRING\n    String legacyAddress(const Network * network = &DEFAULT_NETWORK) const;\n    String segwitAddress(const Network * network = &DEFAULT_NETWORK) const;\n    String nestedSegwitAddress(const Network * network = &DEFAULT_NETWORK) const;\n    String address(const Network * network = &DEFAULT_NETWORK) const{ return legacyAddress(network); };\n#endif\n#if USE_STD_STRING\n    std::string legacyAddress(const Network * network = &DEFAULT_NETWORK) const;\n    std::string segwitAddress(const Network * network = &DEFAULT_NETWORK) const;\n    std::string nestedSegwitAddress(const Network * network = &DEFAULT_NETWORK) const;\n    std::string address(const Network * network = &DEFAULT_NETWORK) const{ return legacyAddress(network); };\n#endif\n    /**\n     *  \\brief verifies the ECDSA signature of the hash of the message\n     */\n    bool verify(const Signature sig, const uint8_t hash[32]) const;\n    /**\n     *  \\brief verifies the Schnorr signature of the hash of the message\n     */\n    bool schnorr_verify(const SchnorrSignature sig, const uint8_t hash[32]) const;\n    /**\n     *  \\brief Returns a Script with the type: `P2PKH`, `P2WPKH` or `P2SH_P2WPKH`\n     */\n    Script script(ScriptType type = P2PKH) const;\n};\n\n/**\n *  PrivateKey class.\n *  Corresponding public key (point on curve) will be calculated in the constructor.\n *      as point calculation is pretty slow, class initialization can take some time.\n */\nclass PrivateKey : public ECScalar{\nprotected:\n    /** \\brief corresponding point on curve ( secret * G ) */\n    PublicKey pubKey;\n    virtual size_t to_str(char * buf, size_t len) const{ return wif( buf, len); };\n    virtual size_t from_str(const char * buf, size_t len){ return fromWIF(buf, len); };\n    virtual size_t from_stream(ParseStream *s);\npublic:\n    PrivateKey();\n    PrivateKey(const uint8_t secret_arr[32], bool use_compressed = true, const Network * net = &DEFAULT_NETWORK);\n    PrivateKey(const ECScalar sc);\n#if USE_ARDUINO_STRING\n    PrivateKey(const String wifString);\n#elif USE_STD_STRING\n    PrivateKey(const std::string wifString);\n#else\n    PrivateKey(const char * wifArr);\n#endif\n    ~PrivateKey();\n    /** \\brief Length of the key in WIF format (52). In reality not always 52... */\n    virtual size_t stringLength() const{ return 52; };\n    virtual size_t length() const{ return 32; };\n    void setSecret(const uint8_t secret_arr[32]){ memcpy(num, secret_arr, 32); pubKey = *this * GeneratorPoint; };\n\n    /** \\brief Pointer to the network to use. Mainnet or Testnet */\n    const Network * network;\n\n    /** \\brief Writes the private key in Wallet Import Format */\n    int wif(char * wifArr, size_t len) const;\n#if USE_ARDUINO_STRING\n    String wif() const;\n#endif\n#if USE_STD_STRING\n    std::string wif() const;\n#endif\n    /** \\brief Loads the private key from a string in Wallet Import Format */\n    int fromWIF(const char * wifArr, size_t wifSize);\n    int fromWIF(const char * wifArr);\n    /** \\brief Returns the corresponding PublicKey = secret * GeneratorPoint */\n    PublicKey publicKey() const;\n    /** \\brief Signs the hash and returns the Signature */\n    Signature sign(const uint8_t hash[32]) const; // pass 32-byte hash of the message here\n    /** \\brief Signs the hash using Schnorr algorithm and returns the SchnorrSignature */\n    SchnorrSignature schnorr_sign(const uint8_t hash[32]) const;\n\n    /** \\brief Alias for .publicKey().address(network) */\n    int address(char * address, size_t len) const;\n    /** \\brief Alias for .publicKey().legacyAddress(network) */\n    int legacyAddress(char * address, size_t len) const;\n    /** \\brief Alias for .publicKey().segwitAddress(network) */\n    int segwitAddress(char * address, size_t len) const;\n    /** \\brief Alias for .publicKey().nestedSegwitAddress(network) */\n    int nestedSegwitAddress(char * address, size_t len) const;\n#if USE_ARDUINO_STRING\n    String address() const;\n    String legacyAddress() const;\n    String segwitAddress() const;\n    String nestedSegwitAddress() const;\n#endif\n#if USE_STD_STRING\n    std::string address() const;\n    std::string legacyAddress() const;\n    std::string segwitAddress() const;\n    std::string nestedSegwitAddress() const;\n#endif\n//    PrivateKey &operator=(const PrivateKey &other);                   // assignment\n    /** \\brief Performs ECDH key agreement using public key of another party.\n     *  32-byte shared secret will be written to `shared_secret` array.\n     *  Optional parameter hash (true by default) defines if you want sha256(<x><y>) or just <x>.\n     *  Having hash=true is recommended unless you have a very good reason not to use it.\n     */\n    int ecdh(const PublicKey pub, uint8_t shared_secret[32], bool hash=true);\n};\n\n/**\n *  \\brief HD Private Key class. Derived from PrivateKey class.\n *         Works according to [bip32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki),\n *         [bip39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) and \n *         [slip32](https://github.com/satoshilabs/slips/blob/master/slip-0032.md).\n *  You can generate the key from mnemonic or seed, derive children and hardened children.\n *  xprv and xpub methods return strings according to slip32, xprv/xpub for bip44, yprv/ypub for bip49 and zprv/zpub for bip84\n */\nclass HDPrivateKey : public PrivateKey{\nprotected:\n    void init();\n    size_t to_bytes(uint8_t * arr, size_t len) const;\n    virtual size_t to_str(char * buf, size_t len) const{ return xprv( buf, len); };\n    virtual size_t from_str(const char * buf, size_t len);\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    uint8_t prefix[4]; // used for parsing only\npublic:\n    HDPrivateKey();\n    HDPrivateKey(const uint8_t secret[32], const uint8_t chain_code[32],\n                 uint8_t key_depth = 0,\n                 const uint8_t parent_fingerprint_arr[4] = NULL,\n                 uint32_t childnumber = 0,\n                 const Network * network = &DEFAULT_NETWORK,\n                 ScriptType key_type = UNKNOWN_TYPE);\n    HDPrivateKey(const char xprvArr[]);\n    HDPrivateKey(const char * mnemonic, size_t mnemonicSize, const char * password, size_t passwordSize, const Network * network = &DEFAULT_NETWORK, void (*progress_callback)(float) = NULL);\n#if USE_STD_STRING\n    HDPrivateKey(std::string mnemonic, std::string password, const Network * network = &DEFAULT_NETWORK, void (*progress_callback)(float) = NULL);\n#endif\n#if USE_ARDUINO_STRING\n    HDPrivateKey(String mnemonic, String password, const Network * network = &DEFAULT_NETWORK, void (*progress_callback)(float) = NULL);\n#endif\n/*    HDPrivateKey(const HDPrivateKey &other):HDPrivateKey(  // copy\n        other.num, other.chainCode, other.depth,\n        other.parentFingerprint, other.childNumber, other.network, other.type){};\n*/\n    ~HDPrivateKey();\n    virtual size_t length() const{ return 78; };\n    /** \\brief Length of the key in base58 encoding (111). */\n    virtual size_t stringLength() const{ return 111; };\n\n    uint8_t chainCode[32];\n    uint8_t depth;\n    uint8_t parentFingerprint[4];\n    uint32_t childNumber;\n    ScriptType type;\n\n    int fromSeed(const uint8_t * seed, size_t seedSize, const Network * network = &DEFAULT_NETWORK);\n    // int fromSeed(const uint8_t seed[64], const Network * network = &DEFAULT_NETWORK);\n    int fromMnemonic(const char * mnemonic, size_t mnemonicSize, const char * password, size_t passwordSize, const Network * network = &DEFAULT_NETWORK, void (*progress_callback)(float) = NULL);\n    int fromMnemonic(const char * mnemonic, const char * password, const Network * network = &DEFAULT_NETWORK, void (*progress_callback)(float) = NULL){\n        return fromMnemonic(mnemonic, strlen(mnemonic), password, strlen(password), network, progress_callback);\n    }\n#if USE_STD_STRING\n    int fromMnemonic(std::string mnemonic, std::string password, const Network * network = &DEFAULT_NETWORK, void (*progress_callback)(float) = NULL);\n#endif\n#if USE_ARDUINO_STRING\n    int fromMnemonic(String mnemonic, String password, const Network * network = &DEFAULT_NETWORK, void (*progress_callback)(float) = NULL);\n#endif\n    int xprv(char * arr, size_t len) const;\n    int xpub(char * arr, size_t len) const;\n    HDPublicKey xpub() const;\n    int address(char * arr, size_t len) const;\n#if USE_ARDUINO_STRING\n    String xprv() const;\n    String address() const;\n#endif\n#if USE_STD_STRING\n    std::string xprv() const;\n    std::string address() const;\n#endif\n\n    /** \\brief populates array with the fingerprint of the key */\n    void fingerprint(uint8_t arr[4]) const;\n#if USE_STD_STRING\n    std::string fingerprint() const;\n#endif\n#if USE_ARDUINO_STRING\n    String fingerprint() const;\n#endif\n\n    HDPrivateKey child(uint32_t index, bool hardened = false) const;\n    HDPrivateKey hardenedChild(uint32_t index) const;\n    /** \\brief derives a child according to derivation path. Use 0x80000000 + index for hardened index. */\n    HDPrivateKey derive(uint32_t * index, size_t len) const;\n    /** \\brief derives a child according to derivation path. For example \"m/84h/1h/0h/1/23/\" for the 23rd change address for testnet with P2WPKH type (bip84). */\n    HDPrivateKey derive(const char * path) const;\n#if USE_ARDUINO_STRING\n    HDPrivateKey derive(String path) const{ return derive(path.c_str()); };\n#endif\n    // just to make sure it is compressed\n    PublicKey publicKey() const{ PublicKey p = pubKey; p.compressed = true; return p; };\n//    HDPrivateKey &operator=(const HDPrivateKey &other);                   // assignment\n};\n\n/**\n *  \\brief HD Public Key class. Derived from PublicKey class.\n *         Works according to [bip32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki),\n *         [bip39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) and \n *         [slip32](https://github.com/satoshilabs/slips/blob/master/slip-0032.md).\n *  You can derive children\n *  xpub method return strings according to slip32, xpub for bip44, ypub for bip49 and zpub for bip84\n */\nclass HDPublicKey : public PublicKey{\n    size_t to_bytes(uint8_t * arr, size_t len) const;\n    virtual size_t to_str(char * buf, size_t len) const{ return xpub( buf, len); };\n    virtual size_t from_str(const char * buf, size_t len);\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    uint8_t prefix[4]; // used for parsing only\npublic:\n    HDPublicKey();\n    HDPublicKey(const uint8_t point[64], const uint8_t chain_code[32],\n                 uint8_t key_depth = 0,\n                 const uint8_t parent_fingerprint_arr[4] = NULL,\n                 uint32_t childnumber = 0,\n                 const Network * net = &DEFAULT_NETWORK,\n                 ScriptType key_type = UNKNOWN_TYPE);\n    HDPublicKey(const char * xpubArr);\n/*    HDPublicKey(const HDPublicKey &other):HDPublicKey(  // copy\n        other.point, other.chainCode, other.depth,\n        other.parentFingerprint, other.childNumber, other.network, other.type){};\n*/\n#if USE_ARDUINO_STRING\n    HDPublicKey(String pub){ reset(); from_str(pub.c_str(), pub.length()); };\n#endif\n    ~HDPublicKey();\n    /** \\brief Length of the key (78). */\n    virtual size_t length() const{ return 78; };\n    /** \\brief Length of the key in base58 encoding (111). */\n    virtual size_t stringLength() const{ return 111; };\n\n    uint8_t chainCode[32];\n    uint8_t depth;\n    uint8_t parentFingerprint[4];\n    uint32_t childNumber;\n    ScriptType type;\n    const Network * network;\n\n    int xpub(char * arr, size_t len) const;\n    int address(char * arr, size_t len) const;\n#if USE_ARDUINO_STRING\n    String xpub() const;\n    String address() const;\n#endif\n#if USE_STD_STRING\n    std::string xpub() const;\n    std::string address() const;\n#endif\n\n    /** \\brief populates array with the fingerprint of the key */\n    void fingerprint(uint8_t arr[4]) const;\n#if USE_STD_STRING\n    std::string fingerprint() const;\n#endif\n#if USE_ARDUINO_STRING\n    String fingerprint() const;\n#endif\n\n    /** \\brief derive a child. \n     *         You can derive only normal children (not hardened) from the public key. \n     */\n    HDPublicKey child(uint32_t index) const;\n    /** \\brief derives a child according to derivation path. */\n    HDPublicKey derive(uint32_t * index, size_t len) const;\n    /** \\brief derives a child according to derivation path. For example \"m/1/23/\" for the 23rd change address. */\n    HDPublicKey derive(const char * path) const;\n#if USE_ARDUINO_STRING\n    HDPublicKey derive(String path) const{ return derive(path.c_str()); };\n#endif\n//    HDPublicKey &operator=(const HDPublicKey &other);                   // assignment\n};\n\n/**\n *  \\brief Signature class.\n *         Reference: https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki\n */\nclass Signature : public Streamable{\nprotected:\n    uint8_t r[32];\n    uint8_t s[32];\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    size_t rlen() const;\n    size_t slen() const;\n    uint8_t tot[3]; // temporary thingy for parsing\npublic:\n    Signature();\n    Signature(const uint8_t r_arr[32], const uint8_t s_arr[32]);\n    Signature(const uint8_t * der, size_t derLen);\n    Signature(const uint8_t * der);\n    explicit Signature(const char * der);\n    virtual size_t length() const;\n\n    uint8_t index; // used to derive pubkey from signature\n\n    /** \\brief encodes signature in der format and writes it to array */\n    size_t der(uint8_t * arr, size_t len) const;\n    /** \\brief parses signature in der format */\n    size_t fromDer(const uint8_t * arr, size_t len);\n    /** \\brief populates array with <r[32]><s[32]><index> */\n    void bin(uint8_t * arr, size_t len) const;\n    /** \\brief parses array as <r[32]><s[32]><index> */\n    void fromBin(const uint8_t * arr, size_t len);\n\n    bool isValid() const{ uint8_t arr[32] = { 0 }; return !((memcmp(r, arr, 32) == 0) && (memcmp(s, arr, 32)==0)); };\n    explicit operator bool() const{ return isValid(); };\n\n    bool operator==(const Signature& other) const{ return (memcmp(r, other.r, 32) == 0) && (memcmp(s, other.s, 32) == 0); };\n    bool operator!=(const Signature& other) const{ return !operator==(other); };\n};\n\n/**\n *  \\brief SchnorrSignature class.\n *         Reference: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki\n */\nclass SchnorrSignature : public Streamable{\nprotected:\n    uint8_t r[32];\n    uint8_t s[32];\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\npublic:\n    SchnorrSignature();\n    SchnorrSignature(const uint8_t r_arr[32], const uint8_t s_arr[32]);\n    SchnorrSignature(const uint8_t rs_arr[64]);\n    explicit SchnorrSignature(const char * rs);\n    virtual size_t length() const{ return 64; };\n\n    bool isValid() const{ uint8_t arr[32] = { 0 }; return !((memcmp(r, arr, 32) == 0) && (memcmp(s, arr, 32)==0)); };\n    explicit operator bool() const{ return isValid(); };\n\n    bool operator==(const SchnorrSignature& other) const{ return (memcmp(r, other.r, 32) == 0) && (memcmp(s, other.s, 32) == 0); };\n    bool operator!=(const SchnorrSignature& other) const{ return !operator==(other); };\n};\n\n/**\n *  \\brief Script class. Parsing requires the length of the script in the beginning.\n */\nclass Script : public Streamable{\nprotected:\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    uint8_t lenLen; // for parsing only, length of the varint\n    void fromAddress(const char * address);\n    void init();\npublic:\n    uint8_t * scriptArray;\n    size_t scriptLen;\n    void clear();\n    Script();\n    Script(const uint8_t * buffer, size_t len);\n    /** \\brief creates a script from address */\n    Script(const char * address){ init(); fromAddress(address); };\n#if USE_ARDUINO_STRING\n    /** \\brief creates a script from address */\n    Script(const String address){ init(); fromAddress(address.c_str()); };\n#endif\n#if USE_STD_STRING\n    /** \\brief creates a script from address */\n    Script(const std::string address){ init(); fromAddress(address.c_str()); };\n#endif\n    /** \\brief creates one of standart scripts (P2PKH, P2WPKH) */\n    Script(const PublicKey pubkey, ScriptType type = P2PKH);\n    /** \\brief creates one of standart scripts (P2SH, P2WSH) */\n    Script(const Script &other, ScriptType type);\n    Script(const Script &other); // copy\n    ~Script(){ if(scriptArray){ free(scriptArray); } };\n\n    /** \\brief tries to determine the script type */\n    ScriptType type() const;\n    /** \\brief returns address corresponding to the script */\n    size_t address(char * buffer, size_t len, const Network * network = &DEFAULT_NETWORK) const;\n#if USE_ARDUINO_STRING\n    String address(const Network * network = &DEFAULT_NETWORK) const;\n#endif\n#if USE_STD_STRING\n    std::string address(const Network * network = &DEFAULT_NETWORK) const;\n#endif\n\n    /** \\brief length of the script with varint */\n    virtual size_t length() const;    \n    /** \\brief pushes a single byte (op_code) to the end */\n    size_t push(uint8_t code);\n    /** \\brief pushes bytes from data object to the end */\n    size_t push(const uint8_t * data, size_t len);\n    /** \\brief adds <len><sec> to the script */\n    size_t push(const PublicKey pubkey);\n    /** \\brief adds <len><der><sigType> to the script */\n    size_t push(const Signature sig, SigHashType sigType = SIGHASH_ALL);\n    /** \\brief adds <len><script> to the script (used for P2SH) */\n    size_t push(const Script sc);\n\n    /** \\brief returns scriptPubkey for this scripts (P2SH or P2WSH) */\n    Script scriptPubkey(ScriptType type = P2SH) const;\n\n    Script &operator=(const Script &other);                   // assignment\n\n    // Bool conversion. Allows to use if(script) construction. Returns false if script is empty, true otherwise\n    explicit operator bool() const{ return (scriptLen > 0); };\n    bool operator==(const Script& other) const{ return (scriptLen == other.scriptLen) && (memcmp(scriptArray, other.scriptArray, scriptLen) == 0); };\n    bool operator!=(const Script& other) const{ return !operator==(other); };\n};\n\nScript pkh(PublicKey pub);\nScript wpkh(PublicKey pub);\nScript multi(uint8_t threshold, const PublicKey * pubkeys, uint8_t pubkeys_len);\nScript sortedmulti(uint8_t threshold, const PublicKey * pubkeys, uint8_t pubkeys_len);\nScript wsh(Script witness_script);\nScript sh(Script script);\n\n/**\n *  \\brief Witness class. Has a form of `<num><e0><e1><e2>...` \n *         where `<e>` can be a public key, signature or arbitrary data (i.e. hash)\n */\nclass Witness : public Streamable{\n    uint8_t * witnessArray;\n    size_t witnessLen;\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    uint32_t numElements;\n    // used for parsing only:\n    uint32_t cur_element; // index of current element\n    size_t cur_element_len; // length of current element\n    size_t cur_bytes_parsed; // number of bytes read from current element\n    uint8_t curLen; // for parsing only, length of the varint\n    uint8_t lenLen; // for parsing, length of the varint\n    virtual void reset(){ status = PARSING_DONE; bytes_parsed = 0; cur_element_len=0; cur_bytes_parsed=0; cur_element=0; lenLen=0; };\n    void init();\npublic:\n    void clear();\n    virtual size_t length() const;\n    Witness();\n    Witness(const uint8_t * buffer, size_t len);\n    Witness(const Signature sig, const PublicKey pub);\n    Witness(const Witness &other); // copy\n    ~Witness(){ if(witnessArray){ free(witnessArray); } };\n    /** \\brief returns number of elements in the witness */\n    uint8_t count() const{ return numElements; };\n    /** \\brief adds `<len><data>` to the witness */\n    size_t push(const uint8_t * data, size_t len);\n    /** \\brief adds `<len><sec>` to the witness */\n    size_t push(const PublicKey pubkey);\n    /** \\brief adds `<len><der><sigType>` to the witness */\n    size_t push(const Signature sig, SigHashType sigType = SIGHASH_ALL);\n    /** \\brief adds `<len><script>` to the witness */\n    size_t push(const Script sc);\n\n    Witness &operator=(Witness const &other); // assignment\n    explicit operator bool() const{ return (numElements > 0); };\n    bool operator==(const Witness& other) const{ return (witnessLen == other.witnessLen) && (memcmp(witnessArray, other.witnessArray, witnessLen) == 0) && (numElements == other.numElements); };\n    bool operator!=(const Witness& other) const{ return !operator==(other); };\n};\n\n/**\n *  \\brief Transaction Input class. Serializes as `<prev_hash><prev_index><scriptSig><sequence>`<br>\n *         Stores information about previous transaction hash, prev output number,\n *         scriptSig, sequence and witness data if it is segwit.\n */\nclass TxIn : public Streamable{\nprotected:\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    void init();\npublic:\n    TxIn(void);\n    TxIn(const uint8_t prev_id[32], uint32_t prev_index, const Script script, uint32_t sequence_number = 0xffffffff);\n    TxIn(const uint8_t prev_id[32], uint32_t prev_index, uint32_t sequence_number = 0xffffffff);\n    explicit TxIn(const char * prev_id, uint32_t prev_index, const Script script, uint32_t sequence_number = 0xffffffff);\n    explicit TxIn(const char * prev_id, uint32_t prev_index, uint32_t sequence_number = 0xffffffff);\n    virtual size_t length() const;\n    uint8_t hash[32];\n    uint32_t outputIndex;\n    Script scriptSig;\n    uint32_t sequence;\n    Witness witness;\n    /** \\brief checks if the input is segwit or not */\n    bool isSegwit() const{ return (witness.count() > 0); };\n\n    bool isValid() const{ return status==PARSING_DONE; };\n    explicit operator bool() const{ return isValid(); };\n};\n\n/**\n *  \\brief Transaction Output class.<br>\n *         Stores information the amount and ScriptPubkey,\n */\nclass TxOut : public Streamable{\nprivate:\n    uint8_t tmp[8]; // for parsing amounts\nprotected:\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    void init(){ status = PARSING_DONE; bytes_parsed=0; amount = 0; };\npublic:\n    TxOut(){ amount = 0; };\n    TxOut(uint64_t send_amount, const Script outputScript){ amount = send_amount; scriptPubkey = outputScript; };\n    TxOut(const Script outputScript, uint64_t send_amount){ amount = send_amount; scriptPubkey = outputScript; };\n    TxOut(uint64_t send_amount, const char * address){ amount = send_amount; scriptPubkey = Script(address); }; \n    TxOut(const char * address, uint64_t send_amount){ amount = send_amount; scriptPubkey = Script(address); };\n    virtual size_t length() const{ return 8+scriptPubkey.length(); };\n\n    /** \\brief this script defines the rules for the spending input */\n    Script scriptPubkey;\n    /** \\brief the output amount in satoshi */\n    uint64_t amount;\n    /** \\brief returns the output amount in BTC */\n    float btcAmount(){ return (float)amount/1e8; };\n    /** \\brief returns the address corresponding to the output script */\n    size_t address(char * addr, size_t len, const Network * network = &DEFAULT_NETWORK) const{ return scriptPubkey.address(addr, len, network); };\n#if USE_ARDUINO_STRING\n    String address(const Network * network = &DEFAULT_NETWORK) const{ return scriptPubkey.address(network); };\n#endif\n#if USE_STD_STRING\n    std::string address(const Network * network = &DEFAULT_NETWORK) const{ return scriptPubkey.address(network); };\n#endif\n\n    bool isValid() const{ return status==PARSING_DONE; };\n    explicit operator bool() const{ return isValid(); };\n};\n/**\n *  \\brief Transaction class.<br>\n *         Can be segwit or not. For legacy tx serializes as `<ver><inputsNumber><inputs><outputsNumber><outputs><locktime>`<br>\n *         For segwit tx serializes as `<ver><00><01><inputsNumber><inputs><outputsNumber><outputs><witnesses><locktime>`\n */\nclass Tx : public Streamable{\nprotected:\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    uint8_t segwit_flag;\n    void clear();\n    void init();\npublic:\n    Tx();\n    Tx(Tx const &other);\n    ~Tx();\n    virtual size_t length() const;\n    uint32_t version;\n    size_t inputsNumber;\n    TxIn * txIns;\n    size_t outputsNumber;\n    TxOut * txOuts;\n    uint32_t locktime;\n\n    /** \\brief checks wether transaction is segwit or not.<br> \n      *        returns `true` if at least one of the inputs has non-empty witness  \n      */\n    bool isSegwit() const;\n\n    /** \\brief populates hash with transaction hash */\n    int hash(uint8_t h[32]) const;\n    /** \\brief populates hash with transaction hash if serialized as segwit */\n    int whash(uint8_t h[32]) const;\n    /** \\brief populates array with id of the transaction (reverse of the hash) */\n    int txid(uint8_t id_arr[32]) const;\n    /** \\brief populates array with witness id of the transaction */\n    int wtxid(uint8_t id_arr[32]) const;\n#if USE_ARDUINO_STRING\n    String txid() const;\n    String wtxid() const;\n#endif\n#if USE_STD_STRING\n    std::string txid() const;\n    std::string wtxid() const;\n#endif\n\n    /** \\brief adds another input to the transaction */\n    uint8_t addInput(const TxIn txIn);\n    /** \\brief adds another output to the transaction */\n    uint8_t addOutput(const TxOut txOut);\n\n    /** \\brief calculates a hash to sign for certain input */\n    int sigHash(uint8_t h[32], uint8_t inputIndex, const Script scriptPubkey, SigHashType sighash = SIGHASH_ALL) const;\n\n    int hashPrevouts(uint8_t h[32]) const;\n    int hashSequence(uint8_t h[32]) const;\n    int hashOutputs(uint8_t h[32]) const;\n    int sigHashSegwit(uint8_t h[32], uint8_t inputIndex, const Script scriptPubKey, uint64_t amount, SigHashType sighash = SIGHASH_ALL) const;\n\n#if 0\n    /** \\brief sorts inputs and outputs in alphabetical order */\n    void sort();\n#endif\n\n    /** \\brief signs legacy input with certain script and returns a signature.\n     *         Don't forget to construct txIns[i].scriptSig correctly if you are using P2SH.\n     *         For P2WPKH, P2WSH and P2SH-P2WPKH use signSegwitInput method.\n     */\n    Signature signInput(uint8_t inputIndex, const PrivateKey pk, const Script redeemScript, SigHashType sighash = SIGHASH_ALL);\n    /** \\brief signs legacy input and returns a signature */\n    Signature signInput(uint8_t inputIndex, const PrivateKey pk){\n        return signInput(inputIndex, pk, Script(pk.publicKey(), P2PKH));\n    };\n\n    /** \\brief signs segwit input with certain script and returns a signature.\n     *         Don't forget to construct txIns[i].witness correctly if you are using P2WSH or P2SH-P2WSH.\n     *         For P2PKH and P2SH use signInput method.\n     */\n    Signature signSegwitInput(uint8_t inputIndex, const PrivateKey pk, const Script redeemScript, uint64_t amount, ScriptType type = P2WSH, SigHashType sighash = SIGHASH_ALL);\n    /** \\brief signs segwit input and returns a signature. Uses native segwit (P2WPKH) by default, \n     *         you can also specify the type to be P2SH-P2WPKH to sign nested segwit transaction.\n     */\n    Signature signSegwitInput(uint8_t inputIndex, const PrivateKey pk, uint64_t amount, ScriptType type = P2WPKH){\n        return signSegwitInput(inputIndex, pk, Script(pk.publicKey(), P2WPKH), amount, type); // FIXME: are you sure?\n    };\n\n    Tx &operator=(Tx const &other);\n\n    bool isValid() const{ return status==PARSING_DONE; };\n    explicit operator bool() const{ return isValid(); };\n};\n\n#endif // __BITCOIN_H__\n"
  },
  {
    "path": "src/BitcoinCurve.cpp",
    "content": "#include \"BitcoinCurve.h\"\n#include \"Conversion.h\"\n#include \"utility/trezor/rfc6979.h\"\n#include \"utility/trezor/ecdsa.h\"\n#include \"utility/trezor/secp256k1.h\"\n\nconst ECPoint InfinityPoint;\nconst ECPoint GeneratorPoint(\"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\");\n\nsize_t ECPoint::from_stream(ParseStream *s){\n\tstatic uint8_t first_byte;\n\tif(status == PARSING_FAILED){\n\t\treturn 0;\n\t}\n\tif(status == PARSING_DONE){\n\t\tbytes_parsed = 0;\n\t}\n\tstatus = PARSING_INCOMPLETE;\n\tsize_t bytes_to_read = 33;\n\tsize_t bytes_read = 0;\n\tif(bytes_parsed > 0){ // we already know if it's compressed or not\n\t\tbytes_to_read = ECPoint::length()-bytes_parsed;\n\t}else{\n\t\tif(s->available()){\n\t\t\tuint8_t c = s->read();\n\t\t\tbytes_read++; bytes_to_read--;\n\t\t\tif(c < 0x02 || c > 0x04){\n\t\t\t\tstatus = PARSING_FAILED;\n\t\t\t\tbytes_parsed += bytes_read;\n\t\t\t\treturn bytes_read;\n\t\t\t}\n\t\t\tfirst_byte = c;\n\t\t\tif(c == 0x04){ // uncompressed\n\t\t\t\tbytes_to_read += 32;\n\t\t\t\tcompressed = false;\n\t\t\t}else{\n\t\t\t\tcompressed = true;\n\t\t\t}\n\t\t}\n\t}\n\twhile(s->available() && bytes_to_read > 0){ // actual data\n\t\tpoint[bytes_parsed+bytes_read-1] = s->read();\n\t\tbytes_read++; bytes_to_read--;\n\t}\n\tif(bytes_to_read==0){\n\t\tif(compressed){\n\t\t\tuint8_t buf[33];\n\t\t\tbuf[0] = first_byte;\n\t\t\tmemcpy(buf+1, point, 32);\n            uint8_t arr[65];\n            ecdsa_uncompress_pubkey(&secp256k1, buf, arr);\n            memcpy(point, arr+1, 64);\n\t\t}\n\t\tstatus = PARSING_DONE;\n\t\tif(!ECPoint::isValid()){\n\t\t\tstatus = PARSING_FAILED;\n\t\t}\n\t}\n\tbytes_parsed += bytes_read;\n\treturn bytes_read;\n}\nsize_t ECPoint::to_stream(SerializeStream *s, size_t offset) const{\n\tsize_t bytes_written = 0;\n\tif(!s->available()){\n\t\treturn 0;\n\t}\n\tif(offset == 0){    \t\t\n\t\tif(compressed){\n\t\t\ts->write(0x02 + (point[63] & 0x01));\n\t\t}else{\n\t\t\ts->write(0x04);\n\t\t}\n\t\tbytes_written ++;\n\t\toffset++;\n\t}\n\twhile(s->available() > 0 && offset < ECPoint::length()){\n\t\ts->write(point[offset-1]);\n\t\toffset++; bytes_written++;\n\t}\n    return bytes_written;\n}\nsize_t ECPoint::sec(uint8_t * arr, size_t len) const{\n\tSerializeByteStream s(arr, len);\n\treturn ECPoint::to_stream(&s);\n}\nsize_t ECPoint::fromSec(const uint8_t * arr, size_t len){\n\tParseByteStream s(arr, len);\n\treturn ECPoint::from_stream(&s);\n}\n\nECPoint::ECPoint(const uint8_t pubkeyArr[64], bool use_compressed){ \n\tmemcpy(point, pubkeyArr, 64);\n\tcompressed = use_compressed;\n};\nECPoint::ECPoint(const uint8_t * secArr){ \n\tif(secArr[0] == 0x04){\n\t\tECPoint::fromSec(secArr, 65);\n\t}else{\n\t\tECPoint::fromSec(secArr, 33);\n\t}\n};\nECPoint::ECPoint(const char * arr){\n\treset();\n\tECPoint::parse(arr, strlen(arr));\n};\n\n// bool verify(const Signature sig, const uint8_t hash[32]) const;\nbool ECPoint::isValid() const{ \n\tif(status != PARSING_DONE){\n\t\treturn false;\n\t}\n    curve_point pub;\n\tuint8_t buf[65];\n\tsec(buf, 65);\n\treturn ecdsa_read_pubkey(&secp256k1, buf, &pub);\n};\nbool ECPoint::isEven() const{\n    return !bool(point[63] & 0x01);\n};\n\nECPoint ECPoint::operator+(const ECPoint& other) const{\n\tif(*this == InfinityPoint){\n\t\treturn other;\n\t}\n\tif(other == InfinityPoint){\n\t\treturn *this;\n\t}\n    curve_point p1, p2;\n\tuint8_t buf[65];\n\tsec(buf, 65);\n\tecdsa_read_pubkey(&secp256k1, buf, &p1);\n\tother.sec(buf, 65);\n\tecdsa_read_pubkey(&secp256k1, buf, &p2);\n    point_add(&secp256k1,&p1,&p2);\n    ECPoint sum;\n\tbn_write_be(&p2.x, sum.point);\n\tbn_write_be(&p2.y, sum.point+32);\n\treturn sum;\n};\nECPoint ECPoint::operator-() const{\n\tif(*this == InfinityPoint){\n\t\treturn *this;\n\t}\n    uint8_t buf[33];\n    x(buf+1, 32);\n    if(isEven()){\n        buf[0] = 0x03;\n    }else{\n        buf[0] = 0x02;\n    }\n    ECPoint a;\n    a.fromSec(buf, 33);\n    a.compressed = compressed;\n    return a;\n}\nECPoint ECPoint::operator-(const ECPoint& other) const{\n\tECPoint a = -other;\n\treturn *this+a;\n}\n\n/*********** ECScalar ******************/\n\nsize_t ECScalar::from_stream(ParseStream *s){\n\tif(status == PARSING_FAILED){\n\t\treturn 0;\n\t}\n\tif(status == PARSING_DONE){\n\t\tbytes_parsed = 0;\n\t}\n\tstatus = PARSING_INCOMPLETE;\n\tsize_t bytes_read = 0;\n\twhile(s->available() > 0 && bytes_parsed+bytes_read < 32){\n\t\tnum[bytes_parsed+bytes_read] = s->read();\n\t\tbytes_read++;\n\t}\n\tif(bytes_parsed+bytes_read == 32){\n\t\tstatus = PARSING_DONE;\n\t\tuint8_t zero[32] = { 0 };\n\t\tif(memcmp(num, zero, 32)==0){ // should we add something else here?\n\t\tstatus = PARSING_FAILED;\n\t\t}\n\t\tbignum256 n;\n\t\tbn_read_be(num, &n);\n\t\tbn_mod(&n, &secp256k1.order);\n\t\tbn_write_be(&n, num);\n\t}\n\tbytes_parsed += bytes_read;\n\treturn bytes_read;\n}\nsize_t ECScalar::to_stream(SerializeStream *s, size_t offset) const{\n\tsize_t bytes_written = 0;\n\twhile(s->available() && offset+bytes_written < 32){\n\t\ts->write(num[bytes_written+offset]);\n\t\tbytes_written++;\n\t}\n\treturn bytes_written;\n}\nECScalar ECScalar::operator+(const ECScalar& other) const{\n    bignum256 a, b;\n\tbn_read_be(this->num, &a);\n\tbn_read_be(other.num, &b);\n\tbn_addmod(&a, &b, &secp256k1.order);\n\tbn_mod(&a, &secp256k1.order);\n\tECScalar sum;\n\tbn_write_be(&a, sum.num);\n\treturn sum;\n}\nECScalar ECScalar::operator+(const uint32_t& i) const{\n\tbignum256 a;\n\tbn_read_be(this->num, &a);\n\tbn_addi(&a, i);\n\tbn_mod(&a, &secp256k1.order);\n\tECScalar sum;\n\tbn_write_be(&a, sum.num);\n\treturn sum;\n}\nECScalar ECScalar::operator-() const{\n    bignum256 a, b;\n\tbn_read_be(this->num, &a);\n\tbn_subtract(&secp256k1.order, &a, &b);\n\tECScalar neg;\n\tbn_write_be(&b, neg.num);\n\treturn neg;\n}\nECScalar ECScalar::operator-(const uint32_t& i) const{\n    bignum256 a;\n\tbn_read_be(this->num, &a);\n\tbn_subi(&a, i, &secp256k1.order);\n    bn_mod(&a, &secp256k1.order);\n\tECScalar sum;\n\tbn_write_be(&a, sum.num);\n\treturn sum;\n}\nECScalar ECScalar::operator-(const ECScalar& other) const{\n\treturn (*this+(-other));\n}\nECScalar ECScalar::operator*(const ECScalar& other) const{\n    bignum256 a, b;\n\tbn_read_be(this->num, &a);\n\tbn_read_be(other.num, &b);\n\tbn_multiply(&b, &a, &secp256k1.order);\n    bn_mod(&a, &secp256k1.order);\n\tECScalar mul;\n\tbn_write_be(&a, mul.num);\n\treturn mul;\n}\nECScalar ECScalar::operator/(const ECScalar& other) const{\n    bignum256 a, b;\n\tbn_read_be(this->num, &a);\n\tbn_read_be(other.num, &b);\n\tbn_inverse(&b, &secp256k1.order);\n\tbn_multiply(&b, &a, &secp256k1.order);\n    bn_mod(&a, &secp256k1.order);\n\tECScalar res;\n\tbn_write_be(&a, res.num);\n\treturn res;\n}\nbool ECScalar::operator<(const ECScalar& other) const{\n\tbignum256 a,b;\n\tbn_read_be(num, &a);\n\tbn_read_be(other.num, &b);\n\treturn bn_is_less(&a, &b);\n}\nbool ECPoint::operator<(const ECPoint& other) const{\n\tuint8_t sec1[65];\n\tuint8_t sec2[65];\n\tsec(sec1, sizeof(sec1));\n\tother.sec(sec2, sizeof(sec2));\n\treturn memcmp(sec1, sec2, sizeof(sec1)) > 0;\n}\nECPoint operator*(const ECScalar& scalar, const ECPoint& point){\n\tECPoint r;\n\tuint8_t num[32];\n\tscalar.getSecret(num);\n\tif(point == GeneratorPoint){\n\t\tuint8_t pubkey[65];\n\t\tecdsa_get_public_key65(&secp256k1, num, pubkey);\n\t\tr.parse(pubkey, 65);\n\t}else{\n\t\tbignum256 d;\n\t\tbn_read_be(num, &d);\n\t\tcurve_point p, res;\n\t\tbn_read_be(point.point, &p.x);\n\t\tbn_read_be(point.point+32, &p.y);\n\t\tpoint_multiply(&secp256k1, &d, &p, &res);\n\t\tbn_write_be(&res.x, r.point);\n\t\tbn_write_be(&res.y, r.point+32);\n\t}\n\tr.compressed = point.compressed;\n\treturn r;\n}\n"
  },
  {
    "path": "src/BitcoinCurve.h",
    "content": "#ifndef __BITCOIN_CURVE_H__\n#define __BITCOIN_CURVE_H__\n\n#include \"uBitcoin_conf.h\"\n#include \"BaseClasses.h\"\n#include \"utility/trezor/memzero.h\"\n#include \"Conversion.h\"\n\nclass ECPoint : public Streamable{\nprotected:\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\npublic:\n    uint8_t point[64];  // point on curve: (x,y)\n    bool compressed;\n\n    virtual void reset(){ bytes_parsed = 0; status=PARSING_DONE; memset(point, 0, 64); compressed = true; };\n    virtual size_t length() const{ return 33 + 32*(1-compressed); };\n    virtual size_t stringLength() const{ return 2*ECPoint::length(); };\n\n    ECPoint(){ reset(); };\n    ECPoint(const uint8_t pubkeyArr[64], bool use_compressed);\n    ECPoint(const uint8_t * secArr);\n    explicit ECPoint(const char * secHex);\n\n    size_t sec(uint8_t * arr, size_t len) const;\n    size_t fromSec(const uint8_t * arr, size_t len);\n    /** \\brief fills array with x coordinate of the point */\n    size_t x(uint8_t * arr, size_t len) const{\n        if(len < 32){\n            return 0;\n        }\n        memcpy(arr, point, 32);\n        return 32;\n    };\n    /** \\brief parses x-only pubkey, from two possible points selects one with even y */\n    size_t from_x(const uint8_t * arr, size_t len){\n        if(len < 32){\n            return 0;\n        }\n        uint8_t sec[33] = {0x02};\n        memcpy(sec+1, arr, 32);\n        return fromSec(sec, sizeof(sec));\n    }\n#if USE_ARDUINO_STRING\n    String sec() const{\n        char arr[65*2+1] = \"\";\n        SerializeByteStream stream(arr, sizeof(arr));\n        ECPoint::to_stream(&stream);\n        if(compressed){\n            arr[33*2+1] = 0;\n        }\n        String s(arr);\n        return s;\n    };\n    String x() const{\n        uint8_t arr[32];\n        x(arr, sizeof(arr));\n        return toHex(arr, sizeof(arr));\n    };\n#endif\n#if USE_STD_STRING\n    std::string sec() const{\n        char arr[65*2+1] = \"\";\n        SerializeByteStream stream(arr, sizeof(arr));\n        ECPoint::to_stream(&stream);\n        if(compressed){\n            arr[33*2+1] = 0;\n        }\n        std::string s(arr);\n        return s;\n    };\n    std::string x() const{\n        uint8_t arr[32];\n        x(arr, sizeof(arr));\n        return toHex(arr, sizeof(arr));\n    };\n#endif\n    // bool verify(const Signature sig, const uint8_t hash[32]) const;\n    virtual bool isValid() const;\n    /** \\brief checks if pubkey has even Y coordinate */\n    bool isEven() const;\n    explicit operator bool() const { return isValid(); };\n    bool operator==(const ECPoint& other) const{ return (memcmp(point, other.point, 64) == 0); };\n    bool operator!=(const ECPoint& other) const{ return !operator==(other); };\n\n    ECPoint operator+(const ECPoint& other) const;\n    ECPoint operator-() const;\n    ECPoint operator-(const ECPoint& other) const;\n    ECPoint operator+=(const ECPoint& other){ *this = *this+other; return *this; };\n    ECPoint operator-=(const ECPoint& other){ *this = *this-other; return *this; };\n\n    // sec-hex-comparison for multisig sorting\n    bool operator<(const ECPoint& other) const;\n    bool operator>(const ECPoint& other) const{ return (other<*this); };\n    bool operator>=(const ECPoint& other) const{ return !(*this<other); };\n    bool operator<=(const ECPoint& other) const{ return !(*this>other); };\n};\n\nextern const ECPoint InfinityPoint;\nextern const ECPoint GeneratorPoint;\n\nclass ECScalar : public Streamable{\nprotected:\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    uint8_t num[32];  // scalar mod secp526k1.order\n    virtual void init(){ bytes_parsed = 0; status=PARSING_DONE; memzero(num, 32); };\npublic:\n    virtual void reset(){ bytes_parsed = 0; status=PARSING_DONE; memzero(num, 32); };\n    virtual size_t length() const{ return 32; };\n\n    ECScalar(){ init(); };\n    ECScalar(const uint8_t * arr, size_t len){ init(); parse(arr, len); };\n    explicit ECScalar(const char * arr){ init(); parse(arr, strlen(arr)); };\n    ECScalar(uint32_t i){ init(); intToBigEndian(i, num, 32); };\n    ~ECScalar(){ memzero(num, 32); };\n\n    /** \\brief Populates array with the secret key */\n    virtual void setSecret(const uint8_t secret_arr[32]){ memcpy(num, secret_arr, 32); };\n    /** \\brief Sets the secret key */\n    void getSecret(uint8_t buffer[32]) const{ memcpy(buffer, num, 32); };\n\n    ECScalar operator+(const ECScalar& other) const;\n    ECScalar operator+(const uint32_t& i) const;\n    ECScalar operator-() const;\n    ECScalar operator-(const ECScalar& other) const;\n    ECScalar operator-(const uint32_t& i) const;\n    ECScalar operator+=(const ECScalar& other){ *this = *this+other; return *this; };\n    ECScalar operator-=(const ECScalar& other){ *this = *this-other; return *this; };\n    ECScalar operator+=(const uint32_t& i){ *this = *this+i; return *this; };\n    ECScalar operator-=(const uint32_t& i){ *this = *this-i; return *this; };\n\n    ECScalar operator*(const ECScalar& other) const;\n    ECScalar operator/(const ECScalar& other) const;\n    ECScalar operator*=(const ECScalar& other){ *this = *this*other; return *this; };\n    ECScalar operator/=(const ECScalar& other){ *this = *this/other; return *this; };\n    \n    virtual bool isValid() const{ uint8_t arr[32] = { 0 }; return (memcmp(num, arr, 32) != 0); };\n    explicit operator bool() const { return isValid(); };\n    bool operator==(const ECScalar& other) const{ return (memcmp(num, other.num, 32) == 0); };\n    bool operator!=(const ECScalar& other) const{ return !operator==(other); };\n    bool operator<(const ECScalar& other) const;\n    bool operator>(const ECScalar& other) const{ return (other<*this); };\n    bool operator>=(const ECScalar& other) const{ return !(*this<other); };\n    bool operator<=(const ECScalar& other) const{ return !(*this>other); };\n};\n\ninline ECScalar operator/(uint32_t i, ECScalar& scalar){ return ECScalar(i) / scalar; };\ninline ECScalar operator/(ECScalar& scalar, uint32_t i){ return scalar / ECScalar(i); };\ninline ECScalar operator*(uint32_t i, ECScalar& scalar){ return ECScalar(i) * scalar; };\ninline ECScalar operator*(ECScalar& scalar, uint32_t i){ return scalar * ECScalar(i); };\ninline ECScalar operator+(uint32_t i, ECScalar& scalar){ return ECScalar(i) + scalar; };\ninline ECScalar operator+(ECScalar& scalar, uint32_t i){ return scalar + ECScalar(i); };\ninline ECScalar operator-(uint32_t i, ECScalar& scalar){ return ECScalar(i) - scalar; };\ninline ECScalar operator-(ECScalar& scalar, uint32_t i){ return scalar - ECScalar(i); };\n\nECPoint operator*(const ECScalar& d, const ECPoint& p);\ninline ECPoint operator*(const ECPoint& p, const ECScalar& d){ return d*p; };\ninline ECPoint operator/(const ECPoint& p, const ECScalar& d){ return (ECScalar(1)/d)*p; };\n\n#endif // __BITCOIN_CURVE_H__\n"
  },
  {
    "path": "src/Conversion.cpp",
    "content": "#include \"Conversion.h\"\n#include \"Hash.h\"\n#include <string.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include \"utility/trezor/memzero.h\"\n\n#if USE_STD_STRING\nusing std::string;\n#define String string\n#endif\n\nstatic const char BASE58_CHARS[] = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\nstatic const char BASE43_CHARS[] = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$*+-./:\";\nstatic const char BASE64_CHARS[] = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nsize_t toHex(const uint8_t * array, size_t arraySize, char * output, size_t outputSize){\n    if(array == NULL || output == NULL){ return 0; }\n    // uint8_t * array = (uint8_t *) arr;\n    if(outputSize < 2*arraySize){\n        return 0;\n    }\n    memzero(output, outputSize);\n\n    for(size_t i=0; i < arraySize; i++){\n        output[2*i] = (array[i] >> 4) + '0';\n        if(output[2*i] > '9'){\n            output[2*i] += 'a'-'9'-1;\n        }\n\n        output[2*i+1] = (array[i] & 0x0F) + '0';\n        if(output[2*i+1] > '9'){\n            output[2*i+1] += 'a'-'9'-1;\n        }\n    }\n    return 2*arraySize;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString toHex(const uint8_t * array, size_t arraySize){\n    if(array == NULL){ return String(); }\n    size_t outputSize = arraySize * 2 + 1;\n    char * output = (char *) malloc(outputSize);\n    if(output == NULL){ return String(); }\n\n    toHex(array, arraySize, output, outputSize);\n\n    String result(output);\n\n    memzero(output, outputSize);\n    free(output);\n\n    return result;\n}\n#endif\n#if USE_ARDUINO_STRING\nsize_t toHex(uint8_t v, Print &s){\n    char c = (v >> 4) + '0';\n    if(c > '9'){\n        c += 'a'-'9'-1;\n    }\n    s.print(c);\n\n    c = (v & 0x0F) + '0';\n    if(c > '9'){\n        c += 'a'-'9'-1;\n    }\n    s.print(c);\n    return 2;\n}\n\nsize_t toHex(const uint8_t * array, size_t arraySize, Print &s){\n    if(array == NULL){ return 0; }\n    size_t l = 0;\n    for(int i=0; i<arraySize; i++){\n        l += toHex(array[i], s);\n    }\n    return l;\n}\n#endif\n\nuint8_t hexToVal(char c){\n    if(c >= '0' && c <= '9'){\n        return ((uint8_t)(c - '0')) & 0x0F;\n    }\n    if(c >= 'A' && c <= 'F'){\n        return ((uint8_t)(c-'A'+10)) & 0x0F;\n    }\n    if(c >= 'a' && c <= 'f'){\n        return ((uint8_t)(c-'a'+10)) & 0x0F;\n    }\n    return 0xFF;\n}\n\nsize_t fromHex(const char * hex, size_t hexLen, uint8_t * array, size_t arraySize){\n    if(array == NULL || hex == NULL){ return 0; }\n    memzero(array, arraySize);\n    // ignoring all non-hex characters in the beginning\n    size_t offset = 0;\n    while(offset < hexLen){\n        uint8_t v = hexToVal(hex[offset]);\n        if(v > 0x0F){ // if invalid char\n            offset++;\n        }else{\n            break;\n        }\n    }\n    hexLen -= offset;\n    for(size_t i=0; i<hexLen/2; i++){\n        uint8_t v1 = hexToVal(hex[offset+2*i]);\n        uint8_t v2 = hexToVal(hex[offset+2*i+1]);\n        if((v1 > 0x0F) || (v2 > 0x0F)){ // if invalid char stop parsing\n            return i;\n        }\n        array[i] = (v1<<4) | v2;\n    }\n    return hexLen/2;\n}\n#if USE_STD_STRING || USE_ARDUINO_STRING\nsize_t fromHex(String encoded, uint8_t * output, size_t outputSize){\n    if(output == NULL){ return 0; }\n    return fromHex(encoded.c_str(), encoded.length(), output, outputSize);\n};\n#endif\n#if !(USE_ARDUINO_STRING  || USE_STD_STRING)\nsize_t fromHex(const char * hex, uint8_t * array, size_t arraySize){\n    if(array == NULL || hex == NULL){ return 0; }\n    return fromHex(hex, strlen(hex), array, arraySize);\n}\n#endif\n\n/******************** Binary conversion *******************/\n\nsize_t fromBin(const char * bin, size_t binLen, uint8_t * array, size_t arraySize){\n    if(bin == NULL || array == NULL){ return 0; }\n    // array is big enough\n    if(arraySize*8 < binLen){\n        return 0;\n    }\n    size_t len = binLen/8;\n    if(binLen % 8 != 0){\n        len += 1; // not aligned to 8 bits\n    }\n    // zero output array\n    memzero(array, arraySize);\n    for(size_t i = 0; i < binLen; i++){\n        // we go in reverse order (from the end of the string)\n        uint8_t exp = (i%8); // shift\n        uint8_t n = (i/8); // current byte from the end\n        char c = bin[binLen-i-1];\n        if(c == '1'){\n            // set bit\n            array[len-n-1] |= (1<<exp);\n        }else if(c == '0'){\n            // correct char, nothing to do here\n        }else{\n            // wrong char\n            return 0;\n        }\n    }\n    return len;\n}\n\nsize_t toBin(const uint8_t * array, size_t arraySize, char * output, size_t outputSize){\n  if(array == NULL || output == NULL){ return 0; }\n  if(outputSize < arraySize*8){\n    return 0;\n  }\n  memzero(output, outputSize);\n  for(size_t i=0; i<arraySize; i++){\n    for(size_t j=0; j<8; j++){\n      if(((array[i] >> j) & 1) == 1){\n        output[8*i+(7-j)] = '1';\n      }else{\n        output[8*i+(7-j)] = '0';\n      }\n    }\n  }\n  return 8*arraySize;\n}\n\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString toBin(const uint8_t * array, size_t arraySize){\n    if(array == NULL){ return String(); }\n    size_t outputSize = arraySize * 8 + 1;\n    char * output = (char *) malloc(outputSize);\n    if(output == NULL){ return String(); }\n\n    toBin(array, arraySize, output, outputSize);\n\n    String result(output);\n\n    memzero(output, outputSize);\n    free(output);\n\n    return result;\n}\n#endif\n#if USE_ARDUINO_STRING\nsize_t toBin(uint8_t v, Print &s){\n    for(int i=7; i>=0; i--){\n        if(((v>>i) & 1)==1){\n            s.print('1');\n        }else{\n            s.print('0');\n        }\n    }\n    return 8;\n}\n\nsize_t toBin(const uint8_t * array, size_t arraySize, Print &s){\n    if(array == NULL){ return 0; }\n    size_t l = 0;\n    for(int i=0; i<arraySize; i++){\n        l += toBin(array[i], s);\n    }\n    return l;\n}\n#endif\n\n#if USE_STD_STRING || USE_ARDUINO_STRING\nsize_t fromBin(String encoded, uint8_t * output, size_t outputSize){\n    if(output == NULL){ return 0; }\n    return fromBin(encoded.c_str(), encoded.length(), output, outputSize);\n};\n#endif\n#if !(USE_ARDUINO_STRING  || USE_STD_STRING)\nsize_t fromBin(const char * hex, uint8_t * array, size_t arraySize){\n    if(hex == NULL || array == NULL){ return 0; }\n    return fromBin(hex, strlen(hex), array, arraySize);\n}\n#endif\n/******************* Base 58 conversion *******************/\n\nsize_t toBase58Length(const uint8_t * array, size_t arraySize){\n    if(array == NULL){ return 0; }\n    // Counting leading zeroes\n    size_t zeroCount = 0;\n    while(zeroCount < arraySize && !array[zeroCount]){\n        zeroCount++;\n    }\n\n    /*\n     *  Encoded string will have maximum length of\n     *  len = arraySize * log(58)/log(256) ≈ arraySize * 1.37\n     *  and should be rounded to larger value\n     *  Limitation: size_t overflow when arraySize > 65536/56 = 1170 bytes\n     *  Extra byte due to numerical error appears after 5117 bytes\n     */\n\n    size_t size = (arraySize - zeroCount) * 183 / 134 + 1;\n    // size_t size = (arraySize - zeroCount) * 137 / 100 + 1;\n    return size+zeroCount;\n}\n\nsize_t toBase58(const uint8_t * array, size_t arraySize, char * output, size_t outputSize){\n    if(array == NULL || output == NULL){ return 0; }\n    // Counting leading zeroes\n    size_t zeroCount = 0;\n    while(zeroCount < arraySize && !array[zeroCount]){\n        zeroCount++;\n    }\n\n    // TODO: refactor with real sizes\n    // size estimation. 56/41 ≈ log(58)/log(256)\n    size_t size = (arraySize - zeroCount) * 183 / 134 + 1;\n    // size_t size = (arraySize - zeroCount) * 137 / 100 + 1;\n    if(outputSize < size+zeroCount){\n        return 0;\n    }\n\n    memzero(output, outputSize);\n\n    // array copy for manipulations\n    size_t bufferSize = arraySize - zeroCount;\n    uint8_t * buffer = (uint8_t *)calloc(bufferSize, sizeof(uint8_t));\n    if(buffer == NULL){ return 0; }\n    for(size_t i = zeroCount; i < arraySize; i++){\n        buffer[i - zeroCount] = array[i];\n    }\n\n    for(size_t j = 0; j < size; j++){\n        uint16_t reminder = 0;\n        uint16_t temp = 0;\n        for(size_t i = 0; i < bufferSize; i++){\n            temp = (reminder * 256 + buffer[i]);\n            reminder = temp % 58;\n            buffer[i] = temp/58;\n        }\n        output[size+zeroCount-j-1] = BASE58_CHARS[reminder];\n    }\n    free(buffer);\n    for (size_t i = 0; i < zeroCount; i++){\n        output[i] = BASE58_CHARS[0];\n    }\n    if(outputSize > size+zeroCount){\n        output[size+zeroCount] = '\\0';\n    }\n\n    // removing leading zeroes\n    // TODO: refactor\n    int shift = 0;\n    for(size_t i=zeroCount; i < size+zeroCount; i++){\n        if(output[i]==BASE58_CHARS[0]){\n            shift++;\n        }else{\n            break;\n        }\n    }\n    if(shift>0){\n        for(size_t i=zeroCount+shift; i < size+zeroCount; i++){\n            output[i-shift] = output[i];\n            output[i] = 0;\n        }\n    }\n    size_t l = size+zeroCount-shift;\n    memzero(output + l, outputSize-l);\n    return l;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString toBase58(const uint8_t * array, size_t arraySize){\n    if(array == NULL){ return String(); }\n    size_t len = toBase58Length(array, arraySize) + 1; // +1 for null terminator\n    char * buf = (char *)malloc(len);\n    if(buf == NULL){ return String(); }\n    toBase58(array, arraySize, buf, len);\n    String result(buf);\n    free(buf);\n    return result;\n}\n#endif\n\nsize_t toBase58Check(const uint8_t * array, size_t arraySize, char * output, size_t outputSize){\n    if(array == NULL || output == NULL){ return 0; }\n    uint8_t * arr = (uint8_t *) malloc(arraySize+4);\n    if(arr == NULL){ return 0; }\n    memcpy(arr, array, arraySize);\n\n    uint8_t hash[32];\n    doubleSha(arr, arraySize, hash);\n    memcpy(arr+arraySize, hash, 4);\n\n    size_t l = toBase58(arr, arraySize+4, output, outputSize);\n    memzero(arr, arraySize+4); // secret should not stay in RAM\n    free(arr);\n    return l;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString toBase58Check(const uint8_t * array, size_t arraySize){\n    if(array == NULL){ return String(); }\n    size_t len = toBase58Length(array, arraySize + 4) + 1; // +4 checksum +1 for null terminator\n    char * buf = (char *)malloc(len);\n    if(buf == NULL){ return String(); }\n    toBase58Check(array, arraySize, buf, len);\n    String result(buf);\n    free(buf);\n    return result;\n}\n#endif\n\n\n// TODO: add zero count, fix wrong length\nsize_t fromBase58Length(const char * array, size_t arraySize){\n    if(array == NULL){ return 0; }\n    size_t size = arraySize * 361 / 493 + 1;\n    return size;\n}\n\nsize_t fromBase58(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize){\n    if(encoded == NULL || output == NULL){ return 0; }\n    memzero(output, outputSize);\n\n    size_t l;\n    // looking for the end of char array\n    for(l=0; l<encodedSize; l++){\n        const char * pch = strchr(BASE58_CHARS, encoded[l]);\n        if(pch==NULL){ // char not in the alphabet\n            break;\n        }\n    }\n    encodedSize = l;\n    size_t size = fromBase58Length(encoded, encodedSize);\n    uint8_t * tmp = (uint8_t *) calloc(size, sizeof(uint8_t));\n    if(tmp == NULL){ return 0; }\n\n    uint8_t zeroCount = 0;\n    for(size_t i = 0; i<encodedSize; i++){\n        if(encoded[i] == BASE58_CHARS[0]){\n            zeroCount++;\n        }else{\n            break;\n        }\n    }\n\n    uint16_t val = 0;\n    for(size_t i = 0; i < encodedSize; i++){\n        const char * pch = strchr(BASE58_CHARS, encoded[i]);\n        if(pch!=NULL){\n            val = pch - BASE58_CHARS;\n            for(size_t j = 0; j < size; j++){\n                uint16_t cur = tmp[size-j-1]*58;\n                cur += val;\n                val = cur/256;\n                tmp[size-j-1] = cur%256;\n            }\n        }else{\n            free(tmp);\n            return 0;\n        }\n    }\n    // shifting array\n    uint8_t shift = 0;\n    for(size_t i = zeroCount; i < size; i++){\n        if(tmp[i] == 0){\n            shift++;\n        }else{\n            break;\n        }\n    }\n    if(size-shift > outputSize){\n        free(tmp);\n        return 0;\n    }\n    memcpy(output, tmp+shift, size-shift);\n    free(tmp);\n    return size-shift;\n}\n\nsize_t fromBase58Check(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize){\n    if(encoded == NULL || output == NULL){ return 0; }\n    uint8_t * arr = (uint8_t *) malloc(outputSize+4);\n    if(arr == NULL){ return 0; }\n    size_t l = fromBase58(encoded, encodedSize, arr, outputSize+4);\n    if(l<4){\n        free(arr);\n        return 0;\n    }\n\n    uint8_t hash[32];\n    doubleSha(arr, l-4, hash);\n    if(memcmp(arr+l-4, hash, 4)!=0){\n        free(arr);\n        return 0;\n    }\n\n    memcpy(output, arr, l-4);\n\n    memzero(arr, outputSize+4); // secret should not stay in RAM\n    free(arr);\n    return l-4;\n}\n\n#if USE_STD_STRING || USE_ARDUINO_STRING\nsize_t fromBase58(String encoded, uint8_t * output, size_t outputSize){\n    return fromBase58(encoded.c_str(), encoded.length(), output, outputSize);\n};\nsize_t fromBase58Check(String encoded, uint8_t * output, size_t outputSize){\n    return fromBase58Check(encoded.c_str(), encoded.length(), output, outputSize);\n};\n#endif\n#if !(USE_ARDUINO_STRING || USE_STD_STRING)\nsize_t fromBase58(const char * encoded, uint8_t * array, size_t arraySize){\n    return fromBase58(encoded, strlen(encoded), array, arraySize);\n}\nsize_t fromBase58Check(const char * encoded, uint8_t * array, size_t arraySize){\n    return fromBase58Check(encoded, strlen(encoded), array, arraySize);\n}\n#endif\n\n/******************* Base 43 conversion *******************/\n\nsize_t toBase43Length(const uint8_t * array, size_t arraySize){\n    if(array == NULL){ return 0; }\n    // Counting leading zeroes\n    size_t zeroCount = 0;\n    while(zeroCount < arraySize && !array[zeroCount]){\n        zeroCount++;\n    }\n    // size estimation. log(256)/log(43)\n    size_t size = (arraySize - zeroCount) * 148 / 100 + 1;\n    return size+zeroCount;\n}\n\nsize_t toBase43(const uint8_t * array, size_t arraySize, char * output, size_t outputSize){\n    if(array == NULL || output == NULL){ return 0; }\n    // Counting leading zeroes\n    size_t zeroCount = 0;\n    while(zeroCount < arraySize && !array[zeroCount]){\n        zeroCount++;\n    }\n\n    // TODO: refactor with real sizes\n    // size estimation. log(256)/log(43)\n    size_t size = (arraySize - zeroCount) * 148 / 100 + 1;\n    if(outputSize < size+zeroCount){\n        return 0;\n    }\n\n    memzero(output, outputSize);\n\n    // array copy for manipulations\n    size_t bufferSize = arraySize - zeroCount;\n    uint8_t * buffer = (uint8_t *)calloc(bufferSize, sizeof(uint8_t));\n    if(buffer == NULL){ return 0; }\n    for(size_t i = zeroCount; i < arraySize; i++){\n        buffer[i - zeroCount] = array[i];\n    }\n\n    for(size_t j = 0; j < size; j++){\n        uint16_t reminder = 0;\n        uint16_t temp = 0;\n        for(size_t i = 0; i < bufferSize; i++){\n            temp = (reminder * 256 + buffer[i]);\n            reminder = temp % 43;\n            buffer[i] = temp/43;\n        }\n        output[size+zeroCount-j-1] = BASE43_CHARS[reminder];\n    }\n    free(buffer);\n    for (size_t i = 0; i < zeroCount; i++){\n        output[i] = BASE43_CHARS[0];\n    }\n    if(outputSize > size+zeroCount){\n        output[size+zeroCount] = '\\0';\n    }\n\n    // removing leading zeroes\n    // TODO: refactor\n    int shift = 0;\n    for(size_t i=zeroCount; i < size+zeroCount; i++){\n        if(output[i]==BASE43_CHARS[0]){\n            shift++;\n        }else{\n            break;\n        }\n    }\n    if(shift>0){\n        for(size_t i=zeroCount+shift; i < size+zeroCount; i++){\n            output[i-shift] = output[i];\n            output[i] = 0;\n        }\n    }\n    size_t l = size+zeroCount-shift;\n    memzero(output + l, outputSize-l);\n    return l;\n}\n#if (USE_STD_STRING || USE_ARDUINO_STRING)\nString toBase43(const uint8_t * array, size_t arraySize){\n    if(array == NULL){ return String(); }\n    size_t l = toBase43Length(array, arraySize);\n    char * output = (char *)calloc(l+1, sizeof(char));\n    if(output == NULL){ return String(); }\n    toBase43(array, arraySize, output, l);\n    String s(output);\n    free(output);\n    return s;\n}\n#endif\n// TODO: add zero count, fix wrong length\nsize_t fromBase43Length(const char * array, size_t arraySize){\n    if(array == NULL){ return 0; }\n    size_t size = arraySize * 68 / 100 + 1;\n    return size;\n}\n\nsize_t fromBase43(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize){\n    if(encoded == NULL || output == NULL){ return 0; }\n    memzero(output, outputSize);\n\n    size_t l;\n    // looking for the end of char array\n    for(l=0; l<encodedSize; l++){\n        const char * pch = strchr(BASE43_CHARS, encoded[l]);\n        if(pch==NULL){ // char not in the alphabet\n            break;\n        }\n    }\n    encodedSize = l;\n    size_t size = fromBase43Length(encoded, encodedSize);\n    uint8_t * tmp = (uint8_t *) calloc(size, sizeof(uint8_t));\n    if(tmp == NULL){ return 0; }\n\n    uint8_t zeroCount = 0;\n    for(size_t i = 0; i<encodedSize; i++){\n        if(encoded[i] == BASE43_CHARS[0]){\n            zeroCount++;\n        }else{\n            break;\n        }\n    }\n\n    uint16_t val = 0;\n    for(size_t i = 0; i < encodedSize; i++){\n        const char * pch = strchr(BASE43_CHARS, encoded[i]);\n        if(pch!=NULL){\n            val = pch - BASE43_CHARS;\n            for(size_t j = 0; j < size; j++){\n                uint16_t cur = tmp[size-j-1]*43;\n                cur += val;\n                val = cur/256;\n                tmp[size-j-1] = cur%256;\n            }\n        }else{\n            free(tmp);\n            return 0;\n        }\n    }\n    // shifting array\n    uint8_t shift = 0;\n    for(size_t i = zeroCount; i < size; i++){\n        if(tmp[i] == 0){\n            shift++;\n        }else{\n            break;\n        }\n    }\n    if(size-shift > outputSize){\n        free(tmp);\n        return 0;\n    }\n    memcpy(output, tmp+shift, size-shift);\n    free(tmp);\n    return size-shift;\n}\n#if (USE_STD_STRING || USE_ARDUINO_STRING)\nsize_t fromBase43(String encoded, uint8_t * output, size_t outputSize){\n    return fromBase43(encoded.c_str(), encoded.length(), output, outputSize);\n};\n#endif\n#if !(USE_ARDUINO_STRING || USE_STD_STRING)\nsize_t fromBase43(const char * encoded, uint8_t * array, size_t arraySize){\n    return fromBase43(encoded, strlen(encoded), array, arraySize);\n}\n#endif\n\n/******************* Base 64 conversion *******************/\n\nsize_t toBase64Length(const uint8_t * array, size_t arraySize, uint8_t flags){\n    if(array == NULL){ return 0; }\n    size_t v = (arraySize / 3) * 4;\n    if(arraySize % 3 != 0){\n        if(flags & BASE64_NOPADDING){\n            v += (arraySize % 3) + 1;\n        }else{\n            v += 4;\n        }\n    }\n    return v;\n}\nsize_t toBase64(const uint8_t * array, size_t arraySize, char * output, size_t outputSize, uint8_t flags){\n    if(array == NULL || output == NULL){ return 0; }\n    memzero(output, outputSize);\n    size_t cur = 0;\n    if(outputSize < toBase64Length(array, arraySize, flags)){\n        return 0;\n    }\n    while(3 * cur + 3 < arraySize){\n        uint32_t val = bigEndianToInt(array+3*cur, 3);\n        for(uint8_t i=0; i<4; i++){\n            output[4*cur + i] = BASE64_CHARS[((val >> (6*(3-i))) & 0x3F)];\n        }\n        cur++;\n    }\n    size_t len = cur * 4;\n    if(arraySize % 3 != 0){\n        uint8_t rem = arraySize % 3;\n        uint32_t val = bigEndianToInt(array+3*cur, rem);\n        val = val << ((3-rem) * 8);\n        for(uint8_t i=0; i<(rem+1); i++){\n            output[4*cur + i] = BASE64_CHARS[((val >> (6*(3-i))) & 0x3F)];\n        }\n        if(flags & BASE64_NOPADDING){\n            len += (rem+1);\n        }else{\n            memset(output + 4 * cur + 1 + rem, '=', 3-rem);\n            len += 4;\n        }\n    }else{\n        uint32_t val = bigEndianToInt(array+3*cur, 3);\n        for(uint8_t i=0; i<4; i++){\n            output[4*cur + i] = BASE64_CHARS[((val >> (6*(3-i))) & 0x3F)];\n        }\n        len += 4;\n    }\n    // replace with urlsafe characters\n    if(flags & BASE64_URLSAFE){\n        for(size_t i=0; i<len; i++){\n            if(output[i] == '+'){\n                output[i] = '-';\n            }\n            if(output[i] == '/'){\n                output[i] = '_';\n            }\n        }\n    }\n    return len;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString toBase64(const uint8_t * array, size_t arraySize, uint8_t flags){\n    if(array == NULL){ return String(); }\n    size_t len = toBase64Length(array, arraySize, flags) + 1; // +1 for null terminator\n    char * buf = (char *)malloc(len);\n    if(buf==NULL){ return String(); }\n    toBase64(array, arraySize, buf, len, flags);\n    String result(buf);\n    free(buf);\n    return result;\n}\n#endif\nsize_t fromBase64Length(const char * array, size_t arraySize, uint8_t flags){\n    if(array == NULL){ return 0; }\n    if(arraySize % 4 != 0 && (flags & BASE64_NOPADDING) == 0){ return 0; }\n    size_t v = (arraySize / 4) * 3;\n    if(flags & BASE64_NOPADDING){\n        if(arraySize % 4 != 0){\n            v += (arraySize % 4)-1;\n        }\n    }else{\n        if(array[arraySize-1] == '='){\n            v--;\n        }\n        if(array[arraySize-2] == '='){\n            v--;\n        }\n    }\n    return v;\n}\nsize_t fromBase64(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize, uint8_t flags){\n    if(encoded == NULL || output == NULL){ return 0; }\n    size_t cur = 0;\n    memzero(output, outputSize);\n    if(outputSize < fromBase64Length(encoded, encodedSize, flags)){\n        return 0;\n    }\n    while(cur*4 < encodedSize){\n        if(cur*4+3 >= encodedSize && (flags & BASE64_NOPADDING) == 0){\n            memzero(output, outputSize);\n            return 0;\n        }\n        uint32_t val = 0;\n        for(size_t i=0; i<4; i++){\n            char c = encoded[cur*4+i];\n            // replace characters for urlsafe version\n            if(c=='-' && (flags & BASE64_URLSAFE)){\n                c = '+';\n            }\n            if(c=='_' && (flags & BASE64_URLSAFE)){\n                c = '/';\n            }\n            const char * pch = strchr(BASE64_CHARS, c);\n            if(pch==NULL || ((flags & BASE64_NOPADDING) && (c == 0))){\n                if((encoded[cur*4+i] == '=') || (c == 0 && (flags & BASE64_NOPADDING))){\n                    if(i==3){\n                        val = (val >> 2);\n                        if(outputSize < 3*cur+2){\n                            memzero(output, outputSize);\n                            return 0;\n                        }\n                        intToBigEndian(val, output+3*cur, 2);\n                        return 3*cur + 2;\n                    }\n                    if(i==2){\n                        val = (val >> 4);\n                        if(outputSize < 3*cur+1){\n                            memzero(output, outputSize);\n                            return 0;\n                        }\n                        output[3*cur] = (val & 0xFF);\n                        return 3*cur + 1;\n                    }\n                }\n                memzero(output, outputSize);\n                return 0;\n            }else{\n                val = (val << 6) + ((pch - BASE64_CHARS) & 0x3F);\n            }\n        }\n        if(outputSize < 3*(cur+1)){\n            memzero(output, outputSize);\n            return 0;\n        }\n        intToBigEndian(val, output+3*cur, 3);\n        cur++;\n    }\n    return 3 * cur;\n}\n#if USE_STD_STRING || USE_ARDUINO_STRING\nsize_t fromBase64(String encoded, uint8_t * output, size_t outputSize, uint8_t flags){\n    return fromBase64(encoded.c_str(), encoded.length(), output, outputSize, flags);\n};\nString base64ToHex(String b64, uint8_t flags){\n    size_t len = fromBase64Length(b64.c_str(), strlen(b64.c_str()), flags) + 1; // +1 for null terminator\n    uint8_t * buf = (uint8_t *)malloc(len);\n    if(buf==NULL){ return String(); }\n    len = fromBase64(b64, buf, len, flags);\n    String result = toHex(buf, len);\n    free(buf);\n    return result;\n};\nString hexToBase64(String hex, uint8_t flags){\n    size_t len = strlen(hex.c_str())/2+1; // +1 for null terminator\n    uint8_t * buf = (uint8_t *)malloc(len);\n    if(buf==NULL){ return String(); }\n    len = fromHex(hex, buf, len);\n    String result = toBase64(buf, len, flags);\n    free(buf);\n    return result;\n};\n#endif\n#if !(USE_ARDUINO_STRING  || USE_STD_STRING)\nsize_t fromBase64(const char * b64, uint8_t * array, size_t arraySize, uint8_t flags){\n    if(b64 == NULL || array == NULL){ return 0; }\n    return fromBase64(b64, strlen(b64), array, arraySize, flags);\n}\n#endif\n\n/* Integer conversion */\n\nuint64_t littleEndianToInt(const uint8_t * array, size_t arraySize){\n    uint64_t num = 0;\n    for(size_t i = 0; i < arraySize; i++){\n        num <<= 8;\n        num += (array[arraySize-i-1] & 0xFF);\n    }\n    return num;\n}\n\nvoid intToLittleEndian(uint64_t num, uint8_t * array, size_t arraySize){\n    for(size_t i = 0; i < arraySize; i++){\n        array[i] = ((num >> (8*i)) & 0xFF);\n    }\n}\n\nuint64_t bigEndianToInt(const uint8_t * array, size_t arraySize){\n    uint64_t num = 0;\n    for(size_t i = 0; i < arraySize; i++){\n        num <<= 8;\n        num += (array[i] & 0xFF);\n    }\n    return num;\n}\n\nvoid intToBigEndian(uint64_t num, uint8_t * array, size_t arraySize){\n    for(size_t i = 0; i < arraySize; i++){\n        array[arraySize-i-1] = ((num >> (8*i)) & 0xFF);\n    }\n}\n\n/* Varint */\n\nuint8_t lenVarInt(uint64_t num){\n    if(num < 0xfd){\n        return 1;\n    }\n    if((num >> 16) == 0){\n        return 3;\n    }\n    if((num >> 32) == 0){\n        return 5;\n    }\n    return 9;\n}\nuint64_t readVarInt(const uint8_t * array, size_t arraySize){\n    if(array[0] < 0xfd){\n        return array[0];\n    }else{\n        size_t len = (1 << (array[0] - 0xfc));\n        if(len+1 > arraySize){\n            return 0;\n        }\n        return littleEndianToInt(array + 1, len);\n    }\n}\n\n// TODO: don't repeat yourself!\nsize_t writeVarInt(uint64_t num, uint8_t * array, size_t arraySize){\n    uint8_t len = lenVarInt(num);\n    if(arraySize < len){\n        return 0;\n    }\n    if(len == 1){\n        array[0] = (uint8_t)(num & 0xFF);\n    }else{\n        switch(len){\n            case 3: array[0] = 0xfd;\n                    break;\n            case 5: array[0] = 0xfe;\n                    break;\n            case 9: array[0] = 0xff;\n                    break;\n        }\n        intToLittleEndian(num, array+1, len-1);\n    }\n    return len;\n}\n\n"
  },
  {
    "path": "src/Conversion.h",
    "content": "#ifndef __CONVERSION_H__\n#define __CONVERSION_H__\n\n#include \"uBitcoin_conf.h\"\n\n#include <string.h>\n#include <stdint.h>\n#include \"utility/segwit_addr.h\"\n\n\n#define BASE64_STANDARD  0\n#define BASE64_NOPADDING 1\n#define BASE64_URLSAFE   2\n\n// TODO: get rid of these blahLength functions, they are redundant\n//       just stop when array is full and return errorcode\n\nsize_t toBase58Length(const uint8_t * array, size_t arraySize);\nsize_t toBase58(const uint8_t * array, size_t arraySize, char * output, size_t outputSize);\n#if USE_ARDUINO_STRING\nString toBase58(const uint8_t * array, size_t arraySize);\n#endif\n#if USE_STD_STRING\nstd::string toBase58(const uint8_t * array, size_t arraySize);\n#endif\n\n\n// base58 conversion with 4-byte checksum at the end (doubleSha)\nsize_t toBase58Check(const uint8_t * array, size_t arraySize, char * output, size_t outputSize);\n#if USE_ARDUINO_STRING\nString toBase58Check(const uint8_t * array, size_t arraySize);\n#endif\n#if USE_STD_STRING\nstd::string toBase58Check(const uint8_t * array, size_t arraySize);\n#endif\n\nsize_t fromBase58Length(const char * array, size_t arraySize);\nsize_t fromBase58(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize);\nsize_t fromBase58Check(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize);\n#if !(USE_ARDUINO_STRING || USE_STD_STRING)\nsize_t fromBase58(const char * encoded, uint8_t * array, size_t arraySize);\nsize_t fromBase58Check(const char * encoded, uint8_t * array, size_t arraySize);\n#endif\n#if USE_ARDUINO_STRING\nsize_t fromBase58(String encoded, uint8_t * output, size_t outputSize);\nsize_t fromBase58Check(String encoded, uint8_t * output, size_t outputSize);\n#endif\n#if USE_STD_STRING\nsize_t fromBase58(std::string encoded, uint8_t * output, size_t outputSize);\nsize_t fromBase58Check(std::string encoded, uint8_t * output, size_t outputSize);\n#endif\n\nsize_t toBase43Length(const uint8_t * array, size_t arraySize);\nsize_t toBase43(const uint8_t * array, size_t arraySize, char * output, size_t outputSize);\n#if USE_ARDUINO_STRING\nString toBase43(const uint8_t * array, size_t arraySize);\n#endif\n#if USE_STD_STRING\nstd::string toBase43(const uint8_t * array, size_t arraySize);\n#endif\nsize_t fromBase43Length(const char * array, size_t arraySize);\nsize_t fromBase43(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize);\n#if !(USE_ARDUINO_STRING || USE_STD_STRING)\nsize_t fromBase43(const char * encoded, uint8_t * array, size_t arraySize);\n#endif\n#if USE_ARDUINO_STRING\nsize_t fromBase43(String encoded, uint8_t * output, size_t outputSize);\n#endif\n#if USE_STD_STRING\nsize_t fromBase43(std::string encoded, uint8_t * output, size_t outputSize);\n#endif\n\nsize_t toHex(const uint8_t * array, size_t arraySize, char * output, size_t outputSize);\n#if USE_ARDUINO_STRING\nString toHex(const uint8_t * array, size_t arraySize);\nsize_t toHex(uint8_t v, Print &s); // printing single hex value to Print\nsize_t toHex(const uint8_t * array, size_t arraySize, Print &s); // TODO: pass pointer instead printing array in hex Print\n#endif\n#if USE_STD_STRING\nstd::string toHex(const uint8_t * array, size_t arraySize);\n#endif\nsize_t fromHex(const char * hex, size_t hexLen, uint8_t * array, size_t arraySize);\nuint8_t hexToVal(char c);\n#if !(USE_ARDUINO_STRING  || USE_STD_STRING)\nsize_t fromHex(const char * hex, uint8_t * array, size_t arraySize);\n#endif\n#if USE_ARDUINO_STRING\nsize_t fromHex(String encoded, uint8_t * output, size_t outputSize);\n#endif\n#if USE_STD_STRING\nsize_t fromHex(std::string encoded, uint8_t * output, size_t outputSize);\n#endif\n\nsize_t toBin(const uint8_t * array, size_t arraySize, char * output, size_t outputSize);\n#if USE_ARDUINO_STRING\nString toBin(const uint8_t * array, size_t arraySize);\nsize_t toBin(uint8_t v, Print &s); // printing single value to Print\nsize_t toBin(const uint8_t * array, size_t arraySize, Print &s);\n#endif\n#if USE_STD_STRING\nstd::string toBin(const uint8_t * array, size_t arraySize);\n#endif\nsize_t fromBin(const char * bin, size_t binLen, uint8_t * array, size_t arraySize);\n#if !(USE_ARDUINO_STRING  || USE_STD_STRING)\nsize_t fromBin(const char * hex, uint8_t * array, size_t arraySize);\n#endif\n#if USE_ARDUINO_STRING\nsize_t fromBin(String encoded, uint8_t * output, size_t outputSize);\n#endif\n#if USE_STD_STRING\nsize_t fromBin(std::string encoded, uint8_t * output, size_t outputSize);\n#endif\n\nsize_t toBase64Length(const uint8_t * array, size_t arraySize, uint8_t flags = BASE64_STANDARD);\nsize_t toBase64(const uint8_t * array, size_t arraySize, char * output, size_t outputSize, uint8_t flags = BASE64_STANDARD);\n#if USE_ARDUINO_STRING\nString toBase64(const uint8_t * array, size_t arraySize, uint8_t flags = BASE64_STANDARD);\n#endif\n#if USE_STD_STRING\nstd::string toBase64(const uint8_t * array, size_t arraySize, uint8_t flags = BASE64_STANDARD);\n#endif\nsize_t fromBase64Length(const char * array, size_t arraySize, uint8_t flags = BASE64_STANDARD);\nsize_t fromBase64(const char * encoded, size_t encodedSize, uint8_t * output, size_t outputSize, uint8_t flags = BASE64_STANDARD);\n#if !(USE_ARDUINO_STRING  || USE_STD_STRING)\nsize_t fromBase64(const char * encoded, uint8_t * array, size_t arraySize, uint8_t flags = BASE64_STANDARD);\n#endif\n#if USE_ARDUINO_STRING\nsize_t fromBase64(String encoded, uint8_t * output, size_t outputSize, uint8_t flags = BASE64_STANDARD);\nString base64ToHex(String b64, uint8_t flags = BASE64_STANDARD);\nString hexToBase64(String hex, uint8_t flags = BASE64_STANDARD);\n#endif\n#if USE_STD_STRING\nsize_t fromBase64(std::string encoded, uint8_t * output, size_t outputSize, uint8_t flags = BASE64_STANDARD);\nstd::string base64ToHex(std::string b64, uint8_t flags = BASE64_STANDARD);\nstd::string hexToBase64(std::string hex, uint8_t flags = BASE64_STANDARD);\n#endif\n\n/* int conversion */\nuint64_t littleEndianToInt(const uint8_t * array, size_t arraySize);\nvoid intToLittleEndian(uint64_t num, uint8_t * array, size_t arraySize);\nuint64_t bigEndianToInt(const uint8_t * array, size_t arraySize);\nvoid intToBigEndian(uint64_t num, uint8_t * array, size_t arraySize);\n\n/* varint */\nuint8_t lenVarInt(uint64_t num); // returns length of the array required for varint encoding\nuint64_t readVarInt(const uint8_t * array, size_t arraySize);\nsize_t writeVarInt(uint64_t num, uint8_t * array, size_t arraySize);\n\n\n#endif\n"
  },
  {
    "path": "src/Electrum.cpp",
    "content": "#include \"Electrum.h\"\n\nElectrumTx::ElectrumTx(ElectrumTx const &other){\n    tx = other.tx;\n    is_segwit = false;\n    txInsMeta = new ElectrumInputMetadata[tx.inputsNumber];\n    for(unsigned int i=0; i<tx.inputsNumber; i++){\n        txInsMeta[i] = other.txInsMeta[i];\n    }\n    status = other.status;\n    bytes_parsed = other.bytes_parsed;\n}\nElectrumTx& ElectrumTx::operator=(ElectrumTx const &other){\n    if (this == &other){ return *this; } // self-assignment\n    if(tx.inputsNumber > 0){\n        delete [] txInsMeta;\n    }\n    tx = other.tx;\n    txInsMeta = new ElectrumInputMetadata[tx.inputsNumber];\n    for(unsigned int i=0; i<tx.inputsNumber; i++){\n        txInsMeta[i] = other.txInsMeta[i];\n    }\n    status = other.status;\n    bytes_parsed = other.bytes_parsed;\n    return *this;\n}\n\nsize_t ElectrumTx::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        if(tx.inputsNumber > 0){\n            delete [] txInsMeta;\n        }\n        txInsMeta = NULL;\n        tx = Tx();\n        bytes_parsed = 0;\n        is_segwit = false;\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    uint8_t prefix[] = {0x45, 0x50, 0x54, 0x46, 0xFF, 0x00};\n    while(s->available() && bytes_read+bytes_parsed<6){\n        uint8_t c = s->read();\n        bytes_read++;\n        if(c != prefix[bytes_read+bytes_parsed-1]){\n            status = PARSING_FAILED;\n            bytes_parsed += bytes_read;\n            return bytes_read;\n        }\n    }\n    if(!is_segwit && s->available() && status == PARSING_INCOMPLETE && tx.getStatus() != PARSING_FAILED){\n        bytes_read += s->parse(&tx);\n        if(tx.getStatus() == PARSING_DONE){\n            status = PARSING_DONE;\n            is_segwit = false;\n            txInsMeta = new ElectrumInputMetadata[tx.inputsNumber];\n            for(unsigned i=0; i<tx.inputsNumber; i++){\n                if(tx.txIns[i].scriptSig.length() != 88){ // no idea how to parse other things\n                    status = PARSING_FAILED;\n                    bytes_parsed+=bytes_read;\n                    return bytes_read;\n                }else{\n                    uint8_t arr[88];\n                    tx.txIns[i].scriptSig.serialize(arr, sizeof(arr));\n                    txInsMeta[i].hd.parse(arr+6,sizeof(arr)-6);\n                    if(txInsMeta[i].hd.getStatus() != PARSING_DONE){\n                        status = PARSING_FAILED;\n                        bytes_parsed+=bytes_read;\n                        return bytes_read;\n                    }\n                    txInsMeta[i].derivation[0] = arr[84] + (arr[85] << 8);\n                    txInsMeta[i].derivation[1] = arr[86] + (arr[87] << 8);\n                    tx.txIns[i].scriptSig = Script();\n                }\n            }\n        }\n    }\n    if(tx.getStatus() == PARSING_FAILED){\n        if(tx.inputsNumber > 0 && tx.txIns[0].witness.getStatus() == PARSING_FAILED){\n            for(unsigned int i=0; i<tx.inputsNumber; i++){\n                tx.txIns[i].witness = Witness();\n            }\n            tx.setStatus(PARSING_DONE);\n            tx.locktime = 0;\n            is_segwit = true;\n            txInsMeta = new ElectrumInputMetadata[tx.inputsNumber];\n            for(unsigned int i=0; i<tx.inputsNumber; i++){\n                txInsMeta[i].amount = 0;\n                txInsMeta[i].derivation[0] = 0;\n                txInsMeta[i].derivation[1] = 0;\n            }\n        }else{\n            status = PARSING_FAILED;\n            bytes_parsed += bytes_read;\n            return bytes_read;\n        }\n    }\n    if(is_segwit && tx.getStatus() == PARSING_DONE){\n        size_t start = 6 + tx.length() + 2 - 4; // locktime is not parsed yet\n        for(unsigned int i = 0; i < tx.inputsNumber; i++){\n            while(s->available() && bytes_parsed+bytes_read < start + 5){\n                s->read(); \n                bytes_read++;\n            }\n            start += 5;\n            while(s->available() && bytes_parsed+bytes_read < start + 8){\n                uint8_t c = s->read();\n                txInsMeta[i].amount += (((uint64_t)c) << (8*(bytes_read+bytes_parsed-start)));\n                bytes_read++;\n            }\n            start += 8;\n            while(s->available() && bytes_parsed+bytes_read < start + 7){\n                s->read(); \n                bytes_read++;\n            }\n            start += 7;\n            while(s->available() && bytes_parsed+bytes_read < start + 78){\n                bytes_read+=s->parse(&txInsMeta[i].hd);\n            }\n            start += 78;\n            while(s->available() && bytes_parsed+bytes_read < start + 4){\n                uint8_t c = s->read();\n                size_t cur = bytes_parsed+bytes_read-start;\n                txInsMeta[i].derivation[cur/2] += (c << (8 * (cur % 2)));\n                bytes_read++;\n            }\n            start += 4;\n        }\n        while(s->available() && bytes_parsed+bytes_read < start + 4){\n            uint8_t c = s->read();\n            tx.locktime += (c << (8*(bytes_read+bytes_parsed-start)));\n            bytes_read++;\n        }\n        start+=4;\n        if(bytes_parsed+bytes_read == start){\n            status = PARSING_DONE;\n        }\n    }\n    bytes_parsed+=bytes_read;\n    return bytes_read;\n}\nElectrumTx::~ElectrumTx(){\n    delete [] txInsMeta;\n}\nuint8_t ElectrumTx::sign(const HDPrivateKey account){\n    uint8_t res = 0; // number of signed inputs\n    for(unsigned int i=0; i<tx.inputsNumber; i++){\n        HDPublicKey pub = account.xpub();\n        ScriptType type = txInsMeta[i].hd.type;\n        pub.type = type;\n        if(pub == txInsMeta[i].hd){\n            PrivateKey pk = account.child(txInsMeta[i].derivation[0]).child(txInsMeta[i].derivation[1]);\n            if(type == P2PKH || type == P2SH || type == UNKNOWN_TYPE || type == DIRECT_SCRIPT){\n                tx.signInput(i, pk);\n            }else{\n                tx.signSegwitInput(i, pk, txInsMeta[i].amount, type);\n            }\n            res++;\n        }\n    }\n    return res;\n}\n\nuint64_t ElectrumTx::fee() const{\n    uint64_t inputs_amount = 0;\n    for(unsigned int i=0; i < tx.inputsNumber; i++){\n        if(txInsMeta[i].amount == 0){\n            return 0;\n        }\n        inputs_amount += txInsMeta[i].amount;\n    }\n    uint64_t outputs_amount = 0;\n    for(unsigned int i=0; i < tx.outputsNumber; i++){\n        outputs_amount += tx.txOuts[i].amount;\n    }\n    if(inputs_amount < outputs_amount){\n        return 0;\n    }\n    return inputs_amount-outputs_amount;\n}\n\n"
  },
  {
    "path": "src/Electrum.h",
    "content": "#ifndef __ELECTRUM_H__\n#define __ELECTRUM_H__\n\n#include \"Bitcoin.h\"\n\n/**\n * \\brief Metadata for Electrum unsigned transaction format to determine how to sign transaction.\n *        Only partially supported - 2 derivation indexes and HD public key. Segwit and legacy.\n */\ntypedef struct{\n    HDPublicKey hd;\n    uint16_t derivation[2];\n    uint64_t amount;\n} ElectrumInputMetadata;\n/**\n *  \\brief Electrum Partially Signed Transaction class.<br>\n *         WARNING: Only partial support is implemented! No multisig and single keys.<br>\n *         For now implements only single HD key transactions are supported (no multisig).<br>\n *         If you explain me how electrum encodes unsigned multisig I will make it.\n */\nclass ElectrumTx : public Streamable{\nprotected:\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const{ return s->serialize(&tx, offset); };\n    bool is_segwit;\npublic:\n    ElectrumTx(){ txInsMeta = NULL; is_segwit = false; };\n    ElectrumTx(ElectrumTx const &other);\n    ~ElectrumTx();\n    Tx tx;\n    virtual size_t length() const{ return tx.length(); };\n\n    /** \\bried metadata for inputs */\n    ElectrumInputMetadata * txInsMeta;\n\n    /** \\brief signs all inputs with matching hd pubkey with account HDPrivateKey.\n     *         Returns number of inputs signed.\n     */\n    uint8_t sign(const HDPrivateKey account);\n    /** \\brief calculates fee if input amounts are known */\n    uint64_t fee() const;\n\n    ElectrumTx &operator=(ElectrumTx const &other);\n    \n    bool isValid() const{ return status==PARSING_DONE; };\n    explicit operator bool() const{ return isValid(); };\n};\n\n#endif // __ELECTRUM_H__\n"
  },
  {
    "path": "src/HDWallet.cpp",
    "content": "#include <stdint.h>\n#include <string.h>\n\n#include \"Bitcoin.h\"\n#include \"Hash.h\"\n#include \"Conversion.h\"\n#include \"utility/trezor/sha2.h\"\n#include \"utility/segwit_addr.h\"\n#include \"utility/trezor/bignum.h\"\n#include \"utility/trezor/ecdsa.h\"\n#include \"utility/trezor/secp256k1.h\"\n#include \"utility/trezor/memzero.h\"\n\n#if USE_STD_STRING\nusing std::string;\n#define String string\n#endif\n\n// ---------------------------------------------------------------- HDPrivateKey class\n\nvoid HDPrivateKey::init(){\n    reset();\n    memzero(chainCode, 32);\n    memzero(num, 32);\n    pubKey.compressed = true;\n    depth = 0;\n    memzero(parentFingerprint, 4);\n    childNumber = 0;\n    type = UNKNOWN_TYPE;\n    status = PARSING_DONE;\n    pubKey.compressed = true;\n}\nHDPrivateKey::HDPrivateKey(void){\n    init();\n}\nHDPrivateKey::HDPrivateKey(const uint8_t secret[32],\n                           const uint8_t chain_code[32],\n                           uint8_t key_depth,\n                           const uint8_t parent_fingerprint_arr[4],\n                           uint32_t child_number,\n                           const Network * net,\n                           ScriptType key_type){\n    init();\n    memcpy(num, secret, 32);\n    network = net;\n    pubKey = *this * GeneratorPoint;\n    pubKey.compressed = true;\n    type = key_type;\n    memcpy(chainCode, chain_code, 32);\n    depth = key_depth;\n    childNumber = child_number;\n    if(parent_fingerprint_arr != NULL){\n        memcpy(parentFingerprint, parent_fingerprint_arr, 4);\n    }else{\n        memzero(parentFingerprint, 4);\n    }\n}\n/*\nHDPrivateKey &HDPrivateKey::operator=(const HDPrivateKey &other){\n    if (this == &other){ return *this; } // self-assignment\n    init();\n    type = other.type;\n    uint8_t secret[32];\n    other.getSecret(secret);\n    setSecret(secret);\n    memcpy(chainCode, other.chainCode, 32);\n    depth = other.depth;\n    childNumber = other.childNumber;\n    memcpy(parentFingerprint, other.parentFingerprint, 4);\n    return *this;\n};*/\nHDPrivateKey::HDPrivateKey(const char * xprvArr){\n    init();\n    from_str(xprvArr, strlen(xprvArr));\n}\nHDPrivateKey::HDPrivateKey(const char * mnemonic, size_t mnemonicSize, const char * password, size_t passwordSize, const Network * net, void (*progress_callback)(float)){\n    init();\n    fromMnemonic(mnemonic, mnemonicSize, password, passwordSize, net, progress_callback);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nHDPrivateKey::HDPrivateKey(String mnemonic, String password, const Network * net, void (*progress_callback)(float)){\n    init();\n    fromMnemonic(mnemonic, password, net, progress_callback);\n}\n#endif\nHDPrivateKey::~HDPrivateKey(void) {\n    memzero(chainCode, 32);\n    memzero(num, 32);\n}\nsize_t HDPrivateKey::to_bytes(uint8_t * arr, size_t len) const{\n    uint8_t hex[78] = { 0 };\n    switch(type){\n        case P2WPKH:\n            memcpy(hex, network->zprv, 4);\n            break;\n        case P2SH_P2WPKH:\n            memcpy(hex, network->yprv, 4);\n            break;\n        case P2WSH:\n            memcpy(hex, network->Zprv, 4);\n            break;\n        case P2SH_P2WSH:\n            memcpy(hex, network->Yprv, 4);\n            break;\n        default:\n            memcpy(hex, network->xprv, 4);\n    }\n    hex[4] = depth;\n    memcpy(hex+5, parentFingerprint, 4);\n    for(uint8_t i=0; i<4; i++){\n        hex[12-i] = ((childNumber >> (i*8)) & 0xFF);\n    }\n    memcpy(hex+13, chainCode, 32);\n    memcpy(hex+46, num, 32);\n    if(len > sizeof(hex)){\n        len = sizeof(hex);\n    }\n    memcpy(arr, hex, len);\n    return len;\n}\nsize_t HDPrivateKey::to_stream(SerializeStream *s, size_t offset) const{\n    uint8_t hex[78] = { 0 };\n    size_t bytes_written = 0;\n    to_bytes(hex, sizeof(hex));\n    while(s->available() && bytes_written+offset < sizeof(hex)){\n        s->write(hex[bytes_written+offset]);\n        bytes_written++;\n    }\n    return bytes_written;\n}\nsize_t HDPrivateKey::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    // reading the prefix\n    while(s->available() > 0 && bytes_parsed+bytes_read < 4){\n        prefix[bytes_parsed+bytes_read] = s->read();\n        bytes_read++;\n    }\n    if(bytes_parsed+bytes_read == 4){\n        bool found = false;\n        for(int i=0; i<networks_len; i++){\n            if(memcmp(prefix, networks[i]->xprv, 4)==0){\n                type = UNKNOWN_TYPE;\n                found = true;\n                network = networks[i];\n                break;\n            }else if(memcmp(prefix, networks[i]->yprv, 4)==0){\n                type = P2SH_P2WPKH;\n                found = true;\n                network = networks[i];\n                break;\n            }else if(memcmp(prefix, networks[i]->zprv, 4)==0){\n                type = P2WPKH;\n                found = true;\n                network = networks[i];\n                break;\n            }else if(memcmp(prefix, networks[i]->Yprv, 4)==0){\n                type = P2SH_P2WSH;\n                found = true;\n                network = networks[i];\n                break;\n            }else if(memcmp(prefix, networks[i]->Zprv, 4)==0){\n                type = P2WSH;\n                found = true;\n                network = networks[i];\n                break;\n            }\n        }\n        if(!found){\n            status = PARSING_FAILED;\n            return bytes_read;\n        }\n    }\n    // depth\n    if(s->available() > 0 && bytes_parsed+bytes_read < 5){\n        depth = s->read();\n        bytes_read++;\n    }\n    // fingerprint\n    while(s->available() > 0 && bytes_parsed+bytes_read < 9){\n        parentFingerprint[bytes_parsed+bytes_read-5] = s->read();\n        bytes_read++;\n    }\n    // childnumber\n    while(s->available() > 0 && bytes_parsed+bytes_read < 13){\n        childNumber <<= 8;\n        childNumber += s->read();\n        bytes_read++;\n    }\n    // chaincode\n    while(s->available() > 0 && bytes_parsed+bytes_read < 45){\n        chainCode[bytes_parsed+bytes_read-13] = s->read();\n        bytes_read++;\n    }\n    // 00 before the private key\n    if(s->available() && bytes_parsed+bytes_read < 46){\n        uint8_t c = s->read();\n        bytes_read++;\n        if(c != 0){\n            status = PARSING_FAILED;\n            return bytes_read;\n        }\n    }\n    // num\n    while(s->available() > 0 && bytes_parsed+bytes_read < 78){\n        num[bytes_parsed+bytes_read-46] = s->read();\n        bytes_read++;\n    }\n    if(bytes_parsed+bytes_read == 78){\n        status = PARSING_DONE;\n        uint8_t zero[32] = { 0 };\n        if(memcmp(num, zero, 32)==0){ // should we add something else here?\n            status = PARSING_FAILED;\n        }\n        bignum256 n;\n        bn_read_be(num, &n);\n        bn_mod(&n, &secp256k1.order);\n        bn_write_be(&n, num);\n        pubKey = *this * GeneratorPoint;\n        pubKey.compressed = true;\n    }\n    bytes_parsed += bytes_read;\n    return bytes_read;\n}\nsize_t HDPrivateKey::from_str(const char * xprvArr, size_t xprvLen){\n    init();\n    uint8_t arr[85] = { 0 };\n    size_t l = fromBase58Check(xprvArr, xprvLen, arr, sizeof(arr));\n    if(l == 0){\n        return 0; // decoding error\n    }\n    ParseByteStream s(arr, sizeof(arr));\n    HDPrivateKey::from_stream(&s);\n    return xprvLen;\n}\nint HDPrivateKey::fromSeed(const uint8_t * seed, size_t seedSize, const Network * net){\n    init();\n    uint8_t raw[64] = { 0 };\n    SHA512 sha;\n    char key[] = \"Bitcoin seed\";\n    sha.beginHMAC((uint8_t *)key, strlen(key));\n    sha.write(seed, seedSize);\n    sha.endHMAC(raw);\n    // sha512Hmac((byte *)key, strlen(key), seed, 64, raw);\n    memcpy(num, raw, 32);\n    network = net;\n    memcpy(chainCode, raw+32, 32);\n    pubKey = *this * GeneratorPoint;\n    pubKey.compressed = true;\n    return 1;\n}\n// int HDPrivateKey::fromSeed(const uint8_t seed[64], const Network * net){\n//     fromSeed(seed, 64);\n// }\nint HDPrivateKey::fromMnemonic(const char * mnemonic, size_t mnemonicSize, const char * password, size_t passwordSize, const Network * net, void (*progress_callback)(float)){\n    init();\n    uint8_t seed[64] = { 0 };\n    uint8_t ind[4] = { 0, 0, 0, 1 };\n    char salt[] = \"mnemonic\";\n    uint8_t u[64] = { 0 };\n\n    // first round\n    SHA512 sha;\n    sha.beginHMAC((uint8_t *)mnemonic, mnemonicSize);\n    sha.write((uint8_t *)salt, strlen(salt));\n    sha.write((uint8_t *)password, passwordSize);\n    sha.write(ind, sizeof(ind));\n    sha.endHMAC(u);\n    memcpy(seed, u, 64);\n    // other rounds\n    for(int i=1; i<PBKDF2_ROUNDS; i++){\n        if(progress_callback != NULL && (i & 0xFF) == 0xFF){\n            progress_callback((float)i/(float)(PBKDF2_ROUNDS-1));\n        }\n        sha.beginHMAC((uint8_t *)mnemonic, mnemonicSize);\n        sha.write(u, sizeof(u));\n        sha.endHMAC(u);\n        for(size_t j=0; j<sizeof(seed); j++){\n            seed[j] = seed[j] ^ u[j];\n        }\n    }\n    fromSeed(seed, sizeof(seed), net);\n    return 1;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nint HDPrivateKey::fromMnemonic(String mnemonic, String password, const Network * net, void (*progress_callback)(float)){\n    return fromMnemonic(mnemonic.c_str(), mnemonic.length(), password.c_str(), password.length(), net, progress_callback);\n}\n#endif\nint HDPrivateKey::xprv(char * arr, size_t len) const{\n    uint8_t hex[78] = { 0 };\n    to_bytes(hex, sizeof(hex));\n    return toBase58Check(hex, sizeof(hex), arr, len);\n}\nint HDPrivateKey::address(char * addr, size_t len) const{\n    switch(type){\n        case P2WPKH:\n            return segwitAddress(addr, len);\n        case P2SH_P2WPKH:\n            return nestedSegwitAddress(addr, len);\n        case P2PKH:\n            return legacyAddress(addr, len);\n        default:\n            return segwitAddress(addr, len);\n    }\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString HDPrivateKey::xprv() const{\n    char arr[112] = { 0 };\n    xprv(arr, sizeof(arr));\n    return String(arr);\n}\nString HDPrivateKey::address() const{\n    switch(type){\n        case P2WPKH:\n            return segwitAddress();\n        case P2SH_P2WPKH:\n            return nestedSegwitAddress();\n        case P2PKH:\n            return legacyAddress();\n        default:\n            return segwitAddress();\n    }\n}\n#endif\nint HDPrivateKey::xpub(char * arr, size_t len) const{\n    uint8_t hex[111] = { 0 }; // TODO: real length, in xpub compressed = true\n    switch(type){\n        case P2WPKH:\n            memcpy(hex, network->zpub, 4);\n            break;\n        case P2SH_P2WPKH:\n            memcpy(hex, network->ypub, 4);\n            break;\n        case P2WSH:\n            memcpy(hex, network->Zpub, 4);\n            break;\n        case P2SH_P2WSH:\n            memcpy(hex, network->Ypub, 4);\n            break;\n        default:\n            memcpy(hex, network->xpub, 4);\n    }\n    hex[4] = depth;\n    memcpy(hex+5, parentFingerprint, 4);\n    for(uint8_t i=0; i<4; i++){\n        hex[12-i] = ((childNumber >> (i*8)) & 0xFF);\n    }\n    memcpy(hex+13, chainCode, 32);\n\n    uint8_t sec[65] = { 0 };\n    int secLen = publicKey().sec(sec, sizeof(sec));\n    memcpy(hex+45, sec, secLen);\n    return toBase58Check(hex, 45+secLen, arr, len);\n}\n\nvoid HDPrivateKey::fingerprint(uint8_t arr[4]) const{\n    uint8_t secArr[65] = { 0 };\n    int l = publicKey().sec(secArr, sizeof(secArr));\n    uint8_t hash[20] = { 0 };\n    hash160(secArr, l, hash);\n    memcpy(arr, hash, 4);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString HDPrivateKey::fingerprint() const{\n    uint8_t arr[4];\n    fingerprint(arr);\n    return toHex(arr, 4);\n}\n#endif\n\nHDPublicKey HDPrivateKey::xpub() const{\n    PublicKey p = publicKey();\n    return HDPublicKey(p.point, chainCode, depth, parentFingerprint, childNumber, network, type);\n}\nHDPrivateKey HDPrivateKey::child(uint32_t index, bool hardened) const{\n    if(index >= HARDENED_INDEX){\n        hardened = true;\n    }\n    HDPrivateKey child;\n\n    uint8_t sec[65] = { 0 };\n    PublicKey p = publicKey();\n    int l = p.sec(sec, sizeof(sec));\n    uint8_t hash[20] = { 0 };\n    hash160(sec, l, hash);\n    memcpy(child.parentFingerprint, hash, 4);\n    if(hardened && index < HARDENED_INDEX){\n        index += HARDENED_INDEX;\n    }\n    child.childNumber = index;\n    child.depth = depth+1;\n\n    child.type = type;\n    child.network = network;\n    if(hardened){\n        if(depth == 0){\n            switch(index){\n                case HARDENED_INDEX+44:\n                    child.type = P2PKH;\n                    break;\n                case HARDENED_INDEX+49:\n                    child.type = P2SH_P2WPKH;\n                    break;\n                case HARDENED_INDEX+84:\n                    child.type = P2WPKH;\n                    break;\n                case HARDENED_INDEX+48:\n                    child.type = MULTISIG;\n                    break;\n                case HARDENED_INDEX+45:\n                    child.type = P2SH;\n                    break;\n            }\n        }\n        if(depth == 1){\n            if(index == (HARDENED_INDEX+1)){\n                child.network = &Testnet;\n            }\n            if(index == HARDENED_INDEX){\n                child.network = &Mainnet;\n            }\n        }\n        if(depth == 3 && type == MULTISIG){\n            if(index == (HARDENED_INDEX+1)){\n                child.type = P2SH_P2WSH;\n            }\n            if(index == (HARDENED_INDEX+2)){\n                child.type = P2WSH;\n            }\n        }\n    }\n\n    uint8_t data[37];\n    if(hardened){\n        data[0] = 0;\n        getSecret(data+1);\n    }else{\n        memcpy(data, sec, 33);\n    }\n    intToBigEndian(index, data+33, 4);\n\n    uint8_t raw[64];\n    SHA512 sha;\n    sha.beginHMAC(chainCode, sizeof(chainCode));\n    sha.write(data, 37);\n    sha.endHMAC(raw);\n\n    memcpy(child.chainCode, raw+32, 32);\n\n    ECScalar r(raw, 32);\n    r += *this;\n    uint8_t secret[32];\n    r.getSecret(secret);\n    child.setSecret(secret);\n    memzero(secret, 32);\n    return child;\n}\n\nHDPrivateKey HDPrivateKey::hardenedChild(uint32_t index) const{\n    return child(index, true);\n}\n\nHDPrivateKey HDPrivateKey::derive(uint32_t * index, size_t len) const{\n    HDPrivateKey pk = *this;\n    for(size_t i=0; i<len; i++){\n        pk = pk.child(index[i]);\n    }\n    return pk;\n}\nHDPrivateKey HDPrivateKey::derive(const char * path) const{\n    static const char VALID_CHARS[] = \"0123456789/'h\";\n    size_t len = strlen(path);\n    const char * cur = path;\n    if(path[0] == 'm'){ // remove leading \"m/\"\n        cur+=2;\n        len-=2;\n    }\n    if(cur[len-1] == '/'){ // remove trailing \"/\"\n        len--;\n    }\n    HDPrivateKey pk; // invalid private key to return if something failed\n    size_t derivationLen = 1;\n    // checking if all chars are valid and counting derivation length\n    for(size_t i=0; i<len; i++){\n        const char * pch = strchr(VALID_CHARS, cur[i]);\n        if(pch == NULL){ // wrong character\n            return pk;\n        }\n        if(cur[i] == '/'){\n            derivationLen++;\n        }\n    }\n    uint32_t * derivation = (uint32_t *)calloc(derivationLen, sizeof(uint32_t));\n    if(derivation == NULL){ return pk; }\n    size_t current = 0;\n    for(size_t i=0; i<len; i++){\n        if(cur[i] == '/'){ // next\n            current++;\n            continue;\n        }\n        const char * pch = strchr(VALID_CHARS, cur[i]);\n        uint32_t val = pch-VALID_CHARS;\n        if(derivation[current] >= HARDENED_INDEX){ // can't have anything after hardened\n            free(derivation);\n            return pk;\n        }\n        if(val < 10){\n            derivation[current] = derivation[current]*10 + val;\n        }else{ // h or ' -> hardened\n            derivation[current] += HARDENED_INDEX;\n        }\n    }\n    pk = derive(derivation, derivationLen);\n    free(derivation);\n    return pk;\n}\n// ---------------------------------------------------------------- HDPublicKey class\n\nsize_t HDPublicKey::to_bytes(uint8_t * arr, size_t len) const{\n    uint8_t hex[78] = { 0 };\n    switch(type){\n        case P2WPKH:\n            memcpy(hex, network->zpub, 4);\n            break;\n        case P2SH_P2WPKH:\n            memcpy(hex, network->ypub, 4);\n            break;\n        case P2WSH:\n            memcpy(hex, network->Zpub, 4);\n            break;\n        case P2SH_P2WSH:\n            memcpy(hex, network->Ypub, 4);\n            break;\n        default:\n            memcpy(hex, network->xpub, 4);\n    }\n    hex[4] = depth;\n    memcpy(hex+5, parentFingerprint, 4);\n    for(uint8_t i=0; i<4; i++){\n        hex[12-i] = ((childNumber >> (i*8)) & 0xFF);\n    }\n    memcpy(hex+13, chainCode, 32);\n    memcpy(hex+46, point, 32);\n    hex[45] = 0x02 + (point[63] & 0x01);\n    if(len > sizeof(hex)){\n        len = sizeof(hex);\n    }\n    memcpy(arr, hex, len);\n    return len;\n}\nsize_t HDPublicKey::to_stream(SerializeStream *s, size_t offset) const{\n    uint8_t hex[78] = { 0 };\n    size_t bytes_written = 0;\n    to_bytes(hex, sizeof(hex));\n    while(s->available() && bytes_written+offset < sizeof(hex)){\n        s->write(hex[bytes_written+offset]);\n        bytes_written++;\n    }\n    return bytes_written;\n}\nsize_t HDPublicKey::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    // reading the prefix\n    while(s->available() > 0 && bytes_parsed+bytes_read < 4){\n        prefix[bytes_parsed+bytes_read] = s->read();\n        bytes_read++;\n    }\n    if(bytes_parsed+bytes_read == 4){\n        bool found = false;\n        for(int i=0; i<networks_len; i++){\n            if(memcmp(prefix, networks[i]->xpub, 4)==0){\n                type = UNKNOWN_TYPE;\n                found = true;\n                network = networks[i];\n                break;\n            }else if(memcmp(prefix, networks[i]->ypub, 4)==0){\n                type = P2SH_P2WPKH;\n                found = true;\n                network = networks[i];\n                break;\n            }else if(memcmp(prefix, networks[i]->zpub, 4)==0){\n                type = P2WPKH;\n                found = true;\n                network = networks[i];\n                break;\n            }else if(memcmp(prefix, networks[i]->Ypub, 4)==0){\n                type = P2SH_P2WSH;\n                found = true;\n                network = networks[i];\n                break;\n            }else if(memcmp(prefix, networks[i]->Zpub, 4)==0){\n                type = P2WSH;\n                found = true;\n                network = networks[i];\n                break;\n            }\n        }\n        if(!found){\n            status = PARSING_FAILED;\n            return bytes_read;\n        }\n    }\n    // depth\n    if(s->available() > 0 && bytes_parsed+bytes_read < 5){\n        depth = s->read();\n        bytes_read++;\n    }\n    // fingerprint\n    while(s->available() > 0 && bytes_parsed+bytes_read < 9){\n        parentFingerprint[bytes_parsed+bytes_read-5] = s->read();\n        bytes_read++;\n    }\n    // childnumber\n    while(s->available() > 0 && bytes_parsed+bytes_read < 13){\n        childNumber <<= 8;\n        childNumber += s->read();\n        bytes_read++;\n    }\n    // chaincode\n    while(s->available() > 0 && bytes_parsed+bytes_read < 45){\n        chainCode[bytes_parsed+bytes_read-13] = s->read();\n        bytes_read++;\n    }\n    // pubkey\n    while(s->available() > 0 && bytes_parsed+bytes_read < 78){\n        point[bytes_parsed+bytes_read-45] = s->read();\n        bytes_read++;\n    }\n    // uncompressing the pubkey\n    if(bytes_parsed+bytes_read == 78){\n        status = PARSING_DONE;\n        uint8_t arr[33];\n        memcpy(arr, point, 33);\n        uint8_t buf[65];\n        ecdsa_uncompress_pubkey(&secp256k1, arr, buf);\n        memcpy(point, buf+1, 64);\n        if(!isValid()){\n            status = PARSING_FAILED;\n        }\n    }\n    bytes_parsed += bytes_read;\n    return bytes_read;\n}\nsize_t HDPublicKey::from_str(const char * xpubArr, size_t xpubLen){\n    uint8_t arr[85] = { 0 };\n    size_t l = fromBase58Check(xpubArr, xpubLen, arr, sizeof(arr));\n    if(l == 0){\n        return 0; // decoding error\n    }\n    ParseByteStream s(arr, sizeof(arr));\n    HDPublicKey::from_stream(&s);\n    return xpubLen;\n}\n\nHDPublicKey::HDPublicKey():PublicKey(){\n    memzero(prefix, 4);\n    compressed = true;\n    memzero(chainCode, 32);\n    depth = 0;\n    memzero(parentFingerprint, 4);\n    childNumber = 0;\n    network = &DEFAULT_NETWORK;\n    type = UNKNOWN_TYPE;\n}\nHDPublicKey::HDPublicKey(const uint8_t p[64],\n                           const uint8_t chain_code[32],\n                           uint8_t key_depth,\n                           const uint8_t parent_fingerprint_arr[4],\n                           uint32_t child_number,\n                           const Network * net,\n                           ScriptType key_type){\n    reset();\n    memcpy(point, p, 64);\n    memzero(prefix, 4);\n    compressed = true;\n    type = key_type;\n    network = net;\n    memcpy(chainCode, chain_code, 32);\n    depth = key_depth;\n    childNumber = child_number;\n    if(parent_fingerprint_arr != NULL){\n        memcpy(parentFingerprint, parent_fingerprint_arr, 4);\n    }else{\n        memzero(parentFingerprint, 4);\n    }\n}\n/*\nHDPublicKey &HDPublicKey::operator=(const HDPublicKey &other){\n    if (this == &other){ return *this; } // self-assignment\n    type = other.type;\n    memcpy(point, other.point, 64);\n    memcpy(chainCode, other.chainCode, 32);\n    compressed = true;\n    depth = other.depth;\n    childNumber = other.childNumber;\n    memcpy(parentFingerprint, other.parentFingerprint, 4);\n    return *this;\n};*/\nHDPublicKey::HDPublicKey(const char * xpubArr){\n    reset();\n    memzero(prefix, 4);\n    childNumber = 0;\n    network = &DEFAULT_NETWORK;\n    from_str(xpubArr, strlen(xpubArr));\n}\nHDPublicKey::~HDPublicKey(void) {\n    memzero(point, 64);\n    memzero(chainCode, 32);\n}\nint HDPublicKey::xpub(char * arr, size_t len) const{\n    uint8_t hex[78] = { 0 };\n    HDPublicKey::to_bytes(hex, sizeof(hex));\n    return toBase58Check(hex, sizeof(hex), arr, len);\n}\nint HDPublicKey::address(char * addr, size_t len) const{\n    switch(type){\n        case P2WPKH:\n            return PublicKey::segwitAddress(addr, len, network);\n        case P2SH_P2WPKH:\n            return PublicKey::nestedSegwitAddress(addr, len, network);\n        case P2PKH:\n            return PublicKey::legacyAddress(addr, len, network);\n        default:\n            return PublicKey::segwitAddress(addr, len, network);\n    }\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString HDPublicKey::xpub() const{\n    char arr[114] = { 0 };\n    xpub(arr, sizeof(arr));\n    return String(arr);\n}\nString HDPublicKey::address() const{\n    switch(type){\n        case P2WPKH:\n            return PublicKey::segwitAddress(network);\n        case P2SH_P2WPKH:\n            return PublicKey::nestedSegwitAddress(network);\n        case P2PKH:\n            return PublicKey::legacyAddress(network);\n        default:\n            return PublicKey::segwitAddress(network);\n    }\n}\n#endif\n\nvoid HDPublicKey::fingerprint(uint8_t arr[4]) const{\n    uint8_t secArr[65] = { 0 };\n    int l = sec(secArr, sizeof(secArr));\n    uint8_t hash[20] = { 0 };\n    hash160(secArr, l, hash);\n    memcpy(arr, hash, 4);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString HDPublicKey::fingerprint() const{\n    uint8_t arr[4];\n    fingerprint(arr);\n    return toHex(arr, 4);\n}\n#endif\n\nHDPublicKey HDPublicKey::child(uint32_t index) const{\n    HDPublicKey child;\n\n    uint8_t secArr[65] = { 0 };\n    int l = sec(secArr, sizeof(secArr));\n    uint8_t hash[20] = { 0 };\n    hash160(secArr, l, hash);\n    memcpy(child.parentFingerprint, hash, 4);\n    child.childNumber = index;\n    child.depth = depth+1;\n\n    child.type = type;\n    child.network = network;\n\n    uint8_t data[37];\n    memcpy(data, secArr, 33);\n    intToBigEndian(index, data+33, 4);\n\n    uint8_t raw[64];\n    SHA512 sha;\n    sha.beginHMAC(chainCode, sizeof(chainCode));\n    sha.write(data, 37);\n    sha.endHMAC(raw);\n\n    memcpy(child.chainCode, raw+32, 32);\n\n    ECScalar r(raw, 32);\n    ECPoint p = r*GeneratorPoint;\n    p += *this;\n    memcpy(child.point, p.point, 64);\n    child.compressed = true;\n    return child;\n}\nHDPublicKey HDPublicKey::derive(uint32_t * index, size_t len) const{\n    HDPublicKey pk = *this;\n    for(size_t i=0; i<len; i++){\n        pk = pk.child(index[i]);\n    }\n    return pk;\n}\nHDPublicKey HDPublicKey::derive(const char * path) const{\n    static const char VALID_CHARS[] = \"0123456789/\";\n    size_t len = strlen(path);\n    const char * cur = path;\n    if(path[0] == 'm'){ // remove leading \"m/\"\n        cur+=2;\n        len-=2;\n    }\n    if(cur[len-1] == '/'){ // remove trailing \"/\"\n        len--;\n    }\n    HDPublicKey pk; // dummy to return if something failed\n    size_t derivationLen = 1;\n    // checking if all chars are valid and counting derivation length\n    for(size_t i=0; i<len; i++){\n        const char * pch = strchr(VALID_CHARS, cur[i]);\n        if(pch == NULL){ // wrong character\n            return pk;\n        }\n        if(cur[i] == '/'){\n            derivationLen++;\n        }\n    }\n    uint32_t * derivation = (uint32_t *)calloc(derivationLen, sizeof(uint32_t));\n    if(derivation == NULL){ return pk; }\n    size_t current = 0;\n    for(size_t i=0; i<len; i++){\n        if(cur[i] == '/'){ // next\n            if(derivation[current] >= HARDENED_INDEX){ // can't be hardened\n                free(derivation);\n                return pk;\n            }\n            current++;\n            continue;\n        }\n        const char * pch = strchr(VALID_CHARS, cur[i]);\n        uint32_t val = pch-VALID_CHARS;\n        derivation[current] = derivation[current]*10 + val;\n    }\n    pk = derive(derivation, derivationLen);\n    free(derivation);\n    return pk;\n}\n\n"
  },
  {
    "path": "src/Hash.cpp",
    "content": "#include \"Hash.h\"\n#include \"utility/trezor/hmac.h\"\n#include \"utility/trezor/ripemd160.h\"\n\n#if USE_STD_STRING\nusing std::string;\n#define String string\n#endif\n\n// generic funtcions for single line hash\nstatic size_t hashData(HashAlgorithm * algo, const uint8_t * data, size_t len, uint8_t * hash){\n    algo->begin();\n    algo->write(data, len);\n    return algo->end(hash);\n}\n\n#if USE_ARDUINO_STRING || USE_STD_STRING\nstatic size_t hashString(HashAlgorithm * algo, const String s, uint8_t * hash){\n    return hashData(algo, (const uint8_t *)s.c_str(), s.length(), hash);\n}\n#endif\n\n/************************* RIPEMD-160 *************************/\n\nint rmd160(const uint8_t * data, size_t len, uint8_t hash[20]){\n    RMD160 rmd;\n    return hashData(&rmd, data, len, hash);\n}\nint rmd160(const char * data, size_t len, uint8_t hash[20]){\n    return rmd160((uint8_t*)data, len, hash);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nint rmd160(const String data, uint8_t hash[20]){\n    RMD160 rmd;\n    return hashString(&rmd, data, hash);\n}\n#endif\n\nvoid RMD160::begin(){\n    ripemd160_Init(&ctx);\n};\nsize_t RMD160::write(const uint8_t * data, size_t len){\n    ripemd160_Update(&ctx, data, len);\n    return len;\n}\nsize_t RMD160::write(uint8_t b){\n    uint8_t arr[1] = { b };\n    ripemd160_Update(&ctx, arr, 1);\n    return 1;\n}\nsize_t RMD160::end(uint8_t hash[20]){\n    ripemd160_Final(&ctx, hash);\n    return 20;\n}\n\n/************************** SHA-256 **************************/\n\nint sha256(const uint8_t * data, size_t len, uint8_t hash[32]){\n    SHA256 sha;\n    return hashData(&sha, data, len, hash);\n}\nint sha256(const char * data, size_t len, uint8_t hash[32]){\n    return sha256((uint8_t*)data, len, hash);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nint sha256(const String data, uint8_t hash[32]){\n    SHA256 sha;\n    return hashString(&sha, data, hash);\n}\n#endif\n\nTaggedHash::TaggedHash(const char * tag){\n    begin();\n    uint8_t th[32];\n    sha256(tag, strlen(tag), th);\n    write(th, 32);\n    write(th, 32);\n}\n\nint tagged_hash(const char * tag, const uint8_t * data, size_t dataLen, uint8_t hash[32]){\n    TaggedHash th(tag);\n    return hashData(&th, data, dataLen, hash);\n}\nint tagged_hash(const char * tag, const char * data, size_t len, uint8_t hash[32]){\n    return tagged_hash(tag, (uint8_t*)data, len, hash);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nint tagged_hash(const String tag, const String data, uint8_t hash[32]){\n    TaggedHash th(tag.c_str());\n    return hashString(&th, data, hash);\n}\n#endif\n\nint sha256Hmac(const uint8_t * key, size_t keyLen, const uint8_t * data, size_t dataLen, uint8_t hash[32]){\n    ubtc_hmac_sha256(key, keyLen, data, dataLen, hash);\n    return 32;\n}\n\nvoid SHA256::begin(){\n    sha256_Init(&ctx.ctx);\n}\nvoid SHA256::beginHMAC(const uint8_t * key, size_t keySize){\n    ubtc_hmac_sha256_Init(&ctx, key, keySize);\n}\nsize_t SHA256::write(const uint8_t * data, size_t len){\n    sha256_Update(&ctx.ctx, data, len);\n    return len;\n}\nsize_t SHA256::write(uint8_t b){\n    uint8_t arr[1] = { b };\n    sha256_Update(&ctx.ctx, arr, 1);\n    return 1;\n}\nsize_t SHA256::end(uint8_t hash[32]){\n    sha256_Final(&ctx.ctx, hash);\n    return 32;\n}\nsize_t SHA256::endHMAC(uint8_t hmac[32]){\n    ubtc_hmac_sha256_Final(&ctx, hmac);\n    return 32;\n}\n\n/************************* Hash-160 **************************/\n/******************** rmd160( sha256( m ) ) ******************/\n\nint hash160(const uint8_t * data, size_t len, uint8_t hash[20]){\n    Hash160 h160;\n    return hashData(&h160, data, len, hash);\n}\nint hash160(const char * data, size_t len, uint8_t hash[20]){\n    return hash160((uint8_t*)data, len, hash);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nint hash160(const String data, uint8_t hash[20]){\n    Hash160 h160;\n    return hashString(&h160, data, hash);\n}\n#endif\n\nsize_t Hash160::end(uint8_t hash[20]){\n    uint8_t h[32];\n    sha256_Final(&ctx.ctx, h);\n    rmd160(h, 32, hash);\n    return 20;\n}\n\n/********************** Double SHA-256 ***********************/\n/******************** sha256( sha256( m ) ) ******************/\n\nint doubleSha(const uint8_t * data, size_t len, uint8_t hash[32]){\n    DoubleSha sha;\n    return hashData(&sha, data, len, hash);\n}\nint doubleSha(const char * data, size_t len, uint8_t hash[32]){\n    return doubleSha((uint8_t*)data, len, hash);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nint doubleSha(const String data, uint8_t hash[32]){\n    DoubleSha sha;\n    return hashString(&sha, data, hash);\n}\n#endif\n\nsize_t DoubleSha::end(uint8_t hash[32]){\n    uint8_t h[32];\n    sha256_Final(&ctx.ctx, h);\n    sha256(h, 32, hash);\n    return 32;\n}\n\n/************************** SHA-512 **************************/\n\nint sha512(const uint8_t * data, size_t len, uint8_t hash[64]){\n    SHA512 sha;\n    return hashData(&sha, data, len, hash);\n}\nint sha512(const char * data, size_t len, uint8_t hash[64]){\n    return sha512((uint8_t*)data, len, hash);\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nint sha512(const String data, uint8_t hash[64]){\n    SHA512 sha;\n    return hashString(&sha, data, hash);\n}\n#endif\n\nvoid SHA512::begin(){\n    sha512_Init(&ctx.ctx);\n};\nvoid SHA512::beginHMAC(const uint8_t * key, size_t keySize){\n    ubtc_hmac_sha512_Init(&ctx, key, keySize);\n}\nsize_t SHA512::write(const uint8_t * data, size_t len){\n    sha512_Update(&ctx.ctx, data, len);\n    return len;\n}\nsize_t SHA512::write(uint8_t b){\n    uint8_t arr[1] = { b };\n    sha512_Update(&ctx.ctx, arr, 1);\n    return 1;\n}\nsize_t SHA512::end(uint8_t hash[64]){\n    sha512_Final(&ctx.ctx, hash);\n    return 64;\n}\nsize_t SHA512::endHMAC(uint8_t hmac[64]){\n    ubtc_hmac_sha512_Final(&ctx, hmac);\n    return 64;\n}\n\nint sha512Hmac(const uint8_t * key, size_t keyLen, const uint8_t * data, size_t dataLen, uint8_t hash[64]){\n    ubtc_hmac_sha512(key, keyLen, data, dataLen, hash);\n    return 64;\n}\n"
  },
  {
    "path": "src/Hash.h",
    "content": "/** @file Hash.h\n *  \\brief All hashing functions and classes live here\n */\n#ifndef __HASH_H__18NLNNCSJ2\n#define __HASH_H__18NLNNCSJ2\n\n#include \"uBitcoin_conf.h\"\n#include \"BaseClasses.h\"\n#include <stdint.h>\n#include <string.h>\n#include \"utility/trezor/sha2.h\"\n#include \"utility/trezor/ripemd160.h\"\n#include \"utility/trezor/hmac.h\"\n\n/** \\brief Abstract hashing class */\nclass HashAlgorithm : public SerializeStream{\npublic:\n    size_t available(){ return 100; };\n\tvoid begin(){};\n    virtual size_t write(const uint8_t * data, size_t len) = 0;\n    virtual size_t write(uint8_t b) = 0;\n    virtual size_t end(uint8_t * hash) = 0;\n};\n\n/************************* RIPEMD-160 *************************/\n\n/** \\brief ripemd-160 one-line hashing function */\nint rmd160(const uint8_t * data, size_t len, uint8_t hash[20]);\nint rmd160(const char * data, size_t len, uint8_t hash[20]);\n#if USE_ARDUINO_STRING\nint rmd160(const String data, uint8_t hash[20]);\n#endif\n#if USE_STD_STRING\nint rmd160(const std::string data, uint8_t hash[20]);\n#endif\n\nclass RMD160 : public HashAlgorithm{\npublic:\n    RMD160(){ begin(); };\n    void begin();\n    size_t write(const uint8_t * data, size_t len);\n    size_t write(uint8_t b);\n    size_t end(uint8_t hash[20]);\nprotected:\n    RIPEMD160_CTX ctx;\n};\n\n/************************** SHA-256 **************************/\n\n/** \\brief sha256 one-line hashing function → 32 bytes output */\nint sha256(const uint8_t * data, size_t len, uint8_t hash[32]);\nint sha256(const char * data, size_t len, uint8_t hash[32]);\n#if USE_ARDUINO_STRING\nint sha256(const String data, uint8_t hash[32]);\n#endif\n#if USE_STD_STRING\nint sha256(const std::string data, uint8_t hash[32]);\n#endif\n\nint sha256Hmac(const uint8_t * key, size_t keyLen, const uint8_t * data, size_t dataLen, uint8_t hash[32]);\n\nclass SHA256 : public HashAlgorithm{\npublic:\n    SHA256(){ begin(); };\n    void begin();\n    void beginHMAC(const uint8_t * key, size_t keySize);\n    size_t write(const uint8_t * data, size_t len);\n    size_t write(uint8_t b);\n    size_t end(uint8_t hash[32]);\n    size_t endHMAC(uint8_t hmac[32]);\nprotected:\n    HMAC_SHA256_CTX ctx;\n};\n\n/************************ Tagged hash ************************/\n\n/** \\brief tagged hash class as defined in bip-schnorr (bip340) */\nclass TaggedHash : public SHA256{\npublic:\n    TaggedHash(const char * tag);\n};\n\n/** \\brief tagged hash one-line hashing function → 32 bytes output */\nint tagged_hash(const char * tag, const uint8_t * data, size_t dataLen, uint8_t hash[32]);\nint tagged_hash(const char * tag, const char * data, size_t dataLen, uint8_t hash[32]);\n#if USE_ARDUINO_STRING\nint tagged_hash(const String tag, const String data, uint8_t hash[32]);\n#endif\n#if USE_STD_STRING\nint tagged_hash(const std::string tag, const std::string data, uint8_t hash[32]);\n#endif\n\n\n/************************* Hash-160 **************************/\n/******************** rmd160( sha256( m ) ) ******************/\n\n/** \\brief rmd160(sha256(data)) → 20 bytes output */\nint hash160(const uint8_t * data, size_t len, uint8_t hash[20]);\nint hash160(const uint8_t * data, size_t len, uint8_t hash[20]);\nint hash160(const char * data, size_t len, uint8_t hash[20]);\n#if USE_ARDUINO_STRING\nint hash160(const String data, uint8_t hash[20]);\n#endif\n#if USE_STD_STRING\nint hash160(const std::string data, uint8_t hash[20]);\n#endif\n\nclass Hash160 : public SHA256{\npublic:\n    size_t end(uint8_t hash[20]);\n};\n\n/********************** Double SHA-256 ***********************/\n/******************** sha256( sha256( m ) ) ******************/\n\n/** \\brief sha256(sha256(data)) → 32 bytes output */\nint doubleSha(const uint8_t * data, size_t len, uint8_t hash[32]);\nint doubleSha(const char * data, size_t len, uint8_t hash[32]);\n#if USE_ARDUINO_STRING\nint doubleSha(const String data, uint8_t hash[32]);\n#endif\n#if USE_STD_STRING\nint doubleSha(const std::string data, uint8_t hash[32]);\n#endif\n\nclass DoubleSha : public SHA256{\npublic:\n    size_t end(uint8_t hash[32]);\n};\n\n/************************** SHA-512 **************************/\n\nint sha512Hmac(const uint8_t * key, size_t keyLen, const uint8_t * data, size_t dataLen, uint8_t hash[64]);\n\nint sha512(const uint8_t * data, size_t len, uint8_t hash[64]);\nint sha512(const char * data, size_t len, uint8_t hash[64]);\n#if USE_ARDUINO_STRING\nint sha512(const String data, uint8_t hash[64]);\n#endif\n#if USE_STD_STRING\nint sha512(const std::string data, uint8_t hash[64]);\n#endif\n\nclass SHA512 : public HashAlgorithm{\npublic:\n    SHA512(){ begin(); };\n    void begin();\n    void beginHMAC(const uint8_t * key, size_t keySize);\n    size_t write(const uint8_t * data, size_t len);\n    size_t write(uint8_t b);\n    size_t end(uint8_t hash[64]);\n    size_t endHMAC(uint8_t hmac[64]);\nprotected:\n    HMAC_SHA512_CTX ctx;\n};\n\n#endif // __HASH_H__18NLNNCSJ2\n"
  },
  {
    "path": "src/Networks.cpp",
    "content": "// all known networks\n#include \"Networks.h\"\n\nconst Network Mainnet = {\n    0x00, // p2pkh\n    0x05, // p2sh\n    \"bc\", // bech32\n    0x80, // wif\n    { 0x04, 0x88, 0xad, 0xe4 }, // xprv\n    { 0x04, 0x9d, 0x78, 0x78 }, // yprv\n    { 0x04, 0xb2, 0x43, 0x0c }, // zprv\n    { 0x02, 0x95, 0xb0, 0x05 }, // Yprv\n    { 0x02, 0xaa, 0x7a, 0x99 }, // Zprv\n    { 0x04, 0x88, 0xb2, 0x1e }, // xpub\n    { 0x04, 0x9d, 0x7c, 0xb2 }, // ypub\n    { 0x04, 0xb2, 0x47, 0x46 }, // zpub\n    { 0x02, 0x95, 0xb4, 0x3f }, // Ypub\n    { 0x02, 0xaa, 0x7e, 0xd3 }, // Zpub\n    0 // bip32 coin type\n};\n\nconst Network Testnet = {\n    0x6F, // p2pkh\n    0xC4, // p2sh\n    \"tb\", // bech32\n    0xEF, // wif\n    { 0x04, 0x35, 0x83, 0x94 }, // tprv\n    { 0x04, 0x4a, 0x4e, 0x28 }, // uprv\n    { 0x04, 0x5f, 0x18, 0xbc }, // vprv\n    { 0x02, 0x42, 0x85, 0xb5 }, // Uprv\n    { 0x02, 0x57, 0x50, 0x48 }, // Vprv\n    { 0x04, 0x35, 0x87, 0xcf }, // tpub\n    { 0x04, 0x4a, 0x52, 0x62 }, // upub\n    { 0x04, 0x5f, 0x1c, 0xf6 }, // vpub\n    { 0x02, 0x42, 0x89, 0xef }, // Upub\n    { 0x02, 0x57, 0x54, 0x83 }, // Vpub\n    1 // bip32 coin type\n};\n\nconst Network Regtest = {\n    0x6F, // p2pkh\n    0xC4, // p2sh\n    \"bcrt\", // bech32\n    0xEF, // wif\n    { 0x04, 0x35, 0x83, 0x94 }, // tprv\n    { 0x04, 0x4a, 0x4e, 0x28 }, // uprv\n    { 0x04, 0x5f, 0x18, 0xbc }, // vprv\n    { 0x02, 0x42, 0x85, 0xb5 }, // Uprv\n    { 0x02, 0x57, 0x50, 0x48 }, // Vprv\n    { 0x04, 0x35, 0x87, 0xcf }, // tpub\n    { 0x04, 0x4a, 0x52, 0x62 }, // upub\n    { 0x04, 0x5f, 0x1c, 0xf6 }, // vpub\n    { 0x02, 0x42, 0x89, 0xef }, // Upub\n    { 0x02, 0x57, 0x54, 0x83 }, // Vpub\n    1 // bip32 coin type\n};\n\n// signet is the same as testnet\nconst Network Signet = Testnet;\n\nconst Network * networks[4] = { &Mainnet, &Testnet, &Regtest, &Signet };\nconst uint8_t networks_len = 4;\n"
  },
  {
    "path": "src/Networks.h",
    "content": "#ifndef __UBTC_NETWORKS_H__\n#define __UBTC_NETWORKS_H__\n\n#include <stdint.h>\n\n/** \\brief Prefixes for particular network (Mainnet / Testnet ).<br>\n *  HD key prefixes are described here:<br>\n *  https://github.com/satoshilabs/slips/blob/master/slip-0132.md<br>\n *  useful tool: in https://iancoleman.io/bip39/\n */\ntypedef struct {\n    /** \\brief Pay-To-Pubkey-Hash addresses */\n    uint8_t p2pkh;   \n    /** \\brief Pay-To-Script-Hash addresses */\n    uint8_t p2sh;    \n    /** \\brief Prefix for segwit addreses ...for regtest it is larger */\n    char bech32[5];  \n    /** \\brief Wallet Import Format, used in PrivateKey */\n    uint8_t wif;     \n    /** \\brief HD private key for legacy addresses (P2PKH) */\n    uint8_t xprv[4]; \n    /** \\brief HD private key for nested Segwit (P2SH-P2WPKH) */\n    uint8_t yprv[4]; \n    /** \\brief HD private key for native Segwit (P2WPKH) */\n    uint8_t zprv[4]; \n    /** \\brief HD private key for nested Segwit Multisig (P2SH-P2WSH) */\n    uint8_t Yprv[4]; \n    /** \\brief HD private key for native Segwit Multisig (P2WSH) */\n    uint8_t Zprv[4]; \n    /** \\brief HD public key for legacy addresses (P2PKH) */\n    uint8_t xpub[4]; \n    /** \\brief HD public key for nested Segwit (P2SH-P2WPKH) */\n    uint8_t ypub[4]; \n    /** \\brief HD public key for native Segwit (P2WPKH) */\n    uint8_t zpub[4]; \n    /** \\brief HD public key for nested Segwit Multisig (P2SH-P2WSH) */\n    uint8_t Ypub[4]; \n    /** \\brief HD public key for native Segwit Multisig (P2WSH) */\n    uint8_t Zpub[4]; \n    /** \\brief bip32 coin index */\n    uint32_t bip32;\n} Network;\n\nextern const Network Mainnet;\nextern const Network Testnet;\nextern const Network Regtest;\nextern const Network Signet;\n\nextern const Network * networks[];\nextern const uint8_t networks_len;\n\n#endif // __UBTC_NETWORKS_H__"
  },
  {
    "path": "src/OpCodes.h",
    "content": "#ifndef __OPCODES_H__R3NU8EN25O\n#define __OPCODES_H__R3NU8EN25O\n\n#include \"uBitcoin_conf.h\"\n\n// reference: https://en.bitcoin.it/wiki/Script#Opcodes\n\n// uncomment the following string to use disabled op-codes:\n// #define INCLUDE_DISABLED \n\n/* OP_CODES */\n\n/* Constants */\n\n#define OP_0 \t\t\t\t\t0\n#define OP_PUSHDATA1 \t\t\t76\n#define OP_PUSHDATA2 \t\t\t77\n#define OP_PUSHDATA4 \t\t\t78\n#define OP_1NEGATE \t\t\t\t79\n#define OP_RESERVED \t\t\t80\n#define OP_1 \t\t\t\t\t81\n#define OP_2 \t\t\t\t\t82\n#define OP_3 \t\t\t\t\t83\n#define OP_4 \t\t\t\t\t84\n#define OP_5 \t\t\t\t\t85\n#define OP_6 \t\t\t\t\t86\n#define OP_7 \t\t\t\t\t87\n#define OP_8 \t\t\t\t\t88\n#define OP_9 \t\t\t\t\t89\n#define OP_10 \t\t\t\t\t90\n#define OP_11 \t\t\t\t\t91\n#define OP_12 \t\t\t\t\t92\n#define OP_13 \t\t\t\t\t93\n#define OP_14 \t\t\t\t\t94\n#define OP_15 \t\t\t\t\t95\n#define OP_16 \t\t\t\t\t96\n\n/* Flow control */\n\n#define OP_NOP \t\t\t\t\t97\n#define OP_VER \t\t\t\t\t98\n#define OP_IF \t\t\t\t\t99\n#define OP_NOTIF \t\t\t\t100\n#define OP_VERIF \t\t\t\t101\n#define OP_VERNOTIF \t\t\t102\n#define OP_ELSE \t\t\t\t103\n#define OP_ENDIF \t\t\t\t104\n#define OP_VERIFY \t\t\t\t105\n#define OP_RETURN \t\t\t\t106\n\n/* Stack */\n\n#define OP_TOALTSTACK \t\t\t107\n#define OP_FROMALTSTACK \t\t108\n#define OP_2DROP \t\t\t\t109\n#define OP_2DUP \t\t\t\t110\n#define OP_3DUP \t\t\t\t111\n#define OP_2OVER \t\t\t\t112\n#define OP_2ROT \t\t\t\t113\n#define OP_2SWAP \t\t\t\t114\n#define OP_IFDUP \t\t\t\t115\n#define OP_DEPTH \t\t\t\t116\n#define OP_DROP \t\t\t\t117\n#define OP_DUP \t\t\t\t\t118\n#define OP_NIP \t\t\t\t\t119\n#define OP_OVER \t\t\t\t120\n#define OP_PICK \t\t\t\t121\n#define OP_ROLL \t\t\t\t122\n#define OP_ROT \t\t\t\t\t123\n#define OP_SWAP \t\t\t\t124\n#define OP_TUCK \t\t\t\t125\n\n/* Splice */\n\n#ifdef INCLUDE_DISABLED\n\t#define OP_CAT \t\t\t\t126\n\t#define OP_SUBSTR \t\t\t127\n\t#define OP_LEFT  \t\t\t128\n\t#define OP_RIGHT \t\t\t129\n#endif\n\n#define OP_SIZE \t\t\t\t130\n\n/* Bitwise logic */\n\n#ifdef INCLUDE_DISABLED\n\t#define OP_INVERT \t\t\t131\n\t#define OP_AND \t\t\t\t132\n\t#define OP_OR \t\t\t\t133\n\t#define OP_XOR \t\t\t\t134\n#endif\n\n#define OP_EQUAL \t\t\t\t135\n#define OP_EQUALVERIFY \t\t\t136\n#define OP_RESERVED1 \t\t\t137\n#define OP_RESERVED2 \t\t\t138\n\n/* Arithmetic */\n\n#define OP_1ADD \t\t\t\t139\n#define OP_1SUB \t\t\t\t140\n\n#ifdef INCLUDE_DISABLED\n\t#define OP_2MUL \t\t\t141\n\t#define OP_2DIV \t\t\t142\n#endif\n\n#define OP_NEGATE \t\t\t\t143\n#define OP_ABS \t\t\t\t\t144\n#define OP_NOT \t\t\t\t\t145\n#define OP_0NOTEQUAL \t\t\t146\n#define OP_ADD \t\t\t\t\t147\n#define OP_SUB \t\t\t\t\t148\n\n#ifdef INCLUDE_DISABLED\n\t#define OP_MUL \t\t\t\t149\n\t#define OP_DIV \t\t\t\t150\n\t#define OP_MOD \t\t\t\t151\n\t#define OP_LSHIFT \t\t\t152\n\t#define OP_RSHIFT \t\t\t153\n#endif\n\n#define OP_BOOLAND \t\t\t\t154\n#define OP_BOOLOR \t\t\t\t155\n#define OP_NUMEQUAL \t\t\t156\n#define OP_NUMEQUALVERIFY \t\t157\n#define OP_NUMNOTEQUAL \t\t\t158\n#define OP_LESSTHAN \t\t\t159\n#define OP_GREATERTHAN \t\t\t160\n#define OP_LESSTHANOREQUAL \t\t161\n#define OP_GREATERTHANOREQUAL \t162\n#define OP_MIN \t\t\t\t\t163\n#define OP_MAX \t\t\t\t\t164\n#define OP_WITHIN \t\t\t\t165\n\n/* Crypto */\n\n#define OP_RIPEMD160 \t\t\t166\n#define OP_SHA1 \t\t\t\t167\n#define OP_SHA256 \t\t\t\t168\n#define OP_HASH160 \t\t\t\t169\n#define OP_HASH256 \t\t\t\t170\n#define OP_CODESEPARATOR \t\t171\n#define OP_CHECKSIG \t\t\t172\n#define OP_CHECKSIGVERIFY \t\t173\n#define OP_CHECKMULTISIG \t\t174\n#define OP_CHECKMULTISIGVERIFY \t175\n#define OP_NOP1 \t\t\t\t176\n\n/* Locktime */\n\n#define OP_CHECKLOCKTIMEVERIFY \t177\n#define OP_CHECKSEQUENCEVERIFY \t178\n\n/* Reserved */\n\n#define OP_NOP4 \t\t\t\t179\n#define OP_NOP5 \t\t\t\t180\n#define OP_NOP6 \t\t\t\t181\n#define OP_NOP7 \t\t\t\t182\n#define OP_NOP8 \t\t\t\t183\n#define OP_NOP9 \t\t\t\t184\n#define OP_NOP10 \t\t\t\t185\n#define OP_NULLDATA \t\t\t252\n\n/* Pseudo-words\n * These opcodes are used internally \n * for assisting with transaction matching. \n * They are invalid if used in actual scripts.\n */\n#define OP_PUBKEYHASH \t\t\t253\n#define OP_PUBKEY \t\t\t\t254\n#define OP_INVALIDOPCODE \t\t255\n\n#endif /* __OPCODES_H__R3NU8EN25O */"
  },
  {
    "path": "src/PSBT.cpp",
    "content": "#include \"PSBT.h\"\n#include \"Conversion.h\"\n#if USE_STD_STRING\nusing std::string;\n#define String string\n#endif\n\n#define UBTC_ERR_PSBT_MAGIC 1\n#define UBTC_ERR_PSBT_SCOPE 2\n#define UBTC_ERR_PSBT_KEY \t3\n#define UBTC_ERR_PSBT_VALUE 4\n#define UBTC_ERR_PSBT_TX    5\n#define UBTC_ERR_PSBT_IN    6\n#define UBTC_ERR_PSBT_OUT   7\n\n// descriptor checksum from https://github.com/bitcoin/bitcoin/blob/master/src/script/descriptor.cpp\nuint64_t PolyMod(uint64_t c, int val){\n    uint8_t c0 = c >> 35;\n    c = ((c & 0x7ffffffff) << 5) ^ val;\n    if (c0 & 1) c ^= 0xf5dee51989;\n    if (c0 & 2) c ^= 0xa9fdca3312;\n    if (c0 & 4) c ^= 0x1bab10e32d;\n    if (c0 & 8) c ^= 0x3706b1677a;\n    if (c0 & 16) c ^= 0x644d626ffd;\n    return c;\n}\n\nsize_t descriptorChecksum(const char * span, size_t spanLen, char * output, size_t outputSize){\n    /** A character set designed such that:\n     *  - The most common 'unprotected' descriptor characters (hex, keypaths) are in the first group of 32.\n     *  - Case errors cause an offset that's a multiple of 32.\n     *  - As many alphabetic characters are in the same group (while following the above restrictions).\n     *\n     * If p(x) gives the position of a character c in this character set, every group of 3 characters\n     * (a,b,c) is encoded as the 4 symbols (p(a) & 31, p(b) & 31, p(c) & 31, (p(a) / 32) + 3 * (p(b) / 32) + 9 * (p(c) / 32).\n     * This means that changes that only affect the lower 5 bits of the position, or only the higher 2 bits, will just\n     * affect a single symbol.\n     *\n     * As a result, within-group-of-32 errors count as 1 symbol, as do cross-group errors that don't affect\n     * the position within the groups.\n     */\n    memset(output, 0, outputSize);\n    if(outputSize < 8){\n        return 0;\n    }\n    static const char * INPUT_CHARSET = \"0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\\\"\\\\ \";\n\n    /** The character set for the checksum itself (same as bech32). */\n    static const char * CHECKSUM_CHARSET = \"qpzry9x8gf2tvdw0s3jn54khce6mua7l\";\n\n    uint64_t c = 1;\n    int cls = 0;\n    int clscount = 0;\n    // size_t len = strlen(span);\n    for(size_t i=0; i<spanLen; i++){\n        char ch = span[i];\n        const char * pch = strchr(INPUT_CHARSET, ch);\n        if(pch==NULL){ // char not in the alphabet\n            return 0;\n        }\n        size_t pos = pch - INPUT_CHARSET;\n        c = PolyMod(c, pos & 31); // Emit a symbol for the position inside the group, for every character.\n        cls = cls * 3 + (pos >> 5); // Accumulate the group numbers\n        if (++clscount == 3) {\n            // Emit an extra symbol representing the group numbers, for every 3 characters.\n            c = PolyMod(c, cls);\n            cls = 0;\n            clscount = 0;\n        }\n    }\n    if (clscount > 0) c = PolyMod(c, cls);\n    for (int j = 0; j < 8; ++j) c = PolyMod(c, 0); // Shift further to determine the checksum.\n    c ^= 1; // Prevent appending zeroes from not affecting the checksum.\n\n    memset(output, ' ', 8);\n    for (int j = 0; j < 8; ++j) output[j] = CHECKSUM_CHARSET[(c >> (5 * (7 - j))) & 31];\n    return 8;\n}\n\n#if (USE_ARDUINO_STRING || USE_STD_STRING)\nString descriptorChecksum(String descriptor){\n    char checksum[10] = { 0 };\n    descriptorChecksum(descriptor.c_str(), strlen(descriptor.c_str()), checksum, sizeof(checksum));\n    return String(checksum);\n}\n#endif\n\nsize_t PSBT::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        // free memory\n        if(tx.inputsNumber > 0){\n            for(size_t i=0; i<tx.inputsNumber; i++){\n                if(txInsMeta[i].derivationsLen > 0){\n                    for(size_t j=0; j<txInsMeta[i].derivationsLen; j++){\n                        if(txInsMeta[i].derivations[j].derivationLen > 0){\n                            free(txInsMeta[i].derivations[j].derivation);\n                        }\n                    }\n                    delete [] txInsMeta[i].derivations;\n                }\n                if(txInsMeta[i].signaturesLen > 0){\n                    delete [] txInsMeta[i].signatures;\n                }\n            }\n            delete [] txInsMeta;\n        }\n        if(tx.outputsNumber > 0){\n            for(size_t i=0; i<tx.outputsNumber; i++){\n                if(txOutsMeta[i].derivationsLen > 0){\n                    for(size_t j=0; j<txOutsMeta[i].derivationsLen; j++){\n                        if(txOutsMeta[i].derivations[j].derivationLen > 0){\n                            free(txOutsMeta[i].derivations[j].derivation);\n                        }\n                    }\n                    delete [] txOutsMeta[i].derivations;\n                }\n            }\n            delete [] txOutsMeta;\n        }\n        tx.reset();\n        bytes_parsed = 0;\n        current_section = 0;\n        last_key_pos = 5;\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    uint8_t prefix[] = {0x70, 0x73, 0x62, 0x74, 0xFF};\n    while(s->available() && bytes_read+bytes_parsed < 5){\n        uint8_t c = s->read();\n        bytes_read++;\n        if(c != prefix[bytes_read+bytes_parsed-1]){\n            status = PARSING_FAILED;\n            ubtc_errno = UBTC_ERR_PSBT_MAGIC;\n            bytes_parsed += bytes_read;\n            return bytes_read;\n        }\n    }\n    // global scope\n    if(bytes_read+bytes_parsed == last_key_pos){\n        bytes_read += s->parse(&key);\n        bytes_read += s->parse(&value);\n    }\n    while(s->available() && key.getStatus() == PARSING_INCOMPLETE){\n        bytes_read += s->parse(&key);\n    }\n    if(key.getStatus() == PARSING_FAILED){\n        status = PARSING_FAILED;\n        ubtc_errno = UBTC_ERR_PSBT_KEY;\n        bytes_parsed += bytes_read;\n        return bytes_read;\n    }\n    while(s->available() && value.getStatus() == PARSING_INCOMPLETE){\n        bytes_read += s->parse(&value);\n    }\n    if(value.getStatus() == PARSING_FAILED){\n        status = PARSING_FAILED;\n        ubtc_errno = UBTC_ERR_PSBT_VALUE;\n        bytes_parsed += bytes_read;\n        return bytes_read;\n    }\n    if(last_key_pos == 5 && value.getStatus() == PARSING_DONE && key.getStatus() == PARSING_DONE){\n        uint8_t * arr = (uint8_t *)calloc(key.length(), sizeof(uint8_t));\n        if(arr == NULL){ status = PARSING_FAILED; return 0; }\n        key.serialize(arr, key.length());\n        if(key.length() != 2 || arr[0] != 1 || arr[1] != 0){\n            status = PARSING_FAILED;\n            ubtc_errno = UBTC_ERR_PSBT_SCOPE;\n        }\n        free(arr);\n        if(status == PARSING_FAILED){\n            bytes_parsed += bytes_read;\n            return bytes_read;\n        }\n        arr = (uint8_t *)calloc(value.length(), sizeof(uint8_t));\n        if(arr == NULL){ status = PARSING_FAILED; return 0; }\n        value.serialize(arr, value.length());\n        size_t l = lenVarInt(value.length());\n        tx.parse(arr+l, value.length()-l);\n        if(tx.getStatus() != PARSING_DONE){\n            status = PARSING_FAILED;\n        }\n        free(arr);\n        if(status == PARSING_FAILED){\n            bytes_parsed += bytes_read;\n            return bytes_read;\n        }\n        txInsMeta = new PSBTInputMetadata[tx.inputsNumber];\n        for(size_t i=0; i<tx.inputsNumber; i++){\n            txInsMeta[i].derivationsLen = 0;\n            txInsMeta[i].signaturesLen = 0;\n        }\n        txOutsMeta = new PSBTOutputMetadata[tx.outputsNumber];\n        for(size_t i=0; i<tx.outputsNumber; i++){\n            txOutsMeta[i].derivationsLen = 0;\n        }\n        last_key_pos += key.length()+value.length();\n    }\n    uint8_t sections_number = 0;\n    if(last_key_pos > 5){ // tx is already parsed\n        sections_number = 1+tx.inputsNumber+tx.outputsNumber;\n    }\n    // parsing keys and values\n    while(s->available() && current_section < sections_number){\n        if(key.getStatus() == PARSING_DONE && value.getStatus() == PARSING_DONE){\n            bytes_read += s->parse(&key);\n        }\n        if(key.getStatus() == PARSING_DONE){\n            if(key.length() == 1){ // delimiter\n                current_section ++;\n                last_key_pos += key.length();\n                continue;\n            }else{\n                bytes_read += s->parse(&value);\n            }\n        }\n        if(key.getStatus() == PARSING_FAILED || value.getStatus() == PARSING_FAILED){\n            status = PARSING_FAILED;\n            ubtc_errno = (key.getStatus() == PARSING_FAILED) ? UBTC_ERR_PSBT_KEY : UBTC_ERR_PSBT_VALUE;\n            bytes_parsed += bytes_read;\n            return bytes_read;\n        }\n        if(key.getStatus() == PARSING_INCOMPLETE){\n            bytes_read += s->parse(&key);\n        }\n        if(value.getStatus() == PARSING_INCOMPLETE){\n            bytes_read += s->parse(&value);\n        }\n        if(key.getStatus() == PARSING_DONE && value.getStatus() == PARSING_DONE){\n            int res = add(current_section, &key, &value);\n            if(res < 0){\n                status = PARSING_FAILED;\n                ubtc_errno = UBTC_ERR_PSBT_SCOPE;\n                bytes_parsed += bytes_read;\n                return bytes_read;\n            }\n            last_key_pos += key.length() + value.length();\n        }\n    }\n    if(current_section == sections_number && sections_number > 0){\n        status = PARSING_DONE;\n        key = Script();\n        value = Script();\n    }\n    bytes_parsed += bytes_read;\n    return bytes_read;\n}\n\nint PSBT::add(uint8_t section, const Script * k, const Script * v){\n    if(section == 0 || section > 1+tx.inputsNumber+tx.outputsNumber){\n        return 0;\n    }\n    uint8_t * key_arr = (uint8_t *)calloc(k->length(), sizeof(uint8_t));\n    if(key_arr == NULL){ return 0; }\n    k->serialize(key_arr, k->length());\n    uint8_t * val_arr = (uint8_t *)calloc(v->length(), sizeof(uint8_t));\n    if(val_arr == NULL){ free(key_arr); return 0; }\n    v->serialize(val_arr, v->length());\n    uint8_t key_code = key_arr[lenVarInt(k->length())];\n    int res = 0;\n\n    if(section < 1+tx.inputsNumber){ // input section\n        uint8_t input = section-1;\n        switch(key_code){\n            case 0: { // PSBT_IN_NON_WITNESS_UTXO\n                // we need to verify that tx hashes to prevtx_hash\n                // and get corresponding txOut from it. We don't need to keep the tx itself.\n                if(k->length() != 2){\n                    res = -1;\n                    break;\n                }\n                Tx tempTx;\n                tempTx.parse(val_arr+lenVarInt(v->length()), v->length()-lenVarInt(v->length()));\n                if(tempTx.getStatus() != PARSING_DONE){\n                    res = -2;\n                    break;\n                }\n                uint8_t hash[32];\n                tempTx.hash(hash);\n                if(memcmp(hash, tx.txIns[input].hash, 32) != 0){\n                    res = -3;\n                    break;\n                }\n                if(tempTx.outputsNumber <= tx.txIns[input].outputIndex){\n                    res = -3;\n                    break;\n                }\n                txInsMeta[input].txOut = tempTx.txOuts[tx.txIns[input].outputIndex];\n                res = 1;\n                break;\n            }\n            case 1: { // PSBT_IN_WITNESS_UTXO\n                if(k->length() != 2){\n                    res = -1;\n                    break;\n                }\n                txInsMeta[input].txOut.parse(val_arr+lenVarInt(v->length()), v->length()-lenVarInt(v->length()));\n                if(txInsMeta[input].txOut.getStatus() != PARSING_DONE){\n                    res = -2;\n                    break;\n                }\n                res = 1;\n                break;\n            }\n            case 2: { // PSBT_IN_PARTIAL_SIG\n                if(k->length() != 35 && k->length() != 67){\n                    res = -1;\n                    break;\n                }\n                PSBTPartialSignature psig;\n                psig.pubkey.parse(key_arr+2, k->length()-2);\n                if(psig.pubkey.getStatus() != PARSING_DONE){\n                    res = -1;\n                    break;\n                }\n                psig.signature.parse(val_arr+1, v->length()-1);\n                if(psig.signature.getStatus() != PARSING_DONE){\n                    res = -2;\n                    break;\n                }\n                if(txInsMeta[input].signaturesLen == 0){\n                    txInsMeta[input].signaturesLen = 1;\n                    txInsMeta[input].signatures = new PSBTPartialSignature[txInsMeta[input].signaturesLen];\n                }else{\n                    PSBTPartialSignature * p = txInsMeta[input].signatures;\n                    txInsMeta[input].signatures = new PSBTPartialSignature[txInsMeta[input].signaturesLen+1];\n                    for(size_t i=0; i<txInsMeta[input].signaturesLen; i++){\n                        txInsMeta[input].signatures[i] = p[i];\n                    }\n                    txInsMeta[input].signaturesLen++;\n                    delete [] p;\n                }\n                txInsMeta[input].signatures[txInsMeta[input].signaturesLen-1] = psig;\n                res = 1;\n                break;\n            }\n            case 3: { // PSBT_IN_SIGHASH_TYPE\n                // not implemented\n                break;\n            }\n            case 4: { // PSBT_IN_REDEEM_SCRIPT\n                if(k->length() != 2){\n                    res = -1;\n                    break;\n                }\n                txInsMeta[input].redeemScript.parse(val_arr, v->length());\n                res = 1;\n                break;\n            }\n            case 5: { // PSBT_IN_WITNESS_SCRIPT\n                if(k->length() != 2){\n                    res = -1;\n                    break;\n                }\n                txInsMeta[input].witnessScript.parse(val_arr, v->length());\n                res = 1;\n                break;\n            }\n            case 6: { // PSBT_IN_BIP32_DERIVATION\n                // TODO: move to function\n                if(k->length() != 35 && k->length() != 67){\n                    res = -1;\n                    break;\n                }\n                if(txInsMeta[input].derivationsLen == 0){\n                    txInsMeta[input].derivationsLen = 1;\n                    txInsMeta[input].derivations = new PSBTDerivation[txInsMeta[input].derivationsLen];\n                }else{\n                    PSBTDerivation * p = txInsMeta[input].derivations;\n                    txInsMeta[input].derivations = new PSBTDerivation[txInsMeta[input].derivationsLen+1];\n                    for(size_t i=0; i<txInsMeta[input].derivationsLen; i++){\n                        txInsMeta[input].derivations[i] = p[i];\n                    }\n                    txInsMeta[input].derivationsLen++;\n                    delete [] p;\n                }\n                PSBTDerivation * der = &txInsMeta[input].derivations[txInsMeta[input].derivationsLen-1];\n                der->pubkey.parse(key_arr+2, k->length()-2);\n                if(der->pubkey.getStatus() != PARSING_DONE){\n                    res = -1;\n                    break;\n                }\n                memcpy(der->fingerprint, val_arr+lenVarInt(v->length()), 4);\n                der->derivationLen = (v->length()-lenVarInt(v->length())-4)/sizeof(uint32_t);\n                der->derivation = (uint32_t *)calloc(der->derivationLen, sizeof(uint32_t));\n                if(der->derivation == NULL){ der->derivationLen = 0; res = -1; break; }\n                for(size_t i=0; i<der->derivationLen; i++){\n                    der->derivation[i] = littleEndianToInt(val_arr+lenVarInt(v->length())+4*(i+1),4);\n                }\n                res = 1;\n                break;\n            }\n            case 7: { // PSBT_IN_FINAL_SCRIPTSIG\n                // not implemented\n                break;\n            }\n            case 8: { // PSBT_IN_FINAL_SCRIPTWITNESS\n                // not implemented\n                break;\n            }\n        }\n    }else{ // output section\n        uint8_t output = section-1-tx.inputsNumber;\n        switch(key_code){\n            case 0: { // PSBT_OUT_REDEEM_SCRIPT\n                if(k->length() != 2){\n                    return -1;\n                }\n                txOutsMeta[output].redeemScript.parse(val_arr, v->length());\n                res = 1;\n                break;\n            }\n            case 1: { // PSBT_OUT_WITNESS_SCRIPT\n                if(k->length() != 2){\n                    return -1;\n                }\n                txOutsMeta[output].witnessScript.parse(val_arr, v->length());\n                res = 1;\n                break;\n            }\n            case 2: { // PSBT_OUT_BIP32_DERIVATION\n                // TODO: move to function\n                if(k->length() != 35 && k->length() != 67){\n                    res = -1;\n                    break;\n                }\n                if(txOutsMeta[output].derivationsLen == 0){\n                    txOutsMeta[output].derivationsLen = 1;\n                    txOutsMeta[output].derivations = new PSBTDerivation[txOutsMeta[output].derivationsLen];\n                }else{\n                    PSBTDerivation * p = txOutsMeta[output].derivations;\n                    txOutsMeta[output].derivations = new PSBTDerivation[txOutsMeta[output].derivationsLen+1];\n                    for(int i=0; i<txOutsMeta[output].derivationsLen; i++){\n                        txOutsMeta[output].derivations[i] = p[i];\n                    }\n                    txOutsMeta[output].derivationsLen++;\n                    delete [] p;\n                }\n                PSBTDerivation * der = &txOutsMeta[output].derivations[txOutsMeta[output].derivationsLen-1];\n                der->pubkey.parse(key_arr+2, k->length()-2);\n                if(der->pubkey.getStatus() != PARSING_DONE){\n                    res = -1;\n                    break;\n                }\n                memcpy(der->fingerprint, val_arr+lenVarInt(v->length()), 4);\n                der->derivationLen = (v->length()-lenVarInt(v->length())-4)/sizeof(uint32_t);\n                der->derivation = (uint32_t *)calloc(der->derivationLen, sizeof(uint32_t));\n                if(der->derivation == NULL){ der->derivationLen = 0; res = -1; break; }\n                for(size_t i=0; i<der->derivationLen; i++){\n                    der->derivation[i] = littleEndianToInt(val_arr+lenVarInt(v->length())+4*(i+1),4);\n                }\n                res = 1;\n                break;\n            }\n        }\n    }\n    free(key_arr);\n    free(val_arr);\n    return res; // by default - ignore the key-value pair\n}\n\nsize_t PSBT::to_stream(SerializeStream *s, size_t offset) const{\n    // PSBT prefix + raw transaction key\n    uint8_t prefix[] = {0x70, 0x73, 0x62, 0x74, 0xff, 0x01, 0x00};\n    size_t bytes_written = 0;\n    while(s->available() && bytes_written+offset < 7){\n        s->write(prefix[bytes_written+offset]);\n        bytes_written++;\n    }\n    size_t cur = 7;\n    uint8_t arr[10];\n    size_t l = writeVarInt(tx.length(), arr, 10);\n    while(s->available() && bytes_written+offset < cur+l){\n        s->write(arr[bytes_written+offset-cur]);\n        bytes_written++;\n    }\n    cur+=l;\n    while(s->available() && bytes_written+offset < cur+tx.length()){\n        bytes_written += s->serialize(&tx, offset+bytes_written-cur);\n    }\n    cur+=tx.length();\n    uint8_t sections_number = 1 + tx.inputsNumber + tx.outputsNumber;\n    uint8_t section = 0;\n    while(s->available() && section < sections_number){\n        if(section > 0 && section < tx.inputsNumber+1){\n            uint8_t input = section-1;\n            for(size_t i=0; i<txInsMeta[input].signaturesLen; i++){\n                uint8_t key_arr[67];\n                key_arr[1] = 0x02; // PSBT_IN_PARTIAL_SIG\n                uint8_t key_len = 1+txInsMeta[input].signatures[i].pubkey.serialize(key_arr+2, 65);\n                key_arr[0] = key_len;\n                while(s->available() && bytes_written+offset-cur < (size_t)key_len+1){\n                    s->write(key_arr[bytes_written+offset-cur]);\n                    bytes_written++;\n                }\n                cur += key_len+1;\n                uint8_t val_arr[100];\n                uint8_t val_len = 1+txInsMeta[input].signatures[i].signature.serialize(val_arr+1, 98);\n                val_arr[0] = val_len;\n                val_arr[val_len] = SIGHASH_ALL;\n                while(s->available() && bytes_written+offset-cur < (size_t)val_len+1){\n                    s->write(val_arr[bytes_written+offset-cur]);\n                    bytes_written++;\n                }\n                cur += val_len+1;\n            }\n        }\n        s->write(0);\n        bytes_written++;\n        section++;\n        cur++;\n    }\n    return bytes_written;\n}\n\nsize_t PSBT::length() const{\n    uint8_t sections_number = 1 + tx.inputsNumber + tx.outputsNumber;\n    size_t len = 7 + lenVarInt(tx.length()) + tx.length() + sections_number;\n    for(size_t input=0; input<tx.inputsNumber; input++){\n        for(size_t i=0; i<txInsMeta[input].signaturesLen; i++){\n            len += 2+txInsMeta[input].signatures[i].pubkey.length();\n            len += 2+txInsMeta[input].signatures[i].signature.length();\n        }\n    }\n    return len;\n}\n\nPSBT::PSBT(PSBT const &other){\n    reset();\n    txInsMeta = NULL; txOutsMeta = NULL; status = PARSING_DONE; current_section = 0; last_key_pos = 0;\n    tx = other.tx;\n    status = other.status;\n    txInsMeta = new PSBTInputMetadata[tx.inputsNumber];\n    txOutsMeta = new PSBTOutputMetadata[tx.outputsNumber];\n    for(size_t i=0; i<tx.inputsNumber; i++){\n        txInsMeta[i] = other.txInsMeta[i];\n        txInsMeta[i].derivations = new PSBTDerivation[txInsMeta[i].derivationsLen];\n        for(size_t j=0; j<txInsMeta[i].derivationsLen; j++){\n            txInsMeta[i].derivations[j] = other.txInsMeta[i].derivations[j];\n            txInsMeta[i].derivations[j].derivation = (uint32_t *)calloc(txInsMeta[i].derivations[j].derivationLen, sizeof(uint32_t));\n            if(txInsMeta[i].derivations[j].derivation == NULL){\n                txInsMeta[i].derivations[j].derivationLen = 0;\n            }else{\n                memcpy(txInsMeta[i].derivations[j].derivation, other.txInsMeta[i].derivations[j].derivation, txInsMeta[i].derivations[j].derivationLen*sizeof(uint32_t));\n            }\n        }\n        txInsMeta[i].signatures = new PSBTPartialSignature[txInsMeta[i].signaturesLen];\n        for(size_t j=0; j<txInsMeta[i].signaturesLen; j++){\n            txInsMeta[i].signatures[j] = other.txInsMeta[i].signatures[j];\n        }\n    }\n    for(size_t i=0; i<tx.outputsNumber; i++){\n        txOutsMeta[i] = other.txOutsMeta[i];\n        txOutsMeta[i].derivations = new PSBTDerivation[txOutsMeta[i].derivationsLen];\n        for(size_t j=0; j<txOutsMeta[i].derivationsLen; j++){\n            txOutsMeta[i].derivations[j] = other.txOutsMeta[i].derivations[j];\n            txOutsMeta[i].derivations[j].derivation = (uint32_t *)calloc(txOutsMeta[i].derivations[j].derivationLen, sizeof(uint32_t));\n            if(txOutsMeta[i].derivations[j].derivation == NULL){\n                txOutsMeta[i].derivations[j].derivationLen = 0;\n            }else{\n                memcpy(txOutsMeta[i].derivations[j].derivation, other.txOutsMeta[i].derivations[j].derivation, txOutsMeta[i].derivations[j].derivationLen*sizeof(uint32_t));\n            }\n        }\n    }\n}\n\nPSBT::~PSBT(){\n    // free memory\n    if(tx.inputsNumber > 0){\n        for(size_t i=0; i<tx.inputsNumber; i++){\n            if(txInsMeta[i].derivationsLen > 0){\n                for(size_t j=0; j<txInsMeta[i].derivationsLen; j++){\n                    if(txInsMeta[i].derivations[j].derivationLen > 0){\n                        free(txInsMeta[i].derivations[j].derivation);\n                    }\n                }\n                delete [] txInsMeta[i].derivations;\n            }\n            if(txInsMeta[i].signaturesLen > 0){\n                delete [] txInsMeta[i].signatures;\n            }\n        }\n        delete [] txInsMeta;\n    }\n    if(tx.outputsNumber > 0){\n        for(size_t i=0; i<tx.outputsNumber; i++){\n            if(txOutsMeta[i].derivationsLen > 0){\n                for(size_t j=0; j<txOutsMeta[i].derivationsLen; j++){\n                    if(txOutsMeta[i].derivations[j].derivationLen > 0){\n                        free(txOutsMeta[i].derivations[j].derivation);\n                    }\n                }\n                delete [] txOutsMeta[i].derivations;\n            }\n        }\n        delete [] txOutsMeta;\n    }\n}\n\nuint8_t PSBT::sign(const HDPrivateKey root){\n    uint8_t fingerprint[4];\n    root.fingerprint(fingerprint);\n    uint8_t counter = 0;\n    // in most cases only one account key is required, so we can cache it\n    uint32_t * first_derivation = NULL;\n    uint8_t first_derivation_len = 0;\n    HDPrivateKey account;\n    for(size_t i=0; i<tx.inputsNumber; i++){\n        if(txInsMeta[i].derivationsLen > 0){\n            for(size_t j=0; j<txInsMeta[i].derivationsLen; j++){\n                if(memcmp(fingerprint, txInsMeta[i].derivations[j].fingerprint, 4) == 0){\n                    // caching account key here\n                    if(first_derivation == NULL){\n                        first_derivation = txInsMeta[i].derivations[j].derivation;\n                        first_derivation_len = 0;\n                        for(size_t k=0; k < txInsMeta[i].derivations[j].derivationLen; k++){\n                            if(txInsMeta[i].derivations[j].derivation[k] >= 0x80000000){\n                                first_derivation_len++;\n                            }else{\n                                break;\n                            }\n                        }\n                        account = root.derive(first_derivation, first_derivation_len);\n                    }\n                    PrivateKey pk;\n                    // checking if cached key is ok\n                    if(memcmp(first_derivation, txInsMeta[i].derivations[j].derivation, first_derivation_len*sizeof(uint32_t))==0){\n                        pk = account.derive(txInsMeta[i].derivations[j].derivation+first_derivation_len, txInsMeta[i].derivations[j].derivationLen - first_derivation_len);\n                    }else{\n                        pk = root.derive(txInsMeta[i].derivations[j].derivation, txInsMeta[i].derivations[j].derivationLen);\n                    }\n                    if(txInsMeta[i].derivations[j].pubkey == pk.publicKey()){\n                        // can sign - let's sign\n                        uint8_t h[32];\n                        if(txInsMeta[i].witnessScript.length() > 1){ // P2WSH / P2SH_P2WSH\n                            tx.sigHashSegwit(h, i, txInsMeta[i].witnessScript, txInsMeta[i].txOut.amount);\n                        }else{\n                            if(txInsMeta[i].redeemScript.length() > 1){\n                                if(txInsMeta[i].redeemScript.type() == P2WPKH){ // P2SH_P2WPKH\n                                    // tx.sigHashSegwit(h, i, txInsMeta[i].redeemScript, txInsMeta[i].txOut.amount);\n                                    tx.sigHashSegwit(h, i, pk.publicKey().script(), txInsMeta[i].txOut.amount);\n                                }else{ // P2SH\n                                    tx.sigHash(h, i, txInsMeta[i].redeemScript);\n                                }\n                            }else{ // P2WPKH / P2PKH / DIRECT_SCRIPT\n                                if(txInsMeta[i].txOut.scriptPubkey.type() == P2WPKH){\n                                    // tx.sigHashSegwit(h, i, txInsMeta[i].txOut.scriptPubkey, txInsMeta[i].txOut.amount);\n                                    tx.sigHashSegwit(h, i, pk.publicKey().script(), txInsMeta[i].txOut.amount);\n                                }else{ // P2PKH / DIRECT_SCRIPT\n                                    tx.sigHash(h, i, txInsMeta[i].txOut.scriptPubkey);\n                                }\n                            }\n                        }\n                        Signature sig = pk.sign(h);\n\n                        // adding partial signature to the PSBT\n                        uint8_t arr[67];\n                        arr[1] = 0x02; // PSBT_IN_PARTIAL_SIG\n                        uint8_t len = 1 + pk.publicKey().serialize(arr+2, 65);\n                        arr[0] = len;\n                        Script k;\n                        k.parse(arr, len+1);\n\n                        uint8_t varr[100];\n                        len = 1+sig.serialize(varr+1, 99);\n                        varr[0] = len;\n                        varr[len] = SIGHASH_ALL;\n                        Script val;\n                        val.parse(varr, len+1);\n                        add(i+1, &k, &val);\n                        counter++; // can sign\n                    }\n                }\n            }\n        }\n    }\n    return counter;\n}\n\n// TODO: refactor, super unefficient\n#if USE_ARDUINO_STRING || USE_STD_STRING\nsize_t PSBT::parseBase64(String b64){\n    String s = base64ToHex(b64);\n    parse(s);\n    return s.length()/2;\n}\nString PSBT::toBase64(){\n    return hexToBase64(toString());\n}\n#endif\n\nuint64_t PSBT::fee() const{\n    uint64_t input_amount = 0;\n    uint64_t output_amount = 0;\n    for(size_t i=0; i<tx.inputsNumber; i++){\n        if(txInsMeta[i].txOut.amount == 0){\n            return 0;\n        }\n        input_amount += txInsMeta[i].txOut.amount;\n    }\n    for(size_t i=0; i<tx.outputsNumber; i++){\n        output_amount += tx.txOuts[i].amount;\n    }\n    if(output_amount > input_amount){\n        return 0;\n    }\n    return input_amount-output_amount;\n}\n\nbool PSBT::isMine(uint8_t outputNumber, const HDPublicKey xpub) const{\n    bool mine = false;\n    if(txOutsMeta[outputNumber].derivationsLen > 0){\n        for(unsigned int j=0; j<txOutsMeta[outputNumber].derivationsLen; j++){\n            HDPublicKey pub = xpub.derive(txOutsMeta[outputNumber].derivations[j].derivation, txOutsMeta[outputNumber].derivations[j].derivationLen);\n            if(memcmp(pub.point, txOutsMeta[outputNumber].derivations[j].pubkey.point, 64)==0){\n                mine = true;\n            }\n        }\n    }\n    // TODO: add verification of the script\n    return mine;\n}\n\nbool PSBT::isMine(uint8_t outputNumber, const HDPrivateKey xprv) const{\n    bool mine = false;\n    if(txOutsMeta[outputNumber].derivationsLen > 0){\n        for(unsigned int j=0; j<txOutsMeta[outputNumber].derivationsLen; j++){\n            HDPublicKey pub = xprv.derive(txOutsMeta[outputNumber].derivations[j].derivation, txOutsMeta[outputNumber].derivations[j].derivationLen).xpub();\n            if(memcmp(pub.point, txOutsMeta[outputNumber].derivations[j].pubkey.point, 64)==0){\n                mine = true;\n            }\n        }\n    }\n    // TODO: add verification of the script\n    return mine;\n}\n\nPSBT& PSBT::operator=(PSBT const &other){\n    if (this == &other){ return *this; } // self-assignment\n    // free memory\n    if(tx.inputsNumber > 0){\n        for(size_t i=0; i<tx.inputsNumber; i++){\n            if(txInsMeta[i].derivationsLen > 0){\n                for(size_t j=0; j<txInsMeta[i].derivationsLen; j++){\n                    if(txInsMeta[i].derivations[j].derivationLen > 0){\n                        free(txInsMeta[i].derivations[j].derivation);\n                    }\n                }\n                delete [] txInsMeta[i].derivations;\n            }\n            if(txInsMeta[i].signaturesLen > 0){\n                delete [] txInsMeta[i].signatures;\n            }\n        }\n        delete [] txInsMeta;\n    }\n    if(tx.outputsNumber > 0){\n        for(size_t i=0; i<tx.outputsNumber; i++){\n            if(txOutsMeta[i].derivationsLen > 0){\n                for(size_t j=0; j<txOutsMeta[i].derivationsLen; j++){\n                    if(txOutsMeta[i].derivations[j].derivationLen > 0){\n                        free(txOutsMeta[i].derivations[j].derivation);\n                    }\n                }\n                delete [] txOutsMeta[i].derivations;\n            }\n        }\n        delete [] txOutsMeta;\n    }\n    // copy\n    tx = other.tx;\n    status = other.status;\n    if(tx.inputsNumber > 0){\n        txInsMeta = new PSBTInputMetadata[tx.inputsNumber];\n        for(size_t i=0; i<tx.inputsNumber; i++){\n            txInsMeta[i] = other.txInsMeta[i];\n            if(txInsMeta[i].derivationsLen > 0){\n                txInsMeta[i].derivations = new PSBTDerivation[txInsMeta[i].derivationsLen];\n                for(size_t j=0; j<txInsMeta[i].derivationsLen; j++){\n                    txInsMeta[i].derivations[j] = other.txInsMeta[i].derivations[j];\n                    txInsMeta[i].derivations[j].derivation = (uint32_t*)calloc(txInsMeta[i].derivations[j].derivationLen, sizeof(uint32_t));\n                    if(txInsMeta[i].derivations[j].derivation == NULL){\n                        txInsMeta[i].derivations[j].derivationLen = 0;\n                    }else{\n                        memcpy(txInsMeta[i].derivations[j].derivation, other.txInsMeta[i].derivations[j].derivation, txInsMeta[i].derivations[j].derivationLen*sizeof(uint32_t));\n                    }\n                }\n            }\n            if(txInsMeta[i].signaturesLen > 0){\n                txInsMeta[i].signatures = new PSBTPartialSignature[txInsMeta[i].signaturesLen];\n                for(size_t j=0; j<txInsMeta[i].signaturesLen; j++){\n                    txInsMeta[i].signatures[j] = other.txInsMeta[i].signatures[j];\n                }\n            }\n        }\n    }\n    if(tx.outputsNumber > 0){\n        txOutsMeta = new PSBTOutputMetadata[tx.outputsNumber];\n        for(size_t i=0; i<tx.outputsNumber; i++){\n            txOutsMeta[i] = other.txOutsMeta[i];\n            txOutsMeta[i].derivations = new PSBTDerivation[txOutsMeta[i].derivationsLen];\n            for(size_t j=0; j<txOutsMeta[i].derivationsLen; j++){\n                txOutsMeta[i].derivations[j] = other.txOutsMeta[i].derivations[j];\n                txOutsMeta[i].derivations[j].derivation = (uint32_t *)calloc(txOutsMeta[i].derivations[j].derivationLen, sizeof(uint32_t));\n                if(txOutsMeta[i].derivations[j].derivation == NULL){\n                    txOutsMeta[i].derivations[j].derivationLen = 0;\n                }else{\n                    memcpy(txOutsMeta[i].derivations[j].derivation, other.txOutsMeta[i].derivations[j].derivation, txOutsMeta[i].derivations[j].derivationLen*sizeof(uint32_t));\n                }\n            }\n        }\n    }\n    return *this;\n}\n"
  },
  {
    "path": "src/PSBT.h",
    "content": "#ifndef __PSBT_H__\n#define __PSBT_H__\n\n#include \"Bitcoin.h\"\n\n// TODO: \n// - SIGHASH types, and other key-value pairs that are still not implemented\n// - finalize()\n\n/** \\brief Derivation information */\ntypedef struct{\n\t/** \\brief PublicKey that we are going to derive */\n    PublicKey pubkey;\n    /** \\brief Fingerprint of the root HD key */\n    uint8_t fingerprint[4];\n    /** \\brief Derivation path */\n    uint32_t * derivation;\n    uint8_t derivationLen;\n} PSBTDerivation;\n\n/** \\brief Partial signature */\ntypedef struct{\n    /** \\brief Public key for the signature */\n    PublicKey pubkey;\n    /** \\brief Signature we generated */\n    Signature signature;\n} PSBTPartialSignature;\n\n/** \\brief Data required for input signing */\ntypedef struct{\n\t/** \\brief TransactionOutput data - scriptPubkey and amount */\n    TxOut txOut;\n    /** \\brief Derivation paths for the keys required for signing.\n     *         Can be more than one in case of multisig.\n     */\n    PSBTDerivation * derivations;\n    uint8_t derivationsLen;\n    /** \\brief Redeem script for P2SH */\n    Script redeemScript;\n    /** \\brief Witness script for P2WSH */\n    Script witnessScript;\n    /** \\brief Signatures we will generate. In most cases will be just one. */\n    PSBTPartialSignature * signatures;\n    uint8_t signaturesLen;\n} PSBTInputMetadata;\n\n/** \\brief Data required to confirm ownership of the output */\ntypedef struct{\n    /** \\brief Derivation paths for the keys.\n     *         Can be more than one in case of multisig.\n     */\n    PSBTDerivation * derivations;\n    uint8_t derivationsLen;\n    /** \\brief Redeem script for P2SH */\n    Script redeemScript;\n    /** \\brief Witness script for P2WSH */\n    Script witnessScript;\n} PSBTOutputMetadata;\n\n/** \\brief Calculates descriptor checksum for Bitcoin Core. */\nsize_t descriptorChecksum(const char * span, size_t spanLen, char * output, size_t outputSize);\n#if USE_ARDUINO_STRING\nString descriptorChecksum(String descriptor);\n#elif USE_STD_STRING\nstd::string descriptorChecksum(std::string descriptor);\n#endif\n\n/** \\brief PSBT class. See [bip174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) */\nclass PSBT : public Streamable{\nprotected:\n    virtual size_t from_stream(ParseStream *s);\n    virtual size_t to_stream(SerializeStream *s, size_t offset = 0) const;\n    Script key; // key for parsing\n    Script value; // value for parsing\n    uint8_t current_section;\n    size_t last_key_pos;\npublic:\n    virtual size_t length() const;\n    PSBT(){ txInsMeta = NULL; txOutsMeta = NULL; status = PARSING_DONE; current_section = 0; last_key_pos = 0; };\n    PSBT(PSBT const &other);\n    ~PSBT();\n    Tx tx;\n    PSBTInputMetadata * txInsMeta;\n    PSBTOutputMetadata * txOutsMeta;\n\n    /** \\brief adds key-value pair to section */\n    int add(uint8_t section, const Script * k, const Script * v);\n    /** \\brief Signes everything it can with keys derived from root HD private key */\n    uint8_t sign(const HDPrivateKey root);\n    /** \\brief parses psbt transaction from base64 encoded string */\n#if USE_ARDUINO_STRING\n    size_t parseBase64(String b64);\n    String toBase64();\n#endif\n#if USE_STD_STRING\n    size_t parseBase64(std::string b64);\n    std::string toBase64();\n#endif\n    /** \\brief Calculates fee if input amounts are known */\n    uint64_t fee() const;\n    /** \\brief Verifies if output is mine */\n    bool isMine(uint8_t outputNumber, const HDPublicKey xpub) const;\n    bool isMine(uint8_t outputNumber, const HDPrivateKey xprv) const;\n    // TODO: add verify() function that checks all the fields (scripts, pubkeys etc)\n    // TODO: add isChange() function that would verify the output with respect the inputs\n    PSBT &operator=(PSBT const &other);\n    bool isValid() const{ return status==PARSING_DONE; };\n    explicit operator bool() const{ return isValid(); };\n};\n\n#endif // __PSBT_H__"
  },
  {
    "path": "src/Script.cpp",
    "content": "#include \"Bitcoin.h\"\n#include \"Hash.h\"\n#include \"Conversion.h\"\n#include \"OpCodes.h\"\n#include \"utility/segwit_addr.h\"\n\n#if USE_STD_STRING\nusing std::string;\n#define String string\n#endif\n\n#define MAX_SCRIPT_SIZE 10000\n\n//------------------------------------------------------------ Script-generating functions\n\nScript pkh(PublicKey pub){\n    // 76 a9 14 hash160(pubkey.sec()) 88 ac\n    uint8_t buffer[] = { 0x76, 0xa9, 0x14, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x88,0xac};\n    uint8_t sec_arr[65] = { 0 };\n    int l = pub.sec(sec_arr, sizeof(sec_arr));\n    hash160(sec_arr, l, buffer+3);\n    return Script(buffer, sizeof(buffer));\n}\n\nScript wpkh(PublicKey pub){\n    // 00 14 hash160(pub.sec())\n    uint8_t buffer[] = { 0x00, 0x14, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\n    uint8_t sec_arr[65] = { 0 };\n    int l = pub.sec(sec_arr, sizeof(sec_arr));\n    hash160(sec_arr, l, buffer+2);\n    return Script(buffer, sizeof(buffer));\n}\n\nScript multi(uint8_t threshold, const PublicKey * pubkeys, uint8_t pubkeys_len){\n    Script sc;\n    if(threshold > pubkeys_len || pubkeys_len == 0 || pubkeys_len > 16 || threshold == 0){\n        // returning empty script\n        return sc;\n    }\n    // OP_M\n    sc.push(OP_1+threshold-1);\n    // pubkeys\n    for(int i=0; i<pubkeys_len; i++){\n        sc.push(pubkeys[i]);\n    }\n    // OP_N OP_CHECKMULTISIG\n    sc.push(OP_1+pubkeys_len-1);\n    sc.push(OP_CHECKMULTISIG);\n    return sc;\n}\n\n// function to swap elements\nstatic void swap(PublicKey *a, PublicKey *b) {\n  PublicKey t = *a;\n  *a = *b;\n  *b = t;\n}\n\n// function to find the partition position\nstatic int partition(PublicKey array[], int low, int high) {\n  \n  // select the rightmost element as pivot\n  PublicKey pivot = array[high];\n  \n  // pointer for greater element\n  int i = (low - 1);\n\n  // traverse each element of the array\n  // compare them with the pivot\n  for (int j = low; j < high; j++) {\n    if (array[j] <= pivot) {\n        \n      // if element smaller than pivot is found\n      // swap it with the greater element pointed by i\n      i++;\n      \n      // swap element at i with element at j\n      swap(&array[i], &array[j]);\n    }\n  }\n\n  // swap the pivot element with the greater element at i\n  swap(&array[i + 1], &array[high]);\n  \n  // return the partition point\n  return (i + 1);\n}\n\nstatic void quickSort(PublicKey array[], int low, int high) {\n  if (low < high) {\n    \n    // find the pivot element such that\n    // elements smaller than pivot are on left of pivot\n    // elements greater than pivot are on right of pivot\n    int pi = partition(array, low, high);\n    \n    // recursive call on the left of pivot\n    quickSort(array, low, pi - 1);\n    \n    // recursive call on the right of pivot\n    quickSort(array, pi + 1, high);\n  }\n}\n\nScript sortedmulti(uint8_t threshold, const PublicKey * pubkeys, uint8_t pubkeys_len){\n    // sort first\n    PublicKey * sortedkeys = (PublicKey *) pubkeys;\n    // TODO: the most\n    return multi(threshold, sortedkeys, pubkeys_len);\n}\n\nScript wsh(Script witness_script){\n    // 00 20 sha256(script.data)\n    uint8_t buffer[] = { 0x00, 0x20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\n    sha256(witness_script.scriptArray, witness_script.scriptLen, buffer+2);\n    return Script(buffer, sizeof(buffer));\n}\n\nScript sh(Script script){\n    // \"a9 14\" + hash160(script.data) + \"87\"\n    uint8_t buffer[] = { 0xa9, 0x14, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x87 };\n    hash160(script.scriptArray, script.scriptLen, buffer+2);\n    return Script(buffer, sizeof(buffer));\n}\n\n//------------------------------------------------------------ Script\nvoid Script::init(){\n    reset();\n    scriptLen = 0;\n    scriptArray = NULL;\n    lenLen = 0;\n}\nScript::Script(void){\n    init();\n}\nScript::Script(const uint8_t * buffer, size_t len){\n    init();\n    push(buffer, len);\n}\nvoid Script::fromAddress(const char * address){\n    clear();\n    uint8_t addr[21];\n    size_t len = strlen(address);\n    if(len > 100){ // very wrong address\n        return;\n    }\n    ScriptType type = UNKNOWN_TYPE;\n    const Network * network;\n    for(int i=0; i<networks_len; i++){\n        if(memcmp(address, networks[i]->bech32, strlen(networks[i]->bech32))==0){\n            type = P2WPKH;\n            network = networks[i];\n            break;\n        }\n    }\n    // segwit\n    if(type == P2WPKH){\n        int ver = 0;\n        uint8_t prog[32];\n        size_t prog_len = 0;\n        int r = segwit_addr_decode(&ver, prog, &prog_len, network->bech32, address);\n        if(r != 1){ // decoding failed\n            return;\n        }\n        scriptLen = prog_len + 2;\n        scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ scriptLen = 0; return; }\n        scriptArray[0] = ver;\n        scriptArray[1] = prog_len; // varint?\n        memcpy(scriptArray+2, prog, prog_len);\n    }else{ // legacy or nested segwit\n        int l = fromBase58Check(address, len, addr, sizeof(addr));\n        if(l != 21){ // either wrong checksum or wierd address\n            return;\n        }\n        for(int i=0; i<networks_len; i++){\n            if(addr[0]==networks[i]->p2pkh){\n                type = P2PKH;\n                network = networks[i];\n                break;\n            }\n            if(addr[0]==networks[i]->p2sh){\n                type = P2SH;\n                network = networks[i];\n                break;\n            }\n        }\n        if(type == P2PKH){\n            scriptLen = 25;\n            scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n            if(scriptArray == NULL){ scriptLen = 0; return; }\n            scriptArray[0] = OP_DUP;\n            scriptArray[1] = OP_HASH160;\n            scriptArray[2] = 20;\n            memcpy(scriptArray+3, addr+1, 20);\n            scriptArray[23] = OP_EQUALVERIFY;\n            scriptArray[24] = OP_CHECKSIG;\n        }\n        if(type == P2SH){\n            scriptLen = 23;\n            scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n            if(scriptArray == NULL){ scriptLen = 0; return; }\n            scriptArray[0] = OP_HASH160;\n            scriptArray[1] = 20;\n            memcpy(scriptArray+2, addr+1, 20);\n            scriptArray[22] = OP_EQUAL;\n        }\n    }\n}\nScript::Script(const PublicKey pubkey, ScriptType type){\n    init();\n    if(type == P2PKH){\n        scriptLen = 25;\n        scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ scriptLen = 0; return; }\n        scriptArray[0] = OP_DUP;\n        scriptArray[1] = OP_HASH160;\n        scriptArray[2] = 20;\n        uint8_t sec_arr[65] = { 0 };\n        int l = pubkey.sec(sec_arr, sizeof(sec_arr));\n        hash160(sec_arr, l, scriptArray+3);\n        scriptArray[23] = OP_EQUALVERIFY;\n        scriptArray[24] = OP_CHECKSIG;\n    }\n    if(type == P2WPKH){\n        scriptLen = 22;\n        scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ scriptLen = 0; return; }\n        scriptArray[0] = 0x00;\n        scriptArray[1] = 20;\n        uint8_t sec_arr[65] = { 0 };\n        int l = pubkey.sec(sec_arr, sizeof(sec_arr));\n        hash160(sec_arr, l, scriptArray+2);\n    }\n}\nScript::Script(const Script &other, ScriptType type){\n    init();\n    if(type == P2SH){\n        scriptLen = 23;\n        scriptArray = (uint8_t *) calloc(scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ scriptLen = 0; return; }\n        hash160(other.scriptArray, other.scriptLen, scriptArray+2);\n        scriptArray[0] = OP_HASH160;\n        scriptArray[1] = 20;\n        scriptArray[scriptLen-1] = OP_EQUAL;\n    }\n    if(type == P2WSH){\n        scriptLen = 34;\n        scriptArray = (uint8_t *) calloc(scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ scriptLen = 0; return; }\n        sha256(other.scriptArray, other.scriptLen, scriptArray+2);\n        scriptArray[0] = 0x00;\n        scriptArray[1] = 32;\n    }\n}\nvoid Script::clear(){\n    if(scriptLen > 0 && scriptArray != NULL){\n        free(scriptArray);\n        scriptArray = NULL;\n        scriptLen = 0;\n        lenLen = 0;\n    }\n}\nsize_t Script::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n        clear();\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    // reading scriptLen varint\n    if(s->available() && bytes_parsed == 0){ \n        lenLen = s->read();\n        bytes_read++;\n        if(lenLen < 0xfd){\n            scriptLen = lenLen;\n            if(scriptLen > 0){\n                scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n            }\n            lenLen = 1;\n        }else{\n            scriptLen = 0;\n            lenLen = 1+(1 << (lenLen - 0xfc));\n            scriptArray = (uint8_t *) calloc( 255, sizeof(uint8_t));\n        }\n        if(scriptArray == NULL && scriptLen > 0){ status = PARSING_FAILED; scriptLen = 0; return 0; }\n    }\n    while(s->available() > 0 && bytes_parsed+bytes_read < lenLen){\n        scriptLen += (s->read() << (8*(bytes_parsed+bytes_read-1)));\n        bytes_read++;\n    }\n    if(bytes_parsed+bytes_read == lenLen && scriptLen > 0){\n        free(scriptArray);\n        scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ status = PARSING_FAILED; scriptLen = 0; return 0; }\n    }\n    if(bytes_parsed+bytes_read == lenLen && lenVarInt(scriptLen) != lenLen){\n        status = PARSING_FAILED;\n        bytes_parsed+=bytes_read;\n        return bytes_read;\n    }\n    // reading the script\n    while(s->available() > 0 && bytes_parsed+bytes_read < scriptLen+lenLen){\n        scriptArray[bytes_parsed+bytes_read-lenLen] = s->read();\n        bytes_read++;\n    }\n    if(bytes_parsed+bytes_read == scriptLen+lenLen){\n        status = PARSING_DONE;\n    }\n    bytes_parsed += bytes_read;\n    return bytes_read;\n}\nsize_t Script::to_stream(SerializeStream *s, size_t offset) const{\n    size_t bytes_written = 0;\n    // varint\n    uint8_t l = lenVarInt(scriptLen);\n    uint8_t arr[10];\n    writeVarInt(scriptLen, arr, sizeof(arr));\n    while(s->available() && bytes_written+offset < l){\n        s->write(arr[offset+bytes_written]);\n        bytes_written++;\n    }\n    while(s->available() && bytes_written+offset < l+scriptLen){\n        s->write(scriptArray[bytes_written+offset-l]);\n        bytes_written++;\n    }\n    return bytes_written;\n}\nScriptType Script::type() const{\n    if(\n        (scriptLen == 25) &&\n        (scriptArray[0] == OP_DUP) &&\n        (scriptArray[1] == OP_HASH160) &&\n        (scriptArray[2] == 20) &&\n        (scriptArray[23] == OP_EQUALVERIFY) &&\n        (scriptArray[24] == OP_CHECKSIG)\n    ){\n        return P2PKH;\n    }\n    if(\n        (scriptLen == 23) &&\n        (scriptArray[0] == OP_HASH160) &&\n        (scriptArray[1] == 20) &&\n        (scriptArray[22] == OP_EQUAL)\n    ){\n        return P2SH;\n    }\n    if(\n        (scriptLen == 22) &&\n        (scriptArray[0] == 0x00) &&\n        (scriptArray[1] == 20)\n    ){\n        return P2WPKH;\n    }\n    if(\n        (scriptLen == 34) &&\n        (scriptArray[0] == 0x00) &&\n        (scriptArray[1] == 32)\n    ){\n        return P2WSH;\n    }\n    return UNKNOWN_TYPE;\n}\nsize_t Script::address(char * buffer, size_t len, const Network * network) const{\n    memset(buffer, 0, len);\n    if(type() == P2PKH){\n        uint8_t addr[21];\n        addr[0] = network->p2pkh;\n        memcpy(addr+1, scriptArray + 3, 20);\n        char address[40] = { 0 };\n        toBase58Check(addr, 21, address, sizeof(address));\n        size_t l = strlen(address);\n        if(l > len){\n            return 0;\n        }\n        memcpy(buffer, address, l);\n        return l;\n    }\n    if(type() == P2SH){\n        uint8_t addr[21];\n        addr[0] = network->p2sh;\n        memcpy(addr+1, scriptArray + 2, 20);\n        char address[40] = { 0 };\n        toBase58Check(addr, 21, address, sizeof(address));\n        size_t l = strlen(address);\n        if(l > len){\n            return 0;\n        }\n        memcpy(buffer, address, l);\n        return l;\n    }\n    if(type() == P2WPKH || type() == P2WSH){\n        char address[76] = { 0 };\n        segwit_addr_encode(address, network->bech32, scriptArray[0], scriptArray+2, scriptArray[1]);\n        size_t l = strlen(address);\n        if(l > len){\n            return 0;\n        }\n        memcpy(buffer, address, l);\n        return l;\n    }\n    return 0;\n}\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString Script::address(const Network * network) const{\n    char buffer[100] = { 0 };\n    size_t l = address(buffer, sizeof(buffer), network);\n    if(l == 0){\n        return String(\"\");\n    }\n    return String(buffer);\n}\n#endif\nsize_t Script::length() const{\n    return scriptLen + lenVarInt(scriptLen);\n}\nsize_t Script::push(uint8_t code){\n    if(scriptLen+1 > MAX_SCRIPT_SIZE){\n        clear();\n        return 0;\n    }\n    if(scriptLen == 0){\n        scriptLen = 1;\n        scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ scriptLen = 0; return 0; } // check if allocation failed\n    }else{\n        scriptLen ++;\n        uint8_t * ptr = (uint8_t *) realloc( scriptArray, scriptLen * sizeof(uint8_t));\n        if(ptr == NULL){ free(scriptArray); scriptArray = NULL; scriptLen = 0; return 0; } // check if realloc failed\n        scriptArray = ptr;\n    }\n    scriptArray[scriptLen-1] = code;\n    return scriptLen;\n}\nsize_t Script::push(const uint8_t * data, size_t len){\n    if(scriptLen+len > MAX_SCRIPT_SIZE){\n        clear();\n        return 0;\n    }\n    if(scriptLen == 0){\n        scriptArray = (uint8_t *) calloc( len, sizeof(uint8_t));\n    }else{\n        uint8_t * ptr = (uint8_t *) realloc( scriptArray, (scriptLen + len) * sizeof(uint8_t));\n        if(ptr == NULL){ free(scriptArray); scriptArray = NULL; scriptLen = 0; return 0; }\n        scriptArray = ptr;\n    }\n    if(scriptArray == NULL){ scriptLen = 0; return 0; }\n    memcpy(scriptArray + scriptLen, data, len);\n    scriptLen += len;\n    return scriptLen;\n}\nsize_t Script::push(const PublicKey pubkey){\n    uint8_t sec[65];\n    uint8_t len = pubkey.sec(sec, sizeof(sec));\n    push(len);\n    push(sec, len);\n    return scriptLen;\n}\nsize_t Script::push(const Signature sig, SigHashType sigType){\n    uint8_t der[75];\n    uint8_t len = sig.der(der, sizeof(der));\n    push(len+1);\n    push(der, len);\n    push(sigType);\n    return scriptLen;\n}\nsize_t Script::push(const Script sc){\n    size_t len = sc.length();\n    uint8_t * tmp;\n    tmp = (uint8_t *)calloc(len, sizeof(uint8_t));\n    if(tmp == NULL){ return 0; }\n    sc.serialize(tmp, len);\n    push(tmp, len);\n    return scriptLen;\n}\nScript Script::scriptPubkey(ScriptType type) const{\n    Script sc(*this, type);\n    return sc;\n}\nScript &Script::operator=(const Script &other){\n    if (this == &other){ return *this; } // self-assignment\n    reset();\n    clear();\n    if(other.scriptLen > 0){\n        scriptLen = other.scriptLen;\n        scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ scriptLen = 0; return *this; }\n        memcpy(scriptArray, other.scriptArray, scriptLen);\n    }\n    return *this;\n};\nScript::Script(const Script &other){\n    init();\n    if(other.scriptLen > 0){\n        scriptLen = other.scriptLen;\n        scriptArray = (uint8_t *) calloc( scriptLen, sizeof(uint8_t));\n        if(scriptArray == NULL){ scriptLen = 0; return; }\n        memcpy(scriptArray, other.scriptArray, scriptLen);\n    }\n};\n\n//------------------------------------------------------------ Witness\n\nvoid Witness::clear(){\n    numElements = 0;\n    if(witnessLen > 0){\n        free(witnessArray);\n        witnessLen = 0;\n    }\n}\nvoid Witness::init(){\n    numElements = 0;\n    witnessLen = 0;\n    witnessArray = NULL;\n    curLen = 0;\n    reset();\n    clear();\n}\nWitness::Witness(void){\n    init();\n}\nWitness::Witness(const uint8_t * buffer, size_t len){\n    init();\n    ParseByteStream s(buffer, len);\n    Witness::from_stream(&s);\n}\nWitness::Witness(const Signature sig, const PublicKey pubkey){\n    init();\n    push(sig);\n    push(pubkey);\n}\nsize_t Witness::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n        cur_element = 0;\n        curLen = 0;\n        cur_element_len = 0;\n        cur_bytes_parsed = 0;\n        reset();\n        clear();\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    // reading elements len varint\n    if(s->available() && bytes_parsed == 0){ \n        lenLen = s->read();\n        bytes_read++;\n        if(lenLen < 0xfd){\n            numElements = lenLen;\n            lenLen = 1;\n        }else{\n            numElements = 0;\n            status = PARSING_FAILED;\n            bytes_parsed += bytes_read;\n            return bytes_read;\n        }\n    }\n    if(bytes_parsed+bytes_read == lenLen && lenVarInt(numElements) != lenLen){\n        status = PARSING_FAILED;\n        bytes_parsed+=bytes_read;\n        return bytes_read;\n    }\n    // reading elements\n    while(s->available() && cur_element<numElements){\n        // beginning of the element\n        size_t offset = bytes_parsed+bytes_read-lenVarInt(numElements)-cur_bytes_parsed;\n        size_t cur_bytes_read = 0;\n        // reading scriptLen varint\n        if(s->available() && cur_bytes_parsed == 0){ \n            curLen = s->read();\n            cur_bytes_read++;\n            if(curLen < 0xfd){\n                cur_element_len = curLen;\n                curLen = 1;\n            }else{\n                cur_element_len = 0;\n                curLen = 1+(1 << (curLen - 0xfc));\n            }\n        }\n        while(s->available() && cur_bytes_parsed+cur_bytes_read < curLen){\n            cur_element_len += (s->read() << (8*(cur_bytes_parsed+cur_bytes_read-1)));\n            cur_bytes_read++;\n        }\n        if(lenVarInt(cur_element_len) != curLen && cur_bytes_parsed+cur_bytes_read == curLen){\n            status = PARSING_FAILED;\n            cur_bytes_parsed+=cur_bytes_read;\n            bytes_read+=cur_bytes_read;\n            bytes_parsed+=bytes_read;\n            return bytes_read;\n        }\n        if(cur_bytes_parsed+cur_bytes_read == curLen && cur_bytes_read>0){\n            if(witnessLen==0){\n                witnessLen = cur_element_len+lenVarInt(cur_element_len);\n                witnessArray = (uint8_t *)calloc(witnessLen, sizeof(uint8_t));\n                if(witnessArray == NULL){ witnessLen = 0; status=PARSING_FAILED; return 0;}\n                writeVarInt(cur_element_len, witnessArray, lenVarInt(cur_element_len));\n            }else{\n                uint8_t * ptr = (uint8_t *)realloc( witnessArray, (witnessLen + cur_element_len + lenVarInt(cur_element_len)) * sizeof(uint8_t));\n                if(ptr == NULL){ free(witnessArray); witnessLen = 0; status=PARSING_FAILED; return 0;}\n                witnessArray = ptr;\n                witnessLen += cur_element_len+lenVarInt(cur_element_len);\n                writeVarInt(cur_element_len, witnessArray+offset, lenVarInt(cur_element_len));\n            }\n        }\n        while(s->available() > 0 && cur_bytes_parsed+cur_bytes_read < cur_element_len+lenVarInt(cur_element_len)){\n            witnessArray[offset+cur_bytes_parsed+cur_bytes_read] = s->read();\n            // s->read();\n            cur_bytes_read++;\n        }\n        if(cur_bytes_parsed+cur_bytes_read==cur_element_len+lenVarInt(cur_element_len)){\n            curLen = 0;\n            cur_element_len = 0;\n            cur_element++;\n            cur_bytes_parsed=0;\n        }else{\n            cur_bytes_parsed += cur_bytes_read;\n        }\n        bytes_read += cur_bytes_read;\n    }\n    if(cur_element==numElements){\n        status = PARSING_DONE;\n    }\n    bytes_parsed += bytes_read;\n    return bytes_read;\n}\nsize_t Witness::to_stream(SerializeStream *s, size_t offset) const{\n    size_t bytes_written = 0;\n    // varint\n    uint8_t l = lenVarInt(numElements);\n    uint8_t arr[10];\n    writeVarInt(numElements, arr, sizeof(arr));\n    while(s->available() && bytes_written+offset < l){\n        s->write(arr[offset+bytes_written]);\n        bytes_written++;\n    }\n    while(s->available() && bytes_written+offset < l+witnessLen){\n        s->write(witnessArray[bytes_written+offset-l]);\n        bytes_written++;\n    }\n    return bytes_written;\n}\nsize_t Witness::length() const{\n    return witnessLen + lenVarInt(numElements);\n}\nsize_t Witness::push(const uint8_t * data, size_t len){\n    if(witnessLen + len + lenVarInt(len) > MAX_SCRIPT_SIZE){\n        clear();\n        return 0;\n    }\n    if(witnessLen == 0){\n        witnessArray = (uint8_t *) calloc( len + lenVarInt(len), sizeof(uint8_t));\n        if(witnessArray == NULL){ witnessLen = 0; return 0; }\n    }else{\n        uint8_t * ptr = (uint8_t *) realloc( witnessArray, (witnessLen + len + lenVarInt(len)) * sizeof(uint8_t));\n        if(ptr == NULL){ free(witnessArray); witnessLen = 0; return 0; }\n        witnessArray = ptr;\n    }\n    writeVarInt(len, witnessArray+witnessLen, lenVarInt(len));\n    memcpy(witnessArray + witnessLen + lenVarInt(len), data, len);\n    witnessLen += len+lenVarInt(len);\n    numElements++;\n    return witnessLen;\n}\nsize_t Witness::push(const PublicKey pubkey){\n    uint8_t sec[65];\n    uint8_t len = pubkey.sec(sec, sizeof(sec));\n    push(sec, len);\n    return witnessLen;\n}\nsize_t Witness::push(const Signature sig, SigHashType sigType){\n    uint8_t der[75];\n    uint8_t len = sig.der(der, sizeof(der));\n    der[len] = sigType;\n    push(der, len+1);\n    return witnessLen;\n}\nsize_t Witness::push(const Script sc){\n    size_t len = sc.length();\n    uint8_t * tmp;\n    tmp = (uint8_t *)calloc(len, sizeof(uint8_t));\n    if(tmp == NULL){ return 0; }\n    size_t l = sc.serialize(tmp, len);\n    size_t dl = readVarInt(tmp, len);\n    push(tmp+l-dl, dl);\n    free(tmp);\n    return witnessLen;\n}\nWitness::Witness(const Witness &other){\n    init();\n    numElements = other.numElements;\n    if(other.witnessLen > 0){\n        witnessLen = other.witnessLen;\n        witnessArray = (uint8_t *) calloc( witnessLen, sizeof(uint8_t));\n        if(witnessArray == NULL){ witnessLen = 0; return;}\n        memcpy(witnessArray, other.witnessArray, witnessLen);\n    }\n};\nWitness &Witness::operator=(Witness const &other){\n    if (this == &other){ return *this; } // self-assignment\n    clear();\n    numElements = other.numElements;\n    if(other.witnessLen > 0){\n        witnessLen = other.witnessLen;\n        witnessArray = (uint8_t *) calloc( witnessLen, sizeof(uint8_t));\n        if(witnessArray == NULL){ witnessLen = 0; return *this;}\n        memcpy(witnessArray, other.witnessArray, witnessLen);\n    }\n    return *this;\n};\n"
  },
  {
    "path": "src/Transaction.cpp",
    "content": "#include <stdint.h>\n#include <string.h>\n#include \"Bitcoin.h\"\n#include \"Hash.h\"\n#include \"Conversion.h\"\n#include \"utility/trezor/sha2.h\"\n\n#if USE_STD_STRING\nusing std::string;\n#define String string\n#endif\n\n#define UBTC_ERR_TX_GLOBAL 1\n#define UBTC_ERR_TX_INPUT  2\n#define UBTC_ERR_TX_OUTPUT 3\n#define UBTC_ERR_TX_SCRIPT 4\n\n//-------------------------------------------------------------------------------------- Transaction Input\nvoid TxIn::init(){\n    outputIndex = 0;\n    sequence = 0;\n    memset(hash, 0, 32);\n    status = PARSING_DONE;\n    bytes_parsed = 0;\n}\nTxIn::TxIn(void){\n    init();\n}\nTxIn::TxIn(const uint8_t prev_id[32], uint32_t prev_index, uint32_t sequence_number){\n    init();\n    outputIndex = prev_index;\n    sequence = sequence_number;\n    for(int i=0; i<32; i++){\n        hash[i] = prev_id[31-i];\n    }\n}\nTxIn::TxIn(const uint8_t prev_id[32], uint32_t prev_index, const Script script, uint32_t sequence_number){\n    outputIndex = prev_index;\n    sequence = sequence_number;\n    for(int i=0; i<32; i++){\n        hash[i] = prev_id[31-i];\n    }\n    scriptSig = script;\n}\nTxIn::TxIn(const char * prev_id, uint32_t prev_index, uint32_t sequence_number){\n    init();\n    memset(hash, 0, 32);\n    if(strlen(prev_id) < 64){\n        return;\n    }\n    outputIndex = prev_index;\n    sequence = sequence_number;\n    uint8_t arr[32];\n    fromHex(prev_id, 64, arr, 32);\n    for(int i=0; i<32; i++){\n        hash[i] = arr[31-i];\n    }\n}\nTxIn::TxIn(const char * prev_id, uint32_t prev_index, const Script script, uint32_t sequence_number){\n    outputIndex = prev_index;\n    sequence = sequence_number;\n    if(strlen(prev_id) < 64){\n        return;\n    }\n    uint8_t tmp[32];\n    fromHex(prev_id, 64, tmp, 32);\n    for(int i=0; i<32; i++){\n        hash[i] = tmp[31-i];\n    }\n    scriptSig = script;\n}\nsize_t TxIn::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n        outputIndex = 0;\n        sequence = 0;\n        scriptSig = Script();\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    while(s->available() && bytes_read+bytes_parsed<32){\n        hash[bytes_read+bytes_parsed] = s->read();\n        bytes_read++;\n    }\n    while(s->available() && bytes_read+bytes_parsed<32+4){\n        uint8_t c = s->read();\n        outputIndex += (c << (8*(bytes_read+bytes_parsed-32)));\n        bytes_read++;\n    }\n    if(s->available() && bytes_read+bytes_parsed == 32+4){\n        bytes_read += s->parse(&scriptSig);\n    }\n    if(s->available() && scriptSig.getStatus() == PARSING_INCOMPLETE){\n        bytes_read += s->parse(&scriptSig);\n    }\n    if(scriptSig.getStatus() == PARSING_FAILED){\n        status = PARSING_FAILED;\n        ubtc_errno = UBTC_ERR_TX_SCRIPT | UBTC_ERR_TX_INPUT;\n        bytes_parsed+=bytes_read;\n        return bytes_read;\n    }\n    while(s->available() && bytes_read+bytes_parsed < 32+4+scriptSig.length()+4){\n        uint8_t c = s->read();\n        sequence += (c << (8*(bytes_read+bytes_parsed-scriptSig.length()-32-4)));\n        bytes_read++;\n    }\n    if(scriptSig.getStatus() == PARSING_DONE && bytes_read+bytes_parsed == 32+4+scriptSig.length()+4){\n        status = PARSING_DONE;\n    }\n    bytes_parsed+=bytes_read;\n    return bytes_read;\n}\nsize_t TxIn::to_stream(SerializeStream *s, size_t offset) const{\n    size_t bytes_written = 0;\n    while(s->available() && bytes_written+offset < 32){\n        s->write(hash[bytes_written+offset]);\n        bytes_written++;\n    }\n    uint8_t arr[4];\n    intToLittleEndian(outputIndex, arr, 4);\n    while(s->available() && bytes_written+offset < 32+4){\n        s->write(arr[bytes_written+offset-32]);\n        bytes_written++;\n    }\n    size_t len = scriptSig.length();\n    if(s->available() && bytes_written+offset < 32+4+len){\n        bytes_written+=s->serialize(&scriptSig, bytes_written+offset-32-4);\n    }\n    intToLittleEndian(sequence, arr, 4);\n    while(s->available() && bytes_written+offset < 32+4+len+4){\n        s->write(arr[bytes_written+offset-(32+4+len)]);\n        bytes_written++;\n    }\n    return bytes_written;\n}\nsize_t TxIn::length() const{\n    return 32+4+scriptSig.length()+4;\n}\n\n//-------------------------------------------------------------------------------------- Transaction Output\n\nsize_t TxOut::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        bytes_parsed = 0;\n        memset(tmp, 0, sizeof(tmp));\n        amount = 0;\n        scriptPubkey.clear(); scriptPubkey.reset();\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    while(s->available() && bytes_read+bytes_parsed<8){\n        uint8_t c = s->read();\n        tmp[bytes_read+bytes_parsed] = c;\n        bytes_read++;\n        amount = littleEndianToInt(tmp, 8);\n    }\n    if(s->available() && bytes_read+bytes_parsed == 8){\n        bytes_read += s->parse(&scriptPubkey);\n    }\n    if(s->available() && scriptPubkey.getStatus() == PARSING_INCOMPLETE){\n        bytes_read += s->parse(&scriptPubkey);\n    }\n    if(scriptPubkey.getStatus() == PARSING_FAILED){\n        status = PARSING_FAILED;\n        ubtc_errno = UBTC_ERR_TX_SCRIPT | UBTC_ERR_TX_OUTPUT;\n        bytes_parsed+=bytes_read;\n        return bytes_read;\n    }\n    if(scriptPubkey.getStatus() == PARSING_DONE && bytes_read+bytes_parsed == 8+scriptPubkey.length()){\n        status = PARSING_DONE;\n    }\n    bytes_parsed+=bytes_read;\n    return bytes_read;\n}\n\nsize_t TxOut::to_stream(SerializeStream *s, size_t offset) const{\n    size_t bytes_written = 0;\n    uint8_t arr[8] = { 0 };\n    intToLittleEndian(amount, arr, 8);\n    while(s->available() && bytes_written+offset < 8){\n        s->write(arr[bytes_written+offset]);\n        bytes_written++;\n    }\n    size_t len = scriptPubkey.length();\n    if(s->available() && bytes_written+offset < 8+len){\n        bytes_written += s->serialize(&scriptPubkey, bytes_written+offset-8);\n    }\n    return bytes_written;\n}\n\n//-------------------------------------------------------------------------------------- Transaction\nvoid Tx::init(){\n    version = 1;\n    inputsNumber = 0;\n    outputsNumber = 0;\n    txIns = NULL;\n    txOuts = NULL;\n    locktime = 0;\n    segwit_flag = 1;\n    status = PARSING_DONE;\n    bytes_parsed = 0;\n}\nTx::Tx(){\n    init();\n}\nTx::Tx(const Tx & other){\n    init();\n    version = other.version;\n    inputsNumber = other.inputsNumber;\n    outputsNumber = other.outputsNumber;\n    txIns = new TxIn[inputsNumber];\n    txOuts = new TxOut[outputsNumber];\n    for(unsigned int i=0;i<inputsNumber;i++){\n        txIns[i] = other.txIns[i];\n    }\n    for(unsigned int i=0;i<outputsNumber;i++){\n        txOuts[i] = other.txOuts[i];\n    }\n    locktime = other.locktime;\n    segwit_flag = other.segwit_flag;\n    status = other.status;\n    bytes_parsed = other.bytes_parsed;\n}\nTx& Tx::operator=(Tx const &other){ // copy-paste =(\n    if (this == &other){ return *this; } // self-assignment\n    version = other.version;\n    if(inputsNumber > 0){\n        delete [] txIns;\n    }\n    if(outputsNumber > 0){\n        delete [] txOuts;\n    }\n    inputsNumber = other.inputsNumber;\n    outputsNumber = other.outputsNumber;\n    txIns = new TxIn[inputsNumber];\n    txOuts = new TxOut[outputsNumber];\n    for(unsigned int i=0;i<inputsNumber;i++){\n        txIns[i] = other.txIns[i];\n    }\n    for(unsigned int i=0;i<outputsNumber;i++){\n        txOuts[i] = other.txOuts[i];\n    }\n    locktime = other.locktime;\n    segwit_flag = other.segwit_flag;\n    status = other.status;\n    bytes_parsed = other.bytes_parsed;\n    return *this;\n}\nTx::~Tx(){\n    clear();\n}\nvoid Tx::clear(){\n    if(inputsNumber > 0){\n        inputsNumber = 0;\n        delete [] txIns;\n        txIns = NULL;\n    }\n    if(outputsNumber > 0){\n        outputsNumber = 0;\n        delete [] txOuts;\n        txOuts = NULL;\n    }\n}\nsize_t Tx::length() const{\n    bool is_segwit = isSegwit();\n    size_t l = 4+4+lenVarInt(inputsNumber)+lenVarInt(outputsNumber)+2*is_segwit;\n    for(unsigned int i=0; i<inputsNumber; i++){\n        l += txIns[i].length();\n        if(is_segwit){\n            l += txIns[i].witness.length();\n        }\n    }\n    for(unsigned int i=0; i<outputsNumber; i++){\n        l += txOuts[i].length();\n    }\n    return l;\n}\nbool Tx::isSegwit() const{\n    for(unsigned int i=0; i<inputsNumber; i++){\n        if(txIns[i].isSegwit()){\n            return true;\n        }\n    }\n    return false;\n}\nsize_t Tx::to_stream(SerializeStream *s, size_t offset) const{\n    size_t bytes_written = 0;\n    uint8_t arr[10] = { 0 }; // we will store varints and other numbers here\n    intToLittleEndian(version, arr, 4);\n    while(s->available() && bytes_written+offset < 4){\n        s->write(arr[bytes_written+offset]);\n        bytes_written++;\n    }\n    bool is_segwit = isSegwit();\n    if(is_segwit && s->available() && bytes_written+offset == 4){\n        s->write(0x00); // segwit marker\n        bytes_written++;\n    }\n    if(is_segwit && s->available() && bytes_written+offset == 5){\n        s->write(0x01); // segwit flag\n        bytes_written++;\n    }\n    size_t cur_offset = 4+2*is_segwit;\n    size_t l = writeVarInt(inputsNumber, arr, 10);\n    if(s->available() && bytes_written+offset < cur_offset+l){\n        s->write(arr[bytes_written+offset-cur_offset]);\n        bytes_written++;\n    }\n    cur_offset+=l;\n    for(unsigned int i=0; i<inputsNumber; i++){\n        l = txIns[i].length();\n        if(s->available() && bytes_written+offset < cur_offset+l){\n            bytes_written += s->serialize(&txIns[i], bytes_written+offset-cur_offset);\n        }\n        cur_offset+=l;\n    }\n    l = writeVarInt(outputsNumber, arr, 10);\n    if(s->available() && bytes_written+offset < cur_offset+l){\n        s->write(arr[bytes_written+offset-cur_offset]);\n        bytes_written++;\n    }\n    cur_offset += l;\n    for(unsigned int i=0; i<outputsNumber; i++){\n        l = txOuts[i].length();\n        if(s->available() && bytes_written+offset < cur_offset+l){\n            bytes_written += s->serialize(&txOuts[i], bytes_written+offset-cur_offset);\n        }\n        cur_offset+=l;\n    }\n    if(is_segwit){\n        for(unsigned int i=0; i<inputsNumber; i++){\n            l = txIns[i].witness.length();\n            if(s->available() && bytes_written+offset < cur_offset+l){\n                bytes_written += s->serialize(&txIns[i].witness, bytes_written+offset-cur_offset);\n            }\n            cur_offset+=l;\n        }\n    }\n    intToLittleEndian(locktime, arr, 4);\n    while(s->available() && bytes_written+offset < cur_offset+4){\n        s->write(arr[bytes_written+offset-cur_offset]);\n        bytes_written++;\n    }\n    return bytes_written;\n}\nsize_t Tx::from_stream(ParseStream *s){\n    if(status == PARSING_FAILED){\n        return 0;\n    }\n    if(status == PARSING_DONE){\n        clear();\n        bytes_parsed = 0;\n        version = 0;\n        locktime = 0;\n        segwit_flag = 0; // keep segwit flag during parsing...\n    }\n    status = PARSING_INCOMPLETE;\n    size_t bytes_read = 0;\n    while(s->available() && bytes_read+bytes_parsed<4){\n        uint8_t c = s->read();\n        version += (c << (8*(bytes_read+bytes_parsed)));\n        bytes_read++;\n    }\n    if(s->available() && bytes_read+bytes_parsed == 4){\n        uint8_t c = s->read();\n        bytes_read++;\n        if(c == 0x00){ // segwit!\n            segwit_flag = 1;\n        }else{\n            inputsNumber = c; // FIXME: should be varint, but 255 inputs will kill the MCU...\n            txIns = new TxIn[inputsNumber];\n            for(unsigned int i=0; i<inputsNumber; i++){ // this will at least set all txins to PARSING_INCOMPLETE\n                bytes_read += s->parse(&txIns[i]);\n            }\n        }\n    }\n    if(s->available() && segwit_flag > 0 && bytes_read+bytes_parsed == 5){\n        uint8_t c = s->read();\n        bytes_read++;\n        if(c != 0x01){ // unsupported segwit version\n            status = PARSING_FAILED;\n            bytes_parsed+=bytes_read;\n            return bytes_read;\n        }\n    }\n    if(s->available() && segwit_flag > 0 && bytes_read+bytes_parsed == 6){\n        inputsNumber = s->read();\n        bytes_read++;\n        txIns = new TxIn[inputsNumber];\n        for(unsigned int i=0; i<inputsNumber; i++){ // this will at least set all txins to PARSING_INCOMPLETE\n            bytes_read += s->parse(&txIns[i]);\n        }\n    }\n    for(unsigned int i=0; i<inputsNumber; i++){\n        if(s->available() && txIns[i].getStatus() == PARSING_INCOMPLETE){\n            bytes_read += s->parse(&txIns[i]);\n        }\n        if(txIns[i].getStatus() == PARSING_FAILED){\n            status = PARSING_FAILED;\n            bytes_parsed+=bytes_read;\n            return bytes_read;\n        }\n    }\n    size_t current_offset = 5+2*segwit_flag;\n    for(unsigned int i=0; i<inputsNumber; i++){\n        current_offset += txIns[i].length();\n    }\n    if(s->available() && bytes_read+bytes_parsed == current_offset){\n        outputsNumber = s->read();\n        bytes_read++;\n        txOuts = new TxOut[outputsNumber];\n        for(unsigned int i=0; i<outputsNumber; i++){ // this will at least set all txouts to PARSING_INCOMPLETE\n            bytes_read += s->parse(&txOuts[i]);\n        }\n    }\n    for(unsigned int i=0; i<outputsNumber; i++){\n        if(s->available() && txOuts[i].getStatus() == PARSING_INCOMPLETE){\n            bytes_read += s->parse(&txOuts[i]);\n        }\n        if(txOuts[i].getStatus() == PARSING_FAILED){\n            status = PARSING_FAILED;\n            bytes_parsed+=bytes_read;\n            return bytes_read;\n        }\n    }\n    current_offset++;\n    for(unsigned int i=0; i<outputsNumber; i++){\n        current_offset += txOuts[i].length();\n    }\n    if(segwit_flag > 0 && bytes_read+bytes_parsed == current_offset){\n        for(unsigned int i=0; i<inputsNumber; i++){ // this will at least set all txins witnesses to PARSING_INCOMPLETE\n            bytes_read += s->parse(&txIns[i].witness);\n        }\n    }\n    if(segwit_flag > 0){\n        for(unsigned int i=0; i<inputsNumber; i++){\n            if(s->available() && txIns[i].witness.getStatus() == PARSING_INCOMPLETE){\n                bytes_read += s->parse(&txIns[i].witness);\n            }\n            if(txIns[i].witness.getStatus() == PARSING_FAILED){\n                status = PARSING_FAILED;\n                ubtc_errno = UBTC_ERR_TX_GLOBAL | UBTC_ERR_TX_SCRIPT;\n                bytes_parsed+=bytes_read;\n                return bytes_read;\n            }\n        }\n        for(unsigned int i=0; i<inputsNumber; i++){\n            current_offset += txIns[i].witness.length();\n        }\n    }\n    while(s->available() && bytes_parsed+bytes_read < current_offset+4){\n        uint8_t c = s->read();\n        locktime += (c << (8*(bytes_read+bytes_parsed-current_offset)));\n        bytes_read++;\n    }\n    current_offset+= 4;\n    if(bytes_read+bytes_parsed == current_offset){\n        bool completed = true;\n        for(unsigned int i=0; i<inputsNumber; i++){\n            if(txIns[i].getStatus() != PARSING_DONE){\n                completed = false;\n            }\n            if(segwit_flag > 0){\n                if(txIns[i].witness.getStatus() != PARSING_DONE){\n                    completed = false;\n                }\n            }\n        }\n        for(unsigned int i=0; i<outputsNumber; i++){\n            if(txOuts[i].getStatus() != PARSING_DONE){\n                completed = false;\n            }\n        }\n        if(completed){\n            status = PARSING_DONE;\n        }\n    }\n    bytes_parsed+=bytes_read;\n    return bytes_read;\n}\nint Tx::sigHash(uint8_t h[32], uint8_t inputIndex, const Script scriptPubkey, SigHashType sighash) const{\n    Script empty;\n    DoubleSha s;\n    s.begin();\n\n    uint8_t arr[10];\n\n    intToLittleEndian(version, arr, 4);\n    s.write(arr, 4);\n    size_t l = writeVarInt(inputsNumber, arr, 10);\n    s.write(arr, l);\n    for(size_t i=0; i<inputsNumber; i++){\n        TxIn t = txIns[i];\n        if(i == inputIndex){\n            t.scriptSig = scriptPubkey;\n        }else{\n            t.scriptSig = empty;\n        }\n        s.serialize(&t, 0);\n    }\n    l = writeVarInt(outputsNumber, arr, 10);\n    s.write(arr, l);\n    for(size_t i=0; i<outputsNumber; i++){\n        s.serialize(&txOuts[i], 0);\n    }\n    intToLittleEndian(locktime, arr, 4);\n    s.write(arr, 4);\n    intToLittleEndian(sighash, arr, 4);\n    s.write(arr, 4);\n    s.end(h);\n    return 32;\n}\nint Tx::hash(uint8_t * h) const{\n    DoubleSha s;\n    s.begin();\n\n    uint8_t arr[10];\n\n    intToLittleEndian(version, arr, 4);\n    s.write(arr, 4);\n    size_t l = writeVarInt(inputsNumber, arr, 10);\n    s.write(arr, l);\n    for(unsigned int i=0; i<inputsNumber; i++){\n        s.serialize(&txIns[i], 0);\n    }\n    l = writeVarInt(outputsNumber, arr, 10);\n    s.write(arr, l);\n    for(unsigned int i=0; i<outputsNumber; i++){\n        s.serialize(&txOuts[i], 0);\n    }\n    intToLittleEndian(locktime, arr, 4);\n    s.write(arr, 4);\n    s.end(h);\n    return 32;\n}\nint Tx::whash(uint8_t * h) const{\n    DoubleSha s;\n    s.begin();\n\n    uint8_t arr[10];\n\n    intToLittleEndian(version, arr, 4);\n    s.write(arr, 4);\n    arr[0] = 0; // marker\n    arr[1] = 1; // flag\n    s.write(arr, 2);\n    size_t l = writeVarInt(inputsNumber, arr, 10);\n    s.write(arr, l);\n    for(unsigned int i=0; i<inputsNumber; i++){\n        s.serialize(&txIns[i], 0);\n    }\n    l = writeVarInt(outputsNumber, arr, 10);\n    s.write(arr, l);\n    for(unsigned int i=0; i<outputsNumber; i++){\n        s.serialize(&txOuts[i], 0);\n    }\n    for(unsigned int i=0; i<inputsNumber; i++){\n        s.serialize(&txIns[i].witness, 0);\n    }\n    intToLittleEndian(locktime, arr, 4);\n    s.write(arr, 4);\n    s.end(h);\n    return 32;\n}\nint Tx::txid(uint8_t * id_arr) const{\n    uint8_t h[32];\n    hash(h);\n    for(uint8_t i=0;i<32;i++){\n        id_arr[i] = h[31-i];\n    }\n    return 32;\n}\nint Tx::wtxid(uint8_t * id_arr) const{\n    uint8_t h[32];\n    whash(h);\n    for(uint8_t i=0;i<32;i++){\n        id_arr[i] = h[31-i];\n    }\n    return 32;\n}\n\n#if USE_ARDUINO_STRING || USE_STD_STRING\nString Tx::txid() const{\n    uint8_t id[32];\n    txid(id);\n    return toHex(id, 32);\n}\nString Tx::wtxid() const{\n    uint8_t id[32];\n    wtxid(id);\n    return toHex(id, 32);\n}\n#endif\n\nuint8_t Tx::addInput(const TxIn txIn){\n    TxIn * arr = new TxIn[inputsNumber+1];\n    for(unsigned int i=0; i<inputsNumber; i++){\n        arr[i] = txIns[i];\n    }\n    arr[inputsNumber] = txIn;\n    if(inputsNumber > 0){\n        delete [] txIns;\n    }\n    txIns = arr;\n    inputsNumber++;\n    return inputsNumber;\n}\nuint8_t Tx::addOutput(const TxOut txOut){\n    TxOut * arr = new TxOut[outputsNumber+1];\n    for(unsigned int i=0; i<outputsNumber; i++){\n        arr[i] = txOuts[i];\n    }\n    arr[outputsNumber] = txOut;\n    if(outputsNumber > 0){\n        delete [] txOuts;\n    }\n    txOuts = arr;\n    outputsNumber++;\n    return outputsNumber;\n}\n\nint Tx::hashPrevouts(uint8_t h[32]) const{\n    DoubleSha s;\n    s.begin();\n    for(size_t i=0; i<inputsNumber; i++){\n        s.write(txIns[i].hash, 32);\n        uint8_t arr[4];\n        intToLittleEndian(txIns[i].outputIndex, arr, 4);\n        s.write(arr, 4);\n    }\n    s.end(h);\n    return 32;\n}\n\nint Tx::hashSequence(uint8_t h[32]) const{\n    DoubleSha s;\n    s.begin();\n    for(size_t i=0; i<inputsNumber; i++){\n        uint8_t arr[4];\n        intToLittleEndian(txIns[i].sequence, arr, 4);\n        s.write(arr, 4);\n    }\n    s.end(h);\n    return 32;\n}\n\nint Tx::hashOutputs(uint8_t h[32]) const{\n    DoubleSha s;\n    s.begin();\n    for(size_t i=0; i<outputsNumber; i++){\n        s.serialize(&txOuts[i], 0);\n    }\n    s.end(h);\n    return 32;\n}\n\nint Tx::sigHashSegwit(uint8_t h[32], uint8_t inputIndex, const Script scriptPubKey, uint64_t amount, SigHashType sighash) const{\n    DoubleSha s;\n    s.begin();\n    uint8_t arr[8];\n    intToLittleEndian(version, arr, 4);\n    s.write(arr, 4);\n\n    hashPrevouts(h);\n    s.write(h, 32);\n\n    hashSequence(h);\n    s.write(h, 32);\n\n    s.write(txIns[inputIndex].hash, 32);\n    intToLittleEndian(txIns[inputIndex].outputIndex, arr, 4);\n    s.write(arr, 4);\n    s.serialize(&scriptPubKey, 0);\n\n    intToLittleEndian(amount, arr, 8);\n    s.write(arr, 8);\n    intToLittleEndian(txIns[inputIndex].sequence, arr, 4);\n    s.write(arr, 4);\n\n    hashOutputs(h);\n    s.write(h, 32);\n\n    intToLittleEndian(locktime, arr, 4);\n    s.write(arr, 4);\n    intToLittleEndian(sighash, arr, 4);\n    s.write(arr, 4);\n\n    s.end(h);\n    return 32;\n}\n\nSignature Tx::signInput(uint8_t inputIndex, const PrivateKey pk, const Script redeemScript, SigHashType sighash){\n    uint8_t h[32];\n    sigHash(h, inputIndex, redeemScript, sighash);\n\n    PublicKey pubkey = pk.publicKey();\n    Signature sig = pk.sign(h);\n\n    Script sc;\n    sc.push(sig);\n    sc.push(pubkey);\n    // push script itself for timelocks and other single-key things if P2SH\n    if(redeemScript.type() != P2PKH){\n        sc.push(redeemScript);\n    }\n\n    txIns[inputIndex].scriptSig = sc;\n\n    return sig;\n}\nSignature Tx::signSegwitInput(uint8_t inputIndex, const PrivateKey pk, const Script redeemScript, uint64_t amount, ScriptType type, SigHashType sighash){\n    uint8_t h[32];\n\n    ScriptType redeem_type = redeemScript.type();\n    if(redeem_type == P2WPKH){\n        Script sc(pk.publicKey(), P2PKH);\n        sigHashSegwit(h, inputIndex, sc, amount, sighash);\n    }else{\n        sigHashSegwit(h, inputIndex, redeemScript, amount, sighash);\n    }\n\n    PublicKey pubkey = pk.publicKey();\n    Signature sig = pk.sign(h);\n\n    if((type == P2SH_P2WPKH) || (type == P2SH_P2WSH)){\n        Script script_sig;\n        if(redeem_type == P2WPKH){\n            script_sig.push(redeemScript);\n        }else{\n            Script sc(redeemScript, P2WSH);\n            script_sig.push(sc);\n        }\n        txIns[inputIndex].scriptSig = script_sig;\n    }else{\n        Script empty;\n        txIns[inputIndex].scriptSig = empty;\n    }\n\n    Witness w;\n    w.push(sig);\n    w.push(pubkey);\n    if(redeem_type != P2WPKH){\n        w.push(redeemScript);\n    }\n    txIns[inputIndex].witness = w;\n\n    return sig;\n}\n"
  },
  {
    "path": "src/uBitcoin_conf.h",
    "content": "#ifndef __UBITCOIN_CONF_H__\n#define __UBITCOIN_CONF_H__\n\n/* Change this if you want to have other network by default */\n#define DEFAULT_NETWORK Mainnet\n\n/* Change this config file to adjust to your framework */\n#ifndef USE_STDONLY\n  #ifdef ARDUINO\n  #include <Arduino.h>\n  #else\n  #define MBED\n  #include <mbed.h>\n  #endif\n#endif\n\n/* If you don't have a Stream class in your framework you can implement one\n * by yourself and use it to parse transactions and hash on the fly.\n * Arduino and Mbed are using slightly different API, choose one.\n * TODO: describe the interface.\n */\n\n/* settings for Arduino */\n#ifdef ARDUINO\n#define USE_ARDUINO_STRING 1 /* Arduino String implementation (WString.h) */\n#define USE_ARDUINO_STREAM 1 /* Arduino Stream class */\n#define USE_STD_STRING     0 /* Standard library std::string */\n#define USE_MBED_STREAM    0 /* Mbed Stream class */\n#endif\n\n#ifdef MBED\n#define USE_ARDUINO_STRING 0 /* Arduino String implementation (WString.h) */\n#define USE_ARDUINO_STREAM 0 /* Arduino Stream class */\n#define USE_STD_STRING     1 /* Standard library std::string */\n#define USE_MBED_STREAM    1 /* Mbed Stream class */\n#endif\n\n#ifdef USE_STDONLY\n #ifndef USE_ARDUINO_STRING\n  #define USE_ARDUINO_STRING 0 /* Arduino String implementation (WString.h) */\n #endif\n #ifndef USE_ARDUINO_STREAM\n  #define USE_ARDUINO_STREAM 0 /* Arduino Stream class */\n #endif\n #ifndef USE_STD_STRING\n  #define USE_STD_STRING     1 /* Standard library std::string */\n #endif\n #ifndef USE_MBED_STREAM\n  #define USE_MBED_STREAM    0 /* Mbed Stream class */\n #endif\n#endif\n\n#if USE_STD_STRING\n#include <string>\n// using std::string;\n#endif\n\n#endif //__UBITCOIN_CONF_H__\n"
  },
  {
    "path": "src/utility/segwit_addr.c",
    "content": "/* Copyright (c) 2017 Pieter Wuille\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"segwit_addr.h\"\n\nuint32_t bech32_polymod_step(uint32_t pre) {\n    uint8_t b = pre >> 25;\n    return ((pre & 0x1FFFFFF) << 5) ^\n        (-((b >> 0) & 1) & 0x3b6a57b2UL) ^\n        (-((b >> 1) & 1) & 0x26508e6dUL) ^\n        (-((b >> 2) & 1) & 0x1ea119faUL) ^\n        (-((b >> 3) & 1) & 0x3d4233ddUL) ^\n        (-((b >> 4) & 1) & 0x2a1462b3UL);\n}\n\nstatic const char* charset = \"qpzry9x8gf2tvdw0s3jn54khce6mua7l\";\n\nstatic const int8_t charset_rev[128] = {\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n    15, -1, 10, 17, 21, 20, 26, 30,  7,  5, -1, -1, -1, -1, -1, -1,\n    -1, 29, -1, 24, 13, 25,  9,  8, 23, -1, 18, 22, 31, 27, 19, -1,\n     1,  0,  3, 16, 11, 28, 12, 14,  6,  4,  2, -1, -1, -1, -1, -1,\n    -1, 29, -1, 24, 13, 25,  9,  8, 23, -1, 18, 22, 31, 27, 19, -1,\n     1,  0,  3, 16, 11, 28, 12, 14,  6,  4,  2, -1, -1, -1, -1, -1\n};\n\nint bech32_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len) {\n    uint32_t chk = 1;\n    size_t i = 0;\n    while (hrp[i] != 0) {\n        int ch = hrp[i];\n        if (ch < 33 || ch > 126) {\n            return 0;\n        }\n\n        if (ch >= 'A' && ch <= 'Z') return 0;\n        chk = bech32_polymod_step(chk) ^ (ch >> 5);\n        ++i;\n    }\n    if (i + 7 + data_len > MAX_BECH32_SIZE) return 0;\n    chk = bech32_polymod_step(chk);\n    while (*hrp != 0) {\n        chk = bech32_polymod_step(chk) ^ (*hrp & 0x1f);\n        *(output++) = *(hrp++);\n    }\n    *(output++) = '1';\n    for (i = 0; i < data_len; ++i) {\n        if (*data >> 5) return 0;\n        chk = bech32_polymod_step(chk) ^ (*data);\n        *(output++) = charset[*(data++)];\n    }\n    for (i = 0; i < 6; ++i) {\n        chk = bech32_polymod_step(chk);\n    }\n    chk ^= 1;\n    for (i = 0; i < 6; ++i) {\n        *(output++) = charset[(chk >> ((5 - i) * 5)) & 0x1f];\n    }\n    *output = 0;\n    return 1;\n}\n\nint bech32_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input) {\n    uint32_t chk = 1;\n    size_t i;\n    size_t input_len = strlen(input);\n    size_t hrp_len;\n    int have_lower = 0, have_upper = 0;\n    if (input_len < 8 || input_len > MAX_BECH32_SIZE) {\n        return 0;\n    }\n    *data_len = 0;\n    while (*data_len < input_len && input[(input_len - 1) - *data_len] != '1') {\n        ++(*data_len);\n    }\n    hrp_len = input_len - (1 + *data_len);\n    if (hrp_len < 1 || *data_len < 6) {\n        return 0;\n    }\n    *(data_len) -= 6;\n    for (i = 0; i < hrp_len; ++i) {\n        int ch = input[i];\n        if (ch < 33 || ch > 126) {\n            return 0;\n        }\n        if (ch >= 'a' && ch <= 'z') {\n            have_lower = 1;\n        } else if (ch >= 'A' && ch <= 'Z') {\n            have_upper = 1;\n            ch = (ch - 'A') + 'a';\n        }\n        hrp[i] = ch;\n        chk = bech32_polymod_step(chk) ^ (ch >> 5);\n    }\n    hrp[i] = 0;\n    chk = bech32_polymod_step(chk);\n    for (i = 0; i < hrp_len; ++i) {\n        chk = bech32_polymod_step(chk) ^ (input[i] & 0x1f);\n    }\n    ++i;\n    while (i < input_len) {\n        int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]];\n        if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1;\n        if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1;\n        if (v == -1) {\n            return 0;\n        }\n        chk = bech32_polymod_step(chk) ^ v;\n        if (i + 6 < input_len) {\n            data[i - (1 + hrp_len)] = v;\n        }\n        ++i;\n    }\n    if (have_lower && have_upper) {\n        return 0;\n    }\n    return chk == 1;\n}\n\nint convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad) {\n    uint32_t val = 0;\n    int bits = 0;\n    uint32_t maxv = (((uint32_t)1) << outbits) - 1;\n    while (inlen--) {\n        val = (val << inbits) | *(in++);\n        bits += inbits;\n        while (bits >= outbits) {\n            bits -= outbits;\n            out[(*outlen)++] = (val >> bits) & maxv;\n        }\n    }\n    if (pad) {\n        if (bits) {\n            out[(*outlen)++] = (val << (outbits - bits)) & maxv;\n        }\n    } else if (((val << (outbits - bits)) & maxv) || bits >= inbits) {\n        return 0;\n    }\n    return 1;\n}\n\nint segwit_addr_encode(char *output, const char *hrp, int witver, const uint8_t *witprog, size_t witprog_len) {\n    uint8_t data[65];\n    size_t datalen = 0;\n    if (witver > 16) return 0;\n    if (witver == 0 && witprog_len != 20 && witprog_len != 32) return 0;\n    if (witprog_len < 2 || witprog_len > 40) return 0;\n    data[0] = witver;\n    convert_bits(data + 1, &datalen, 5, witprog, witprog_len, 8, 1);\n    ++datalen;\n    return bech32_encode(output, hrp, data, datalen);\n}\n\nint segwit_addr_decode(int* witver, uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) {\n    uint8_t data[84];\n    char hrp_actual[84];\n    size_t data_len;\n    if (!bech32_decode(hrp_actual, data, &data_len, addr)) return 0;\n    if (data_len == 0 || data_len > 65) return 0;\n    if (strncmp(hrp, hrp_actual, 84) != 0) return 0;\n    if (data[0] > 16) return 0;\n    *witdata_len = 0;\n    if (!convert_bits(witdata, witdata_len, 8, data + 1, data_len - 1, 5, 0)) return 0;\n    if (*witdata_len < 2 || *witdata_len > 40) return 0;\n    if (data[0] == 0 && *witdata_len != 20 && *witdata_len != 32) return 0;\n    *witver = data[0];\n    return 1;\n}"
  },
  {
    "path": "src/utility/segwit_addr.h",
    "content": "/* Copyright (c) 2017 Pieter Wuille\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\n#ifndef _SEGWIT_ADDR_H_\n#define _SEGWIT_ADDR_H_ 1\n\n#include <stdint.h>\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n#define MAX_BECH32_SIZE 1000 // for lightning\n\n/** Encode a SegWit address\n *\n *  Out: output:   Pointer to a buffer of size 73 + strlen(hrp) that will be\n *                 updated to contain the null-terminated address.\n *  In:  hrp:      Pointer to the null-terminated human readable part to use\n *                 (chain/network specific).\n *       ver:      Version of the witness program (between 0 and 16 inclusive).\n *       prog:     Data bytes for the witness program (between 2 and 40 bytes).\n *       prog_len: Number of data bytes in prog.\n *  Returns 1 if successful.\n */\nint segwit_addr_encode(\n    char *output,\n    const char *hrp,\n    int ver,\n    const uint8_t *prog,\n    size_t prog_len\n);\n\n/** Decode a SegWit address\n *\n *  Out: ver:      Pointer to an int that will be updated to contain the witness\n *                 program version (between 0 and 16 inclusive).\n *       prog:     Pointer to a buffer of size 40 that will be updated to\n *                 contain the witness program bytes.\n *       prog_len: Pointer to a size_t that will be updated to contain the length\n *                 of bytes in prog.\n *       hrp:      Pointer to the null-terminated human readable part that is\n *                 expected (chain/network specific).\n *       addr:     Pointer to the null-terminated address.\n *  Returns 1 if successful.\n */\nint segwit_addr_decode(\n    int* ver,\n    uint8_t* prog,\n    size_t* prog_len,\n    const char* hrp,\n    const char* addr\n);\n\n/** Encode a Bech32 string\n *\n *  Out: output:  Pointer to a buffer of size strlen(hrp) + data_len + 8 that\n *                will be updated to contain the null-terminated Bech32 string.\n *  In: hrp :     Pointer to the null-terminated human readable part.\n *      data :    Pointer to an array of 5-bit values.\n *      data_len: Length of the data array.\n *  Returns 1 if successful.\n */\nint bech32_encode(\n    char *output,\n    const char *hrp,\n    const uint8_t *data,\n    size_t data_len\n);\n\n/** Decode a Bech32 string\n *\n *  Out: hrp:      Pointer to a buffer of size strlen(input) - 6. Will be\n *                 updated to contain the null-terminated human readable part.\n *       data:     Pointer to a buffer of size strlen(input) - 8 that will\n *                 hold the encoded 5-bit data values.\n *       data_len: Pointer to a size_t that will be updated to be the number\n *                 of entries in data.\n *  In: input:     Pointer to a null-terminated Bech32 string.\n *  Returns 1 if succesful.\n */\nint bech32_decode(\n    char *hrp,\n    uint8_t *data,\n    size_t *data_len,\n    const char *input\n);\n\nint convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad);\n\n#ifdef __cplusplus\n} /* end of extern \"C\" */\n#endif\n\n#endif"
  },
  {
    "path": "src/utility/trezor/address.c",
    "content": "/**\n * Copyright (c) 2016 Daira Hopwood\n * Copyright (c) 2016 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include \"address.h\"\n#include \"bignum.h\"\n\nsize_t address_prefix_bytes_len(uint32_t address_type)\n{\n\tif (address_type <= 0xFF)     return 1;\n\tif (address_type <= 0xFFFF)   return 2;\n\tif (address_type <= 0xFFFFFF) return 3;\n\treturn 4;\n}\n\nvoid address_write_prefix_bytes(uint32_t address_type, uint8_t *out)\n{\n\tif (address_type > 0xFFFFFF) *(out++) =  address_type >> 24;\n\tif (address_type > 0xFFFF)   *(out++) = (address_type >> 16) & 0xFF;\n\tif (address_type > 0xFF)     *(out++) = (address_type >>  8) & 0xFF;\n\t*(out++) = address_type & 0xFF;\n}\n\nbool address_check_prefix(const uint8_t *addr, uint32_t address_type)\n{\n\tif (address_type <= 0xFF) {\n\t\treturn address_type == (uint32_t)(addr[0]);\n\t}\n\tif (address_type <= 0xFFFF) {\n\t\treturn address_type == (((uint32_t) addr[0] << 8) | ((uint32_t) addr[1]));\n\t}\n\tif (address_type <= 0xFFFFFF) {\n\t\treturn address_type == (((uint32_t) addr[0] << 16) | ((uint32_t) addr[1] << 8) | ((uint32_t) addr[2]));\n\t}\n\treturn address_type == (((uint32_t) addr[0] << 24) | ((uint32_t) addr[1] << 16) | ((uint32_t) addr[2] << 8) | ((uint32_t) addr[3]));\n}\n\n#if USE_ETHEREUM\n#include \"sha3.h\"\n\nvoid ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id)\n{\n\tconst char *hex = \"0123456789abcdef\";\n\tfor (int i = 0; i < 20; i++) {\n\t\taddress[i * 2]     = hex[(addr[i] >> 4) & 0xF];\n\t\taddress[i * 2 + 1] = hex[addr[i] & 0xF];\n\t}\n\taddress[40] = 0;\n\n\tSHA3_CTX ctx;\n\tuint8_t hash[32];\n\tkeccak_256_Init(&ctx);\n\tif (rskip60) {\n\t\tchar prefix[16];\n\t\tint prefix_size = bn_format_uint64(chain_id, NULL, \"0x\", 0, 0, false, prefix, sizeof(prefix));\n\t\tkeccak_Update(&ctx, (const uint8_t *)prefix, prefix_size);\n\t}\n\tkeccak_Update(&ctx, (const uint8_t *)address, 40);\n\tkeccak_Final(&ctx, hash);\n\n\tfor (int i = 0; i < 20; i++) {\n\t\tif (hash[i] & 0x80 && address[i * 2    ] >= 'a' && address[i * 2    ] <= 'f') {\n\t\t\taddress[i * 2] -= 0x20;\n\t\t}\n\t\tif (hash[i] & 0x08 && address[i * 2 + 1] >= 'a' && address[i * 2 + 1] <= 'f') {\n\t\t\taddress[i * 2 + 1] -= 0x20;\n\t\t}\n\t}\n}\n#endif\n"
  },
  {
    "path": "src/utility/trezor/address.h",
    "content": "/**\n * Copyright (c) 2016 Daira Hopwood\n * Copyright (c) 2016 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __ADDRESS_H__\n#define __ADDRESS_H__\n\n#include <stdint.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include \"options.h\"\n\nsize_t address_prefix_bytes_len(uint32_t address_type);\nvoid address_write_prefix_bytes(uint32_t address_type, uint8_t *out);\nbool address_check_prefix(const uint8_t *addr, uint32_t address_type);\n#if USE_ETHEREUM\nvoid ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id);\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/base58.c",
    "content": "/**\n * Copyright (c) 2012-2014 Luke Dashjr\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <string.h>\n#include <stdbool.h>\n//#include <sys/types.h>\n#include <stdint.h>\n#include \"base58.h\"\n#include \"sha2.h\"\n#include \"ripemd160.h\"\n#include \"memzero.h\"\n\n#define ssize_t int32_t\n\nconst char b58digits_ordered[] = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\";\nconst int8_t b58digits_map[] = {\n\t-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\n\t-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\n\t-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\n\t-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,\n\t-1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1,\n\t22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,\n\t-1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46,\n\t47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1,\n};\n\nbool b58tobin(void *bin, size_t *binszp, const char *b58)\n{\n\tsize_t binsz = *binszp;\n\n\tif (binsz == 0) {\n\t\treturn false;\n\t}\n\n\tconst unsigned char *b58u = (const unsigned char*)b58;\n\tunsigned char *binu = (unsigned char *)bin;\n\tsize_t outisz = (binsz + 3) / 4;\n\tuint32_t outi[outisz];\n\tuint64_t t;\n\tuint32_t c;\n\tsize_t i, j;\n\tuint8_t bytesleft = binsz % 4;\n\tuint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;\n\tunsigned zerocount = 0;\n\tsize_t b58sz;\n\n\tb58sz = strlen(b58);\n\n\tmemset(outi, 0, outisz * sizeof(*outi));\n\n\t// Leading zeros, just count\n\tfor (i = 0; i < b58sz && b58u[i] == '1'; ++i)\n\t\t++zerocount;\n\n\tfor ( ; i < b58sz; ++i)\n\t{\n\t\tif (b58u[i] & 0x80)\n\t\t\t// High-bit set on invalid digit\n\t\t\treturn false;\n\t\tif (b58digits_map[b58u[i]] == -1)\n\t\t\t// Invalid base58 digit\n\t\t\treturn false;\n\t\tc = (unsigned)b58digits_map[b58u[i]];\n\t\tfor (j = outisz; j--; )\n\t\t{\n\t\t\tt = ((uint64_t)outi[j]) * 58 + c;\n\t\t\tc = (t & 0x3f00000000) >> 32;\n\t\t\touti[j] = t & 0xffffffff;\n\t\t}\n\t\tif (c)\n\t\t\t// Output number too big (carry to the next int32)\n\t\t\treturn false;\n\t\tif (outi[0] & zeromask)\n\t\t\t// Output number too big (last int32 filled too far)\n\t\t\treturn false;\n\t}\n\n\tj = 0;\n\tswitch (bytesleft) {\n\t\tcase 3:\n\t\t\t*(binu++) = (outi[0] &   0xff0000) >> 16;\n\t\t\t//-fallthrough\n\t\tcase 2:\n\t\t\t*(binu++) = (outi[0] &     0xff00) >>  8;\n\t\t\t//-fallthrough\n\t\tcase 1:\n\t\t\t*(binu++) = (outi[0] &       0xff);\n\t\t\t++j;\n\t\t\t//-fallthrough\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\tfor (; j < outisz; ++j)\n\t{\n\t\t*(binu++) = (outi[j] >> 0x18) & 0xff;\n\t\t*(binu++) = (outi[j] >> 0x10) & 0xff;\n\t\t*(binu++) = (outi[j] >>    8) & 0xff;\n\t\t*(binu++) = (outi[j] >>    0) & 0xff;\n\t}\n\n\t// Count canonical base58 byte count\n\tbinu = (unsigned char *)bin;\n\tfor (i = 0; i < binsz; ++i)\n\t{\n\t\tif (binu[i]) {\n\t\t\tif (zerocount > i) {\n\t\t\t\t/* result too large */\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\t--*binszp;\n\t}\n\t*binszp += zerocount;\n\n\treturn true;\n}\n\nint b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str)\n{\n\tunsigned char buf[32];\n\tconst uint8_t *binc = (const uint8_t *)bin;\n\tunsigned i;\n\tif (binsz < 4)\n\t\treturn -4;\n\thasher_Raw(hasher_type, (const uint8_t *)bin, binsz - 4, buf);\n\tif (memcmp(&binc[binsz - 4], buf, 4))\n\t\treturn -1;\n\n\t// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)\n\tfor (i = 0; binc[i] == '\\0' && base58str[i] == '1'; ++i)\n\t{}  // Just finding the end of zeros, nothing to do in loop\n\tif (binc[i] == '\\0' || base58str[i] == '1')\n\t\treturn -3;\n\n\treturn binc[0];\n}\n\nbool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)\n{\n\tconst uint8_t *bin = (const uint8_t *)data;\n\tint carry;\n\tssize_t i, j, high, zcount = 0;\n\tsize_t size;\n\n\twhile (zcount < (ssize_t)binsz && !bin[zcount])\n\t\t++zcount;\n\n\tsize = (binsz - zcount) * 138 / 100 + 1;\n\tuint8_t buf[size];\n\tmemset(buf, 0, size);\n\n\tfor (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j)\n\t{\n\t\tfor (carry = bin[i], j = size - 1; (j > high) || carry; --j)\n\t\t{\n\t\t\tcarry += 256 * buf[j];\n\t\t\tbuf[j] = carry % 58;\n\t\t\tcarry /= 58;\n\t\t}\n\t}\n\n\tfor (j = 0; j < (ssize_t)size && !buf[j]; ++j);\n\n\tif (*b58sz <= zcount + size - j)\n\t{\n\t\t*b58sz = zcount + size - j + 1;\n\t\treturn false;\n\t}\n\n\tif (zcount)\n\t\tmemset(b58, '1', zcount);\n\tfor (i = zcount; j < (ssize_t)size; ++i, ++j)\n\t\tb58[i] = b58digits_ordered[buf[j]];\n\tb58[i] = '\\0';\n\t*b58sz = i + 1;\n\n\treturn true;\n}\n\nint base58_encode_check(const uint8_t *data, int datalen, HasherType hasher_type, char *str, int strsize)\n{\n\tif (datalen > 128) {\n\t\treturn 0;\n\t}\n\tuint8_t buf[datalen + 32];\n\tuint8_t *hash = buf + datalen;\n\tmemcpy(buf, data, datalen);\n\thasher_Raw(hasher_type, data, datalen, hash);\n\tsize_t res = strsize;\n\tbool success = b58enc(str, &res, buf, datalen + 4);\n\tmemzero(buf, sizeof(buf));\n\treturn success ? res : 0;\n}\n\nint base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen)\n{\n\tif (datalen > 128) {\n\t\treturn 0;\n\t}\n\tuint8_t d[datalen + 4];\n\tsize_t res = datalen + 4;\n\tif (b58tobin(d, &res, str) != true) {\n\t\treturn 0;\n\t}\n\tuint8_t *nd = d + datalen + 4 - res;\n\tif (b58check(nd, res, hasher_type, str) < 0) {\n\t\treturn 0;\n\t}\n\tmemcpy(data, nd, res - 4);\n\treturn res - 4;\n}\n\n#if USE_GRAPHENE\nint b58gphcheck(const void *bin, size_t binsz, const char *base58str)\n{\n\tunsigned char buf[32];\n\tconst uint8_t *binc = bin;\n\tunsigned i;\n\tif (binsz < 4)\n\t\treturn -4;\n\tripemd160(bin, binsz - 4, buf);  // No double SHA256, but a single RIPEMD160\n\tif (memcmp(&binc[binsz - 4], buf, 4))\n\t\treturn -1;\n\n\t// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)\n\tfor (i = 0; binc[i] == '\\0' && base58str[i] == '1'; ++i)\n\t{}  // Just finding the end of zeros, nothing to do in loop\n\tif (binc[i] == '\\0' || base58str[i] == '1')\n\t\treturn -3;\n\n\treturn binc[0];\n}\n\nint base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize)\n{\n\tif (datalen > 128) {\n\t\treturn 0;\n\t}\n\tuint8_t buf[datalen + 32];\n\tuint8_t *hash = buf + datalen;\n\tmemcpy(buf, data, datalen);\n\tripemd160(data, datalen, hash);  // No double SHA256, but a single RIPEMD160\n\tsize_t res = strsize;\n\tbool success = b58enc(str, &res, buf, datalen + 4);\n\tmemzero(buf, sizeof(buf));\n\treturn success ? res : 0;\n}\n\nint base58gph_decode_check(const char *str, uint8_t *data, int datalen)\n{\n\tif (datalen > 128) {\n\t\treturn 0;\n\t}\n\tuint8_t d[datalen + 4];\n\tsize_t res = datalen + 4;\n\tif (b58tobin(d, &res, str) != true) {\n\t\treturn 0;\n\t}\n\tuint8_t *nd = d + datalen + 4 - res;\n\tif (b58gphcheck(nd, res, str) < 0) {\n\t\treturn 0;\n\t}\n\tmemcpy(data, nd, res - 4);\n\treturn res - 4;\n}\n#endif\n"
  },
  {
    "path": "src/utility/trezor/base58.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __BASE58_H__\n#define __BASE58_H__\n\n#include <stdint.h>\n#include <stdbool.h>\n#include \"hasher.h\"\n#include \"options.h\"\n\nextern const char b58digits_ordered[];\nextern const int8_t b58digits_map[];\n\nint base58_encode_check(const uint8_t *data, int len, HasherType hasher_type, char *str, int strsize);\nint base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen);\n\n// Private\nbool b58tobin(void *bin, size_t *binszp, const char *b58);\nint b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str);\nbool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz);\n\n#if USE_GRAPHENE\nint base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize);\nint base58gph_decode_check(const char *str, uint8_t *data, int datalen);\nint b58gphcheck(const void *bin, size_t binsz, const char *base58str);\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/bignum.c",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n * Copyright (c)      2015 Jochen Hoenicke\n * Copyright (c)      2016 Alex Beregszaszi\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n#include \"bignum.h\"\n#include \"memzero.h\"\n\n/* big number library */\n\n/* The structure bignum256 is an array of nine 32-bit values, which\n * are digits in base 2^30 representation.  I.e. the number\n *   bignum256 a;\n * represents the value\n *   sum_{i=0}^8 a.val[i] * 2^{30 i}.\n *\n * The number is *normalized* iff every digit is < 2^30.\n *\n * As the name suggests, a bignum256 is intended to represent a 256\n * bit number, but it can represent 270 bits.  Numbers are usually\n * reduced using a prime, either the group order or the field prime.\n * The reduction is often partly done by bn_fast_mod, and similarly\n * implicitly in bn_multiply.  A *partly reduced number* is a\n * normalized number between 0 (inclusive) and 2*prime (exclusive).\n *\n * A partly reduced number can be fully reduced by calling bn_mod.\n * Only a fully reduced number is guaranteed to fit in 256 bit.\n *\n * All functions assume that the prime in question is slightly smaller\n * than 2^256.  In particular it must be between 2^256-2^224 and\n * 2^256 and it must be a prime number.\n */\n\ninline uint32_t read_be(const uint8_t *data)\n{\n\treturn (((uint32_t)data[0]) << 24) |\n\t       (((uint32_t)data[1]) << 16) |\n\t       (((uint32_t)data[2]) << 8)  |\n\t       (((uint32_t)data[3]));\n}\n\ninline void write_be(uint8_t *data, uint32_t x)\n{\n\tdata[0] = x >> 24;\n\tdata[1] = x >> 16;\n\tdata[2] = x >> 8;\n\tdata[3] = x;\n}\n\ninline uint32_t read_le(const uint8_t *data)\n{\n\treturn (((uint32_t)data[3]) << 24) |\n\t       (((uint32_t)data[2]) << 16) |\n\t       (((uint32_t)data[1]) << 8)  |\n\t       (((uint32_t)data[0]));\n}\n\ninline void write_le(uint8_t *data, uint32_t x)\n{\n\tdata[3] = x >> 24;\n\tdata[2] = x >> 16;\n\tdata[1] = x >> 8;\n\tdata[0] = x;\n}\n\n// convert a raw bigendian 256 bit value into a normalized bignum.\n// out_number is partly reduced (since it fits in 256 bit).\nvoid bn_read_be(const uint8_t *in_number, bignum256 *out_number)\n{\n\tint i;\n\tuint32_t temp = 0;\n\tfor (i = 0; i < 8; i++) {\n\t\t// invariant: temp = (in_number % 2^(32i)) >> 30i\n\t\t// get next limb = (in_number % 2^(32(i+1))) >> 32i\n\t\tuint32_t limb = read_be(in_number + (7 - i) * 4);\n\t\t// temp = (in_number % 2^(32(i+1))) << 30i\n\t\ttemp |= limb << (2*i);\n\t\t// store 30 bits into val[i]\n\t\tout_number->val[i]= temp & 0x3FFFFFFF;\n\t\t// prepare temp for next round\n\t\ttemp = limb >> (30 - 2*i);\n\t}\n\tout_number->val[8] = temp;\n}\n\n// convert a normalized bignum to a raw bigendian 256 bit number.\n// in_number must be fully reduced.\nvoid bn_write_be(const bignum256 *in_number, uint8_t *out_number)\n{\n\tint i;\n\tuint32_t temp = in_number->val[8];\n\tfor (i = 0; i < 8; i++) {\n\t\t// invariant: temp = (in_number >> 30*(8-i))\n\t\tuint32_t limb = in_number->val[7 - i];\n\t\ttemp = (temp << (16 + 2*i)) | (limb >> (14 - 2*i));\n\t\twrite_be(out_number + i * 4, temp);\n\t\ttemp = limb;\n\t}\n}\n\n// convert a raw little endian 256 bit value into a normalized bignum.\n// out_number is partly reduced (since it fits in 256 bit).\nvoid bn_read_le(const uint8_t *in_number, bignum256 *out_number)\n{\n\tint i;\n\tuint32_t temp = 0;\n\tfor (i = 0; i < 8; i++) {\n\t\t// invariant: temp = (in_number % 2^(32i)) >> 30i\n\t\t// get next limb = (in_number % 2^(32(i+1))) >> 32i\n\t\tuint32_t limb = read_le(in_number + i * 4);\n\t\t// temp = (in_number % 2^(32(i+1))) << 30i\n\t\ttemp |= limb << (2*i);\n\t\t// store 30 bits into val[i]\n\t\tout_number->val[i]= temp & 0x3FFFFFFF;\n\t\t// prepare temp for next round\n\t\ttemp = limb >> (30 - 2*i);\n\t}\n\tout_number->val[8] = temp;\n}\n\n// convert a normalized bignum to a raw little endian 256 bit number.\n// in_number must be fully reduced.\nvoid bn_write_le(const bignum256 *in_number, uint8_t *out_number)\n{\n\tint i;\n\tuint32_t temp = in_number->val[8];\n\tfor (i = 0; i < 8; i++) {\n\t\t// invariant: temp = (in_number >> 30*(8-i))\n\t\tuint32_t limb = in_number->val[7 - i];\n\t\ttemp = (temp << (16 + 2*i)) | (limb >> (14 - 2*i));\n\t\twrite_le(out_number + (7 - i) * 4, temp);\n\t\ttemp = limb;\n\t}\n}\n\nvoid bn_read_uint32(uint32_t in_number, bignum256 *out_number)\n{\n\tout_number->val[0] = in_number & 0x3FFFFFFF;\n\tout_number->val[1] = in_number >> 30;\n\tout_number->val[2] = 0;\n\tout_number->val[3] = 0;\n\tout_number->val[4] = 0;\n\tout_number->val[5] = 0;\n\tout_number->val[6] = 0;\n\tout_number->val[7] = 0;\n\tout_number->val[8] = 0;\n}\n\nvoid bn_read_uint64(uint64_t in_number, bignum256 *out_number)\n{\n\tout_number->val[0] = in_number & 0x3FFFFFFF;\n\tout_number->val[1] = (in_number >>= 30) & 0x3FFFFFFF;\n\tout_number->val[2] = in_number >>= 30;\n\tout_number->val[3] = 0;\n\tout_number->val[4] = 0;\n\tout_number->val[5] = 0;\n\tout_number->val[6] = 0;\n\tout_number->val[7] = 0;\n\tout_number->val[8] = 0;\n}\n\n// a must be normalized\nint bn_bitcount(const bignum256 *a)\n{\n\tint i;\n\tfor (i = 8; i >= 0; i--) {\n\t\tint tmp = a->val[i];\n\t\tif (tmp != 0) {\n\t\t\treturn i * 30 + (32 - __builtin_clz(tmp));\n\t\t}\n\t}\n\treturn 0;\n}\n\n#define DIGITS 78 // log10(2 ^ 256)\n\nunsigned int bn_digitcount(const bignum256 *a)\n{\n\tbignum256 val;\n\tmemcpy(&val, a, sizeof(bignum256));\n\n\tunsigned int digits = 1;\n\n\tfor (unsigned int i = 0; i < DIGITS; i += 3) {\n\t\tuint32_t limb;\n\t\tbn_divmod1000(&val, &limb);\n\n\t\tif (limb >= 100) {\n\t\t\tdigits = i + 3;\n\t\t} else if (limb >= 10) {\n\t\t\tdigits = i + 2;\n\t\t} else if (limb >= 1) {\n\t\t\tdigits = i + 1;\n\t\t}\n\t}\n\n\treturn digits;\n}\n\n// sets a bignum to zero.\nvoid bn_zero(bignum256 *a)\n{\n\tint i;\n\tfor (i = 0; i < 9; i++) {\n\t\ta->val[i] = 0;\n\t}\n}\n\n// sets a bignum to one.\nvoid bn_one(bignum256 *a)\n{\n\ta->val[0] = 1;\n\ta->val[1] = 0;\n\ta->val[2] = 0;\n\ta->val[3] = 0;\n\ta->val[4] = 0;\n\ta->val[5] = 0;\n\ta->val[6] = 0;\n\ta->val[7] = 0;\n\ta->val[8] = 0;\n}\n\n// checks that a bignum is zero.\n// a must be normalized\n// function is constant time (on some architectures, in particular ARM).\nint bn_is_zero(const bignum256 *a)\n{\n\tint i;\n\tuint32_t result = 0;\n\tfor (i = 0; i < 9; i++) {\n\t\tresult |= a->val[i];\n\t}\n\treturn !result;\n}\n\n// Check whether a < b\n// a and b must be normalized\n// function is constant time (on some architectures, in particular ARM).\nint bn_is_less(const bignum256 *a, const bignum256 *b)\n{\n\tint i;\n\tuint32_t res1 = 0;\n\tuint32_t res2 = 0;\n\tfor (i = 8; i >= 0; i--) {\n\t\tres1 = (res1 << 1) | (a->val[i] < b->val[i]);\n\t\tres2 = (res2 << 1) | (a->val[i] > b->val[i]);\n\t}\n\treturn res1 > res2;\n}\n\n// Check whether a == b\n// a and b must be normalized\n// function is constant time (on some architectures, in particular ARM).\nint bn_is_equal(const bignum256 *a, const bignum256 *b) {\n\tint i;\n\tuint32_t result = 0;\n\tfor (i = 0; i < 9; i++) {\n\t\tresult |= (a->val[i] ^ b->val[i]);\n\t}\n\treturn !result;\n}\n\n// Assigns res = cond ? truecase : falsecase\n// assumes that cond is either 0 or 1.\n// function is constant time.\nvoid bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, const bignum256 *falsecase)\n{\n\tint i;\n\tuint32_t tmask = (uint32_t) -cond;\n\tuint32_t fmask = ~tmask;\n\n\tassert (cond == 1 || cond == 0);\n\tfor (i = 0; i < 9; i++) {\n\t\tres->val[i] = (truecase->val[i] & tmask) |\n\t\t\t(falsecase->val[i] & fmask);\n\t}\n}\n\n// shift number to the left, i.e multiply it by 2.\n// a must be normalized.  The result is normalized but not reduced.\nvoid bn_lshift(bignum256 *a)\n{\n\tint i;\n\tfor (i = 8; i > 0; i--) {\n\t\ta->val[i] = ((a->val[i] << 1) & 0x3FFFFFFF) | ((a->val[i - 1] & 0x20000000) >> 29);\n\t}\n\ta->val[0] = (a->val[0] << 1) & 0x3FFFFFFF;\n}\n\n// shift number to the right, i.e divide by 2 while rounding down.\n// a must be normalized.  The result is normalized.\nvoid bn_rshift(bignum256 *a)\n{\n\tint i;\n\tfor (i = 0; i < 8; i++) {\n\t\ta->val[i] = (a->val[i] >> 1) | ((a->val[i + 1] & 1) << 29);\n\t}\n\ta->val[8] >>= 1;\n}\n\n// sets bit in bignum\nvoid bn_setbit(bignum256 *a, uint8_t bit)\n{\n\ta->val[bit / 30] |= (1u << (bit % 30));\n}\n\n// clears bit in bignum\nvoid bn_clearbit(bignum256 *a, uint8_t bit)\n{\n\ta->val[bit / 30] &= ~(1u << (bit % 30));\n}\n\n// tests bit in bignum\nuint32_t bn_testbit(bignum256 *a, uint8_t bit)\n{\n\treturn a->val[bit / 30] & (1u << (bit % 30));\n}\n\n// a = b ^ c\nvoid bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c)\n{\n\tint i;\n\tfor (i = 0; i < 9; i++) {\n\t\ta->val[i] = b->val[i] ^ c->val[i];\n\t}\n}\n\n// multiply x by 1/2 modulo prime.\n// it computes x = (x & 1) ? (x + prime) >> 1 : x >> 1.\n// assumes x is normalized.\n// if x was partly reduced, it is also partly reduced on exit.\n// function is constant time.\nvoid bn_mult_half(bignum256 * x, const bignum256 *prime)\n{\n\tint j;\n\tuint32_t xodd = -(x->val[0] & 1);\n\t// compute x = x/2 mod prime\n\t// if x is odd compute (x+prime)/2\n\tuint32_t tmp1 = (x->val[0] + (prime->val[0] & xodd)) >> 1;\n\tfor (j = 0; j < 8; j++) {\n\t\tuint32_t tmp2 = (x->val[j+1] + (prime->val[j+1] & xodd));\n\t\ttmp1 += (tmp2 & 1) << 29;\n\t\tx->val[j] = tmp1 & 0x3fffffff;\n\t\ttmp1 >>= 30;\n\t\ttmp1 += tmp2 >> 1;\n\t}\n\tx->val[8] = tmp1;\n}\n\n// multiply x by k modulo prime.\n// assumes x is normalized, 0 <= k <= 4.\n// guarantees x is partly reduced.\nvoid bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime)\n{\n\tint j;\n\tfor (j = 0; j < 9; j++) {\n\t\tx->val[j] = k * x->val[j];\n\t}\n\tbn_fast_mod(x, prime);\n}\n\n// compute x = x mod prime  by computing  x >= prime ? x - prime : x.\n// assumes x partly reduced, guarantees x fully reduced.\nvoid bn_mod(bignum256 *x, const bignum256 *prime)\n{\n\tconst int flag = bn_is_less(x, prime); // x < prime\n\tbignum256 temp;\n\tbn_subtract(x, prime, &temp); // temp = x - prime\n\tbn_cmov(x, flag, x, &temp);\n}\n\n// auxiliary function for multiplication.\n// compute k * x as a 540 bit number in base 2^30 (normalized).\n// assumes that k and x are normalized.\nvoid bn_multiply_long(const bignum256 *k, const bignum256 *x, uint32_t res[18])\n{\n\tint i, j;\n\tuint64_t temp = 0;\n\n\t// compute lower half of long multiplication\n\tfor (i = 0; i < 9; i++)\n\t{\n\t\tfor (j = 0; j <= i; j++) {\n\t\t\t// no overflow, since 9*2^60 < 2^64\n\t\t\ttemp += k->val[j] * (uint64_t)x->val[i - j];\n\t\t}\n\t\tres[i] = temp & 0x3FFFFFFFu;\n\t\ttemp >>= 30;\n\t}\n\t// compute upper half\n\tfor (; i < 17; i++)\n\t{\n\t\tfor (j = i - 8; j < 9 ; j++) {\n\t\t\t// no overflow, since 9*2^60 < 2^64\n\t\t\ttemp += k->val[j] * (uint64_t)x->val[i - j];\n\t\t}\n\t\tres[i] = temp & 0x3FFFFFFFu;\n\t\ttemp >>= 30;\n\t}\n\tres[17] = temp;\n}\n\n// auxiliary function for multiplication.\n// reduces res modulo prime.\n// assumes    res normalized, res < 2^(30(i-7)) * 2 * prime\n// guarantees res normalized, res < 2^(30(i-8)) * 2 * prime\nvoid bn_multiply_reduce_step(uint32_t res[18], const bignum256 *prime, uint32_t i) {\n\t// let k = i-8.\n\t// on entry:\n\t//   0 <= res < 2^(30k + 31) * prime\n\t// estimate coef = (res / prime / 2^30k)\n\t// by coef = res / 2^(30k + 256)  rounded down\n\t// 0 <= coef < 2^31\n\t// subtract (coef * 2^(30k) * prime) from res\n\t// note that we unrolled the first iteration\n\tuint32_t j;\n\tuint32_t coef = (res[i] >> 16) + (res[i + 1] << 14);\n\tuint64_t temp = 0x2000000000000000ull + res[i - 8] - prime->val[0] * (uint64_t)coef;\n\tassert (coef < 0x80000000u);\n\tres[i - 8] = temp & 0x3FFFFFFF;\n\tfor (j = 1; j < 9; j++) {\n\t\ttemp >>= 30;\n\t\t// Note: coeff * prime->val[j] <= (2^31-1) * (2^30-1)\n\t\t// Hence, this addition will not underflow.\n\t\ttemp += 0x1FFFFFFF80000000ull + res[i - 8 + j] - prime->val[j] * (uint64_t)coef;\n\t\tres[i - 8 + j] = temp & 0x3FFFFFFF;\n\t\t// 0 <= temp < 2^61 + 2^30\n\t}\n\ttemp >>= 30;\n\ttemp += 0x1FFFFFFF80000000ull + res[i - 8 + j];\n\tres[i - 8 + j] = temp & 0x3FFFFFFF;\n\t// we rely on the fact that prime > 2^256 - 2^224\n\t//   res = oldres - coef*2^(30k) * prime;\n\t// and\n\t//   coef * 2^(30k + 256) <= oldres < (coef+1) * 2^(30k + 256)\n\t// Hence, 0 <= res < 2^30k (2^256 + coef * (2^256 - prime))\n\t//                 < 2^30k (2^256 + 2^31 * 2^224)\n\t//                 < 2^30k (2 * prime)\n}\n\n\n// auxiliary function for multiplication.\n// reduces x = res modulo prime.\n// assumes    res normalized, res < 2^270 * 2 * prime\n// guarantees x partly reduced, i.e., x < 2 * prime\nvoid bn_multiply_reduce(bignum256 *x, uint32_t res[18], const bignum256 *prime)\n{\n\tint i;\n\t// res = k * x is a normalized number (every limb < 2^30)\n\t// 0 <= res < 2^270 * 2 * prime.\n\tfor (i = 16; i >= 8; i--) {\n\t\tbn_multiply_reduce_step(res, prime, i);\n\t\tassert(res[i + 1] == 0);\n\t}\n\t// store the result\n\tfor (i = 0; i < 9; i++) {\n\t\tx->val[i] = res[i];\n\t}\n}\n\n// Compute x := k * x  (mod prime)\n// both inputs must be smaller than 180 * prime.\n// result is partly reduced (0 <= x < 2 * prime)\n// This only works for primes between 2^256-2^224 and 2^256.\nvoid bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime)\n{\n\tuint32_t res[18] = {0};\n\tbn_multiply_long(k, x, res);\n\tbn_multiply_reduce(x, res, prime); \n\tmemzero(res, sizeof(res));\n}\n\n// partly reduce x modulo prime\n// input x does not have to be normalized.\n// x can be any number that fits.\n// prime must be between (2^256 - 2^224) and 2^256\n// result is partly reduced, smaller than 2*prime\nvoid bn_fast_mod(bignum256 *x, const bignum256 *prime)\n{\n\tint j;\n\tuint32_t coef;\n\tuint64_t temp;\n\n\tcoef = x->val[8] >> 16;\n\t// substract (coef * prime) from x\n\t// note that we unrolled the first iteration\n\ttemp = 0x2000000000000000ull + x->val[0] - prime->val[0] * (uint64_t)coef;\n\tx->val[0] = temp & 0x3FFFFFFF;\n\tfor (j = 1; j < 9; j++) {\n\t\ttemp >>= 30;\n\t\ttemp += 0x1FFFFFFF80000000ull + x->val[j] - prime->val[j] * (uint64_t)coef;\n\t\tx->val[j] = temp & 0x3FFFFFFF;\n\t}\n}\n\n// square root of x = x^((p+1)/4)\n// http://en.wikipedia.org/wiki/Quadratic_residue#Prime_or_prime_power_modulus\n// assumes    x is normalized but not necessarily reduced.\n// guarantees x is reduced\nvoid bn_sqrt(bignum256 *x, const bignum256 *prime)\n{\n\t// this method compute x^1/2 = x^(prime+1)/4\n\tuint32_t i, j, limb;\n\tbignum256 res, p;\n\tbn_one(&res);\n\t// compute p = (prime+1)/4\n\tmemcpy(&p, prime, sizeof(bignum256));\n\tbn_addi(&p, 1);\n\tbn_rshift(&p);\n\tbn_rshift(&p);\n\tfor (i = 0; i < 9; i++) {\n\t\t// invariants:\n\t\t//    x   = old(x)^(2^(i*30))\n\t\t//    res = old(x)^(p % 2^(i*30))\n\t\t// get the i-th limb of prime - 2\n\t\tlimb = p.val[i];\n\t\tfor (j = 0; j < 30; j++) {\n\t\t\t// invariants:\n\t\t\t//    x    = old(x)^(2^(i*30+j))\n\t\t\t//    res  = old(x)^(p % 2^(i*30+j))\n\t\t\t//    limb = (p % 2^(i*30+30)) / 2^(i*30+j)\n\t\t\tif (i == 8 && limb == 0) break;\n\t\t\tif (limb & 1) {\n\t\t\t\tbn_multiply(x, &res, prime);\n\t\t\t}\n\t\t\tlimb >>= 1;\n\t\t\tbn_multiply(x, x, prime);\n\t\t}\n\t}\n\tbn_mod(&res, prime);\n\tmemcpy(x, &res, sizeof(bignum256));\n\tmemzero(&res, sizeof(res));\n\tmemzero(&p, sizeof(p));\n}\n\n#if ! USE_INVERSE_FAST\n\n// in field G_prime, small but slow\nvoid bn_inverse(bignum256 *x, const bignum256 *prime)\n{\n\t// this method compute x^-1 = x^(prime-2)\n\tuint32_t i, j, limb;\n\tbignum256 res;\n\tbn_one(&res);\n\tfor (i = 0; i < 9; i++) {\n\t\t// invariants:\n\t\t//    x   = old(x)^(2^(i*30))\n\t\t//    res = old(x)^((prime-2) % 2^(i*30))\n\t\t// get the i-th limb of prime - 2\n\t\tlimb = prime->val[i];\n\t\t// this is not enough in general but fine for secp256k1 & nist256p1 because prime->val[0] > 1\n\t\tif (i == 0) limb -= 2;\n\t\tfor (j = 0; j < 30; j++) {\n\t\t\t// invariants:\n\t\t\t//    x    = old(x)^(2^(i*30+j))\n\t\t\t//    res  = old(x)^((prime-2) % 2^(i*30+j))\n\t\t\t//    limb = ((prime-2) % 2^(i*30+30)) / 2^(i*30+j)\n\t\t\t// early abort when only zero bits follow\n\t\t\tif (i == 8 && limb == 0) break;\n\t\t\tif (limb & 1) {\n\t\t\t\tbn_multiply(x, &res, prime);\n\t\t\t}\n\t\t\tlimb >>= 1;\n\t\t\tbn_multiply(x, x, prime);\n\t\t}\n\t}\n\tbn_mod(&res, prime);\n\tmemcpy(x, &res, sizeof(bignum256));\n}\n\n#else\n\n// in field G_prime, big and complicated but fast\n// the input must not be 0 mod prime.\n// the result is smaller than prime\nvoid bn_inverse(bignum256 *x, const bignum256 *prime)\n{\n\tint i, j, k, cmp;\n\tstruct combo {\n\t\tuint32_t a[9];\n\t\tint len1;\n\t} us, vr, *odd, *even;\n\tuint32_t pp[8];\n\tuint32_t temp32;\n\tuint64_t temp;\n\n\t// The algorithm is based on Schroeppel et. al. \"Almost Modular Inverse\"\n\t// algorithm.  We keep four values u,v,r,s in the combo registers\n\t// us and vr.  us stores u in the first len1 limbs (little endian)\n\t// and s in the last 9-len1 limbs (big endian).  vr stores v and r.\n\t// This is because both u*s and v*r are guaranteed to fit in 8 limbs, so\n\t// their components are guaranteed to fit in 9.  During the algorithm,\n\t// the length of u and v shrinks while r and s grow.\n\t// u,v,r,s correspond to F,G,B,C in Schroeppel's algorithm.\n\n\t// reduce x modulo prime.  This is necessary as it has to fit in 8 limbs.\n\tbn_fast_mod(x, prime);\n\tbn_mod(x, prime);\n\t// convert x and prime to 8x32 bit limb form\n\ttemp32 = prime->val[0];\n\tfor (i = 0; i < 8; i++) {\n\t\ttemp32 |= prime->val[i + 1] << (30-2*i);\n\t\tus.a[i] = pp[i] = temp32;\n\t\ttemp32 = prime->val[i + 1] >> (2+2*i);\n\t}\n\ttemp32 = x->val[0];\n\tfor (i = 0; i < 8; i++) {\n\t\ttemp32 |= x->val[i + 1] << (30-2*i);\n\t\tvr.a[i] = temp32;\n\t\ttemp32 = x->val[i + 1] >> (2+2*i);\n\t}\n\tus.len1 = 8;\n\tvr.len1 = 8;\n\t// set s = 1 and r = 0\n\tus.a[8] = 1;\n\tvr.a[8] = 0;\n\t// set k = 0.\n\tk = 0;\n\n\t// only one of the numbers u,v can be even at any time.  We\n\t// let even point to that number and odd to the other.\n\t// Initially the prime u is guaranteed to be odd.\n\todd = &us;\n\teven = &vr;\n\n\t// u = prime, v = x\n\t// r = 0    , s = 1\n\t// k = 0\n\tfor (;;) {\n\t\t// invariants:\n\t\t//   let u = limbs us.a[0..u.len1-1] in little endian,\n\t\t//   let s = limbs us.a[u.len..8] in big endian,\n\t\t//   let v = limbs vr.a[0..u.len1-1] in little endian,\n\t\t//   let r = limbs vr.a[u.len..8] in big endian,\n\t\t//   r,s >= 0 ; u,v >= 1\n\t\t//   x*-r = u*2^k mod prime\n\t\t//   x*s  = v*2^k mod prime\n\t\t//   u*s + v*r = prime\n\t\t//   floor(log2(u)) + floor(log2(v)) + k <= 510\n\t\t//   max(u,v) <= 2^k   (*) see comment at end of loop\n\t\t//   gcd(u,v) = 1\n\t\t//   {odd,even} = {&us, &vr}\n\t\t//   odd->a[0] and odd->a[8] are odd\n\t\t//   even->a[0] or even->a[8] is even\n\t\t//\n\t\t// first u/v are large and r/s small\n\t\t// later u/v are small and r/s large\n\t\tassert(odd->a[0] & 1);\n\t\tassert(odd->a[8] & 1);\n\n\t\t// adjust length of even.\n\t\twhile (even->a[even->len1 - 1] == 0) {\n\t\t\teven->len1--;\n\t\t\t// if input was 0, return.\n\t\t\t// This simple check prevents crashing with stack underflow\n\t\t\t// or worse undesired behaviour for illegal input.\n\t\t\tif (even->len1 < 0)\n\t\t\t\treturn;\n\t\t}\n\n\t\t// reduce even->a while it is even\n\t\twhile (even->a[0] == 0) {\n\t\t\t// shift right first part of even by a limb\n\t\t\t// and shift left second part of even by a limb.\n\t\t\tfor (i = 0; i < 8; i++) {\n\t\t\t\teven->a[i] = even->a[i+1];\n\t\t\t}\n\t\t\teven->a[i] = 0;\n\t\t\teven->len1--;\n\t\t\tk += 32;\n\t\t}\n\t\t// count up to 32 zero bits of even->a.\n\t\tj = 0;\n\t\twhile ((even->a[0] & (1u << j)) == 0) {\n\t\t\tj++;\n\t\t}\n\t\tif (j > 0) {\n\t\t\t// shift first part of even right by j bits.\n\t\t\tfor (i = 0; i + 1 < even->len1; i++) {\n\t\t\t\teven->a[i] = (even->a[i] >> j) | (even->a[i + 1] << (32 - j));\n\t\t\t}\n\t\t\teven->a[i] = (even->a[i] >> j);\n\t\t\tif (even->a[i] == 0) {\n\t\t\t\teven->len1--;\n\t\t\t} else {\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\t// shift second part of even left by j bits.\n\t\t\tfor (; i < 8; i++) {\n\t\t\t\teven->a[i] = (even->a[i] << j) | (even->a[i + 1] >> (32 - j));\n\t\t\t}\n\t\t\teven->a[i] = (even->a[i] << j);\n\t\t\t// add j bits to k.\n\t\t\tk += j;\n\t\t}\n\t\t// invariant is reestablished.\n\t\t// now both a[0] are odd.\n\t\tassert(odd->a[0] & 1);\n\t\tassert(odd->a[8] & 1);\n\t\tassert(even->a[0] & 1);\n\t\tassert((even->a[8] & 1) == 0);\n\n\t\t// cmp > 0 if us.a[0..len1-1] > vr.a[0..len1-1],\n\t\t// cmp = 0 if equal, < 0 if less.\n\t\tcmp = us.len1 - vr.len1;\n\t\tif (cmp == 0) {\n\t\t\ti = us.len1 - 1;\n\t\t\twhile (i >= 0 && us.a[i] == vr.a[i]) i--;\n\t\t\t// both are equal to 1 and we are done.\n\t\t\tif (i == -1)\n\t\t\t\tbreak;\n\t\t\tcmp = us.a[i] > vr.a[i] ? 1 : -1;\n\t\t}\n\t\tif (cmp > 0) {\n\t\t\teven = &us;\n\t\t\todd = &vr;\n\t\t} else {\n\t\t\teven = &vr;\n\t\t\todd = &us;\n\t\t}\n\n\t\t// now even > odd.\n\n\t\t//  even->a[0..len1-1] = (even->a[0..len1-1] - odd->a[0..len1-1]);\n\t\ttemp = 1;\n\t\tfor (i = 0; i < odd->len1; i++) {\n\t\t\ttemp += 0xFFFFFFFFull + even->a[i] - odd->a[i];\n\t\t\teven->a[i] = temp & 0xFFFFFFFF;\n\t\t\ttemp >>= 32;\n\t\t}\n\t\tfor (; i < even->len1; i++) {\n\t\t\ttemp += 0xFFFFFFFFull + even->a[i];\n\t\t\teven->a[i] = temp & 0xFFFFFFFF;\n\t\t\ttemp >>= 32;\n\t\t}\n\t\t//  odd->a[len1..8] = (odd->b[len1..8] + even->b[len1..8]);\n\t\ttemp = 0;\n\t\tfor (i = 8; i >= even->len1; i--) {\n\t\t\ttemp += (uint64_t) odd->a[i] + even->a[i];\n\t\t\todd->a[i] = temp & 0xFFFFFFFF;\n\t\t\ttemp >>= 32;\n\t\t}\n\t\tfor (; i >= odd->len1; i--) {\n\t\t\ttemp += (uint64_t) odd->a[i];\n\t\t\todd->a[i] = temp & 0xFFFFFFFF;\n\t\t\ttemp >>= 32;\n\t\t}\n\t\t// note that\n\t\t//  if u > v:\n\t\t//   u'2^k = (u - v) 2^k = x(-r) - xs = x(-(r+s)) = x(-r') mod prime\n\t\t//   u's' + v'r' = (u-v)s + v(r+s) = us + vr\n\t\t//  if u < v:\n\t\t//   v'2^k = (v - u) 2^k = xs - x(-r) = x(s+r) = xs' mod prime\n\t\t//   u's' + v'r' = u(s+r) + (v-u)r = us + vr\n\n\t\t// even->a[0] is difference between two odd numbers, hence even.\n\t\t// odd->a[8] is sum of even and odd number, hence odd.\n\t\tassert(odd->a[0] & 1);\n\t\tassert(odd->a[8] & 1);\n\t\tassert((even->a[0] & 1) == 0);\n\n\t\t// The invariants are (almost) reestablished.\n\t\t// The invariant max(u,v) <= 2^k can be invalidated at this point,\n\t\t// because odd->a[len1..8] was changed.  We only have\n\t\t//\n\t\t//     odd->a[len1..8] <= 2^{k+1}\n\t\t//\n\t\t// Since even->a[0] is even, k will be incremented at the beginning\n\t\t// of the next loop while odd->a[len1..8] remains unchanged.\n\t\t// So after that, odd->a[len1..8] <= 2^k will hold again.\n\t}\n\t// In the last iteration we had u = v and gcd(u,v) = 1.\n\t// Hence, u=1, v=1, s+r = prime, k <= 510, 2^k > max(s,r) >= prime/2\n\t// This implies 0 <= s < prime and 255 <= k <= 510.\n\t//\n\t// The invariants also give us x*s = 2^k mod prime,\n\t// hence s = 2^k * x^-1 mod prime.\n\t// We need to compute s/2^k mod prime.\n\n\t// First we compute inverse = -prime^-1 mod 2^32, which we need later.\n\t// We use the Explicit Quadratic Modular inverse algorithm.\n\t//   http://arxiv.org/pdf/1209.6626.pdf\n\t// a^-1  = (2-a) * PROD_i (1 + (a - 1)^(2^i)) mod 2^32\n\t// the product will converge quickly, because (a-1)^(2^i) will be\n\t// zero mod 2^32 after at most five iterations.\n\t// We want to compute -prime^-1 so we start with (pp[0]-2).\n\tassert(pp[0] & 1);\n\tuint32_t amone = pp[0]-1;\n\tuint32_t inverse = pp[0] - 2;\n\twhile (amone) {\n\t\tamone *= amone;\n\t\tinverse *= (amone + 1);\n\t}\n\n\twhile (k >= 32) {\n\t\t// compute s / 2^32 modulo prime.\n\t\t// Idea: compute factor, such that\n\t\t//   s + factor*prime mod 2^32 == 0\n\t\t// i.e. factor = s * -1/prime mod 2^32.\n\t\t// Then compute s + factor*prime and shift right by 32 bits.\n\t\tuint32_t factor = (inverse * us.a[8]) & 0xffffffff;\n\t\ttemp = us.a[8] + (uint64_t) pp[0] * factor;\n\t\tassert((temp & 0xffffffff) == 0);\n\t\ttemp >>= 32;\n\t\tfor (i = 0; i < 7; i++) {\n\t\t\ttemp += us.a[8-(i+1)] + (uint64_t) pp[i+1] * factor;\n\t\t\tus.a[8-i] = temp & 0xffffffff;\n\t\t\ttemp >>= 32;\n\t\t}\n\t\tus.a[8-i] = temp & 0xffffffff;\n\t\tk -= 32;\n\t}\n\tif (k > 0) {\n\t\t// compute s / 2^k  modulo prime.\n\t\t// Same idea: compute factor, such that\n\t\t//   s + factor*prime mod 2^k == 0\n\t\t// i.e. factor = s * -1/prime mod 2^k.\n\t\t// Then compute s + factor*prime and shift right by k bits.\n\t\tuint32_t mask = (1u << k) - 1;\n\t\tuint32_t factor = (inverse * us.a[8]) & mask;\n\t\ttemp = (us.a[8] + (uint64_t) pp[0] * factor) >> k;\n\t\tassert(((us.a[8] + pp[0] * factor) & mask) == 0);\n\t\tfor (i = 0; i < 7; i++) {\n\t\t\ttemp += (us.a[8-(i+1)] + (uint64_t) pp[i+1] * factor) << (32 - k);\n\t\t\tus.a[8-i] = temp & 0xffffffff;\n\t\t\ttemp >>= 32;\n\t\t}\n\t\tus.a[8-i] = temp & 0xffffffff;\n\t}\n\n\t// convert s to bignum style\n\ttemp32 = 0;\n\tfor (i = 0; i < 8; i++) {\n\t\tx->val[i] = ((us.a[8-i] << (2 * i)) & 0x3FFFFFFFu) | temp32;\n\t\ttemp32 = us.a[8-i] >> (30 - 2 * i);\n\t}\n\tx->val[i] = temp32;\n\n\t// let's wipe all temp buffers\n\tmemzero(pp, sizeof(pp));\n\tmemzero(&us, sizeof(us));\n\tmemzero(&vr, sizeof(vr));\n}\n#endif\n\nvoid bn_normalize(bignum256 *a) {\n\tbn_addi(a, 0);\n}\n\n// add two numbers a = a + b\n// assumes that a, b are normalized\n// guarantees that a is normalized\nvoid bn_add(bignum256 *a, const bignum256 *b)\n{\n\tint i;\n\tuint32_t tmp = 0;\n\tfor (i = 0; i < 9; i++) {\n\t\ttmp += a->val[i] + b->val[i];\n\t\ta->val[i] = tmp & 0x3FFFFFFF;\n\t\ttmp >>= 30;\n\t}\n}\n\nvoid bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime)\n{\n\tint i;\n\tfor (i = 0; i < 9; i++) {\n\t\ta->val[i] += b->val[i];\n\t}\n\tbn_fast_mod(a, prime);\n}\n\nvoid bn_addi(bignum256 *a, uint32_t b) {\n\tint i;\n\tuint32_t tmp = b;\n\tfor (i = 0; i < 9; i++) {\n\t\ttmp += a->val[i];\n\t\ta->val[i] = tmp & 0x3FFFFFFF;\n\t\ttmp >>= 30;\n\t}\n}\n\nvoid bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime) {\n\tassert (b <= prime->val[0]);\n\t// the possible underflow will be taken care of when adding the prime\n\ta->val[0] -= b;\n\tbn_add(a, prime);\n}\n\n// res = a - b mod prime.  More exactly res = a + (2*prime - b).\n// b must be a partly reduced number\n// result is normalized but not reduced.\nvoid bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, const bignum256 *prime)\n{\n\tint i;\n\tuint32_t temp = 1;\n\tfor (i = 0; i < 9; i++) {\n\t\ttemp += 0x3FFFFFFF + a->val[i] + 2u * prime->val[i] - b->val[i];\n\t\tres->val[i] = temp & 0x3FFFFFFF;\n\t\ttemp >>= 30;\n\t}\n}\n\n// res = a - b ; a > b\nvoid bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res)\n{\n\tint i;\n\tuint32_t tmp = 1;\n\tfor (i = 0; i < 9; i++) {\n\t\ttmp += 0x3FFFFFFF + a->val[i] - b->val[i];\n\t\tres->val[i] = tmp & 0x3FFFFFFF;\n\t\ttmp >>= 30;\n\t}\n}\n\n// a / 58 = a (+r)\nvoid bn_divmod58(bignum256 *a, uint32_t *r)\n{\n\tint i;\n\tuint32_t rem, tmp;\n\trem = a->val[8] % 58;\n\ta->val[8] /= 58;\n\tfor (i = 7; i >= 0; i--) {\n\t\t// invariants:\n\t\t//   rem = old(a) >> 30(i+1) % 58\n\t\t//   a[i+1..8] = old(a[i+1..8])/58\n\t\t//   a[0..i]   = old(a[0..i])\n\t\t// 2^30 == 18512790*58 + 4\n\t\ttmp = rem * 4 + a->val[i];\n\t\t// set a[i] = (rem * 2^30 + a[i])/58\n\t\t//          = rem * 18512790 + (rem * 4 + a[i])/58\n\t\ta->val[i] = rem * 18512790 + (tmp / 58);\n\t\t// set rem = (rem * 2^30 + a[i]) mod 58\n\t\t//         = (rem * 4 + a[i]) mod 58\n\t\trem = tmp % 58;\n\t}\n\t*r = rem;\n}\n\n// a / 1000 = a (+r)\nvoid bn_divmod1000(bignum256 *a, uint32_t *r)\n{\n\tint i;\n\tuint32_t rem, tmp;\n\trem = a->val[8] % 1000;\n\ta->val[8] /= 1000;\n\tfor (i = 7; i >= 0; i--) {\n\t\t// invariants:\n\t\t//   rem = old(a) >> 30(i+1) % 1000\n\t\t//   a[i+1..8] = old(a[i+1..8])/1000\n\t\t//   a[0..i]   = old(a[0..i])\n\t\t// 2^30 == 1073741*1000 + 824\n\t\ttmp = rem * 824 + a->val[i];\n\t\t// set a[i] = (rem * 2^30 + a[i])/1000\n\t\t//          = rem * 1073741 + (rem * 824 + a[i])/1000\n\t\ta->val[i] = rem * 1073741 + (tmp / 1000);\n\t\t// set rem = (rem * 2^30 + a[i]) mod 1000\n\t\t//         = (rem * 824 + a[i]) mod 1000\n\t\trem = tmp % 1000;\n\t}\n\t*r = rem;\n}\n\nsize_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen)\n{\n\tsize_t prefixlen = prefix ? strlen(prefix) : 0;\n\tsize_t suffixlen = suffix ? strlen(suffix) : 0;\n\n\t/* add prefix to beginning of out buffer */\n\tif (prefixlen) {\n\t\tmemcpy(out, prefix, prefixlen);\n\t}\n\t/* add suffix to end of out buffer */\n\tif (suffixlen) {\n\t\tmemcpy(&out[outlen - suffixlen - 1], suffix, suffixlen);\n\t}\n\t/* nul terminate (even if suffix = NULL) */\n\tout[outlen - 1] = '\\0';\n\n\t/* fill number between prefix and suffix (between start and end) */\n\tchar *start = &out[prefixlen], *end = &out[outlen - suffixlen - 1];\n\tchar *str = end;\n\n#define BN_FORMAT_PUSH_CHECKED(c) \\\n\tdo { \\\n\t\tif (str == start) return 0; \\\n\t\t*--str = (c); \\\n\t} while (0)\n\n#define BN_FORMAT_PUSH(n) \\\n\tdo { \\\n\t\tif (exponent < 0) { \\\n\t\t\texponent++; \\\n\t\t} else { \\\n\t\t\tif ((n) > 0 || trailing || str != end || decimals <= 1) { \\\n\t\t\t\tBN_FORMAT_PUSH_CHECKED('0' + (n)); \\\n\t\t\t} \\\n\t\t\tif (decimals > 0 && decimals-- == 1) { \\\n\t\t\t\tBN_FORMAT_PUSH_CHECKED('.'); \\\n\t\t\t} \\\n\t\t} \\\n\t} while (0)\n\n\tbignum256 val;\n\tmemcpy(&val, amnt, sizeof(bignum256));\n\n\tif (bn_is_zero(&val)) {\n\t\texponent = 0;\n\t}\n\n\tfor (; exponent > 0; exponent--) {\n\t\tBN_FORMAT_PUSH(0);\n\t}\n\n\tunsigned int digits = bn_digitcount(&val);\n\tfor (unsigned int i = 0; i < digits / 3; i++) {\n\t\tuint32_t limb;\n\t\tbn_divmod1000(&val, &limb);\n\n\t\tBN_FORMAT_PUSH(limb % 10);\n\t\tlimb /= 10;\n\t\tBN_FORMAT_PUSH(limb % 10);\n\t\tlimb /= 10;\n\t\tBN_FORMAT_PUSH(limb % 10);\n\t}\n\n\tif (digits % 3 != 0) {\n\t\tuint32_t limb;\n\t\tbn_divmod1000(&val, &limb);\n\n\t\tswitch (digits % 3) {\n\t\tcase 2:\n\t\t\tBN_FORMAT_PUSH(limb % 10);\n\t\t\tlimb /= 10;\n\t\t\t//-fallthrough\n\n\t\tcase 1:\n\t\t\tBN_FORMAT_PUSH(limb % 10);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\twhile (decimals > 0 || str[0] == '\\0' || str[0] == '.') {\n\t\tBN_FORMAT_PUSH(0);\n\t}\n\n\t/* finally move number to &out[prefixlen] to close the gap between\n\t * prefix and str.  len is length of number + suffix + traling 0\n\t */\n\tsize_t len = &out[outlen] - str;\n\tmemmove(&out[prefixlen], str, len);\n\n\t/* return length of number including prefix and suffix without trailing 0 */\n\treturn prefixlen + len - 1;\n}\n\n#if USE_BN_PRINT\nvoid bn_print(const bignum256 *a)\n{\n\tprintf(\"%04x\", a->val[8] & 0x0000FFFF);\n\tprintf(\"%08x\", (a->val[7] << 2) | ((a->val[6] & 0x30000000) >> 28));\n\tprintf(\"%07x\", a->val[6] & 0x0FFFFFFF);\n\tprintf(\"%08x\", (a->val[5] << 2) | ((a->val[4] & 0x30000000) >> 28));\n\tprintf(\"%07x\", a->val[4] & 0x0FFFFFFF);\n\tprintf(\"%08x\", (a->val[3] << 2) | ((a->val[2] & 0x30000000) >> 28));\n\tprintf(\"%07x\", a->val[2] & 0x0FFFFFFF);\n\tprintf(\"%08x\", (a->val[1] << 2) | ((a->val[0] & 0x30000000) >> 28));\n\tprintf(\"%07x\", a->val[0] & 0x0FFFFFFF);\n}\n\nvoid bn_print_raw(const bignum256 *a)\n{\n\tint i;\n\tfor (i = 0; i <= 8; i++) {\n\t\tprintf(\"0x%08x, \", a->val[i]);\n\t}\n}\n#endif\n"
  },
  {
    "path": "src/utility/trezor/bignum.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n * Copyright (c) 2016 Alex Beregszaszi\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __BIGNUM_H__\n#define __BIGNUM_H__\n\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n#include \"options.h\"\n\n// bignum256 are 256 bits stored as 8*30 bit + 1*16 bit\n// val[0] are lowest 30 bits, val[8] highest 16 bits\ntypedef struct {\n\tuint32_t val[9];\n} bignum256;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n// read 4 big endian bytes into uint32\nuint32_t read_be(const uint8_t *data);\n\n// write 4 big endian bytes\nvoid write_be(uint8_t *data, uint32_t x);\n\n// read 4 little endian bytes into uint32\nuint32_t read_le(const uint8_t *data);\n\n// write 4 little endian bytes\nvoid write_le(uint8_t *data, uint32_t x);\n\nvoid bn_read_be(const uint8_t *in_number, bignum256 *out_number);\n\nvoid bn_write_be(const bignum256 *in_number, uint8_t *out_number);\n\nvoid bn_read_le(const uint8_t *in_number, bignum256 *out_number);\n\nvoid bn_write_le(const bignum256 *in_number, uint8_t *out_number);\n\nvoid bn_read_uint32(uint32_t in_number, bignum256 *out_number);\n\nvoid bn_read_uint64(uint64_t in_number, bignum256 *out_number);\n\nstatic inline uint32_t bn_write_uint32(const bignum256 *in_number)\n{\n\treturn in_number->val[0] | (in_number->val[1] << 30);\n}\n\nstatic inline uint64_t bn_write_uint64(const bignum256 *in_number)\n{\n\tuint64_t tmp;\n\ttmp = in_number->val[2];\n\ttmp <<= 30;\n\ttmp |= in_number->val[1];\n\ttmp <<= 30;\n\ttmp |= in_number->val[0];\n\treturn tmp;\n}\n\n// copies number a to b\nstatic inline void bn_copy(const bignum256 *a, bignum256 *b) {\n\t*b = *a;\n}\n\nint bn_bitcount(const bignum256 *a);\n\nunsigned int bn_digitcount(const bignum256 *a);\n\nvoid bn_zero(bignum256 *a);\n\nint bn_is_zero(const bignum256 *a);\n\nvoid bn_one(bignum256 *a);\n\nstatic inline int bn_is_even(const bignum256 *a) {\n\treturn (a->val[0] & 1) == 0;\n}\n\nstatic inline int bn_is_odd(const bignum256 *a) {\n\treturn (a->val[0] & 1) == 1;\n}\n\nint bn_is_less(const bignum256 *a, const bignum256 *b);\n\nint bn_is_equal(const bignum256 *a, const bignum256 *b);\n\nvoid bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, const bignum256 *falsecase);\n\nvoid bn_lshift(bignum256 *a);\n\nvoid bn_rshift(bignum256 *a);\n\nvoid bn_setbit(bignum256 *a, uint8_t bit);\n\nvoid bn_clearbit(bignum256 *a, uint8_t bit);\n\nuint32_t bn_testbit(bignum256 *a, uint8_t bit);\n\nvoid bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c);\n\nvoid bn_mult_half(bignum256 *x, const bignum256 *prime);\n\nvoid bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime);\n\nvoid bn_mod(bignum256 *x, const bignum256 *prime);\n\nvoid bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime);\n\nvoid bn_fast_mod(bignum256 *x, const bignum256 *prime);\n\nvoid bn_sqrt(bignum256 *x, const bignum256 *prime);\n\nvoid bn_inverse(bignum256 *x, const bignum256 *prime);\n\nvoid bn_normalize(bignum256 *a);\n\nvoid bn_add(bignum256 *a, const bignum256 *b);\n\nvoid bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime);\n\nvoid bn_addi(bignum256 *a, uint32_t b);\n\nvoid bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime);\n\nvoid bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, const bignum256 *prime);\n\nvoid bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res);\n\nvoid bn_divmod58(bignum256 *a, uint32_t *r);\n\nvoid bn_divmod1000(bignum256 *a, uint32_t *r);\n\nsize_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen);\n\nstatic inline size_t bn_format_uint64(uint64_t amount, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen)\n{\n\tbignum256 amnt;\n\tbn_read_uint64(amount, &amnt);\n\n\treturn bn_format(&amnt, prefix, suffix, decimals, exponent, trailing, out, outlen);\n}\n\n#if USE_BN_PRINT\nvoid bn_print(const bignum256 *a);\nvoid bn_print_raw(const bignum256 *a);\n#endif\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/bip32.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __BIP32_H__\n#define __BIP32_H__\n\n#include <stdint.h>\n#include <stdlib.h>\n#include <stdbool.h>\n#include \"ecdsa.h\"\n// #include \"ed25519-donna/ed25519.h\"\n#include \"options.h\"\n\ntypedef struct {\n\tconst char *bip32_name;    // string for generating BIP32 xprv from seed\n\tconst ecdsa_curve *params; // ecdsa curve parameters, null for ed25519\n\n\tHasherType hasher_base58;\n\tHasherType hasher_sign;\n\tHasherType hasher_pubkey;\n\tHasherType hasher_script;\n} curve_info;\n\ntypedef struct {\n\tuint32_t depth;\n\tuint32_t child_num;\n\tuint8_t chain_code[32];\n\n\tuint8_t private_key[32];\n\tuint8_t private_key_extension[32];\n\n\tuint8_t public_key[33];\n\tconst curve_info *curve;\n} HDNode;\n\n// int hdnode_from_xpub(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *public_key, const char *curve, HDNode *out);\n//\n// int hdnode_from_xprv(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *private_key, const char *curve, HDNode *out);\n//\n// int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, HDNode *out);\n//\n// #define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000))\n//\n// int hdnode_private_ckd(HDNode *inout, uint32_t i);\n//\n// #if USE_CARDANO\n// int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i);\n// int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, const uint8_t *seed, int seed_len, HDNode *out);\n// #endif\n//\n// int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code);\n//\n// int hdnode_public_ckd(HDNode *inout, uint32_t i);\n//\n// void hdnode_public_ckd_address_optimized(const curve_point *pub, const uint8_t *chain_code, uint32_t i, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize, int addrformat);\n//\n// #if USE_BIP32_CACHE\n// int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, uint32_t *fingerprint);\n// #endif\n//\n// uint32_t hdnode_fingerprint(HDNode *node);\n//\n// void hdnode_fill_public_key(HDNode *node);\n//\n// #if USE_ETHEREUM\n// int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash);\n// #endif\n//\n// #if USE_NEM\n// int hdnode_get_nem_address(HDNode *node, uint8_t version, char *address);\n// int hdnode_get_nem_shared_key(const HDNode *node, const ed25519_public_key peer_public_key, const uint8_t *salt, ed25519_public_key mul, uint8_t *shared_key);\n// int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key, const uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer);\n// int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key, uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer);\n// #endif\n//\n// int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType hasher_sign, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));\n// int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));\n//\n// int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, uint8_t *session_key, int *result_size);\n//\n// int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize);\n//\n// int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize);\n//\n// int hdnode_deserialize(const char *str, uint32_t version_public, uint32_t version_private, const char *curve, HDNode *node, uint32_t *fingerprint);\n//\n// void hdnode_get_address_raw(HDNode *node, uint32_t version, uint8_t *addr_raw);\n// void hdnode_get_address(HDNode *node, uint32_t version, char *addr, int addrsize);\n//\n// const curve_info *get_curve_by_name(const char *curve_name);\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/bip39.c",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <string.h>\n#include <stdbool.h>\n\n#include \"bip39.h\"\n#include \"hmac.h\"\n#include \"rand.h\"\n#include \"sha2.h\"\n#include \"pbkdf2.h\"\n#include \"bip39_english.h\"\n#include \"options.h\"\n#include \"memzero.h\"\n\n#if USE_BIP39_CACHE\n\nstatic int bip39_cache_index = 0;\n\nstatic CONFIDENTIAL struct {\n\tbool set;\n\tchar mnemonic[256];\n\tchar passphrase[64];\n\tuint8_t seed[512 / 8];\n} bip39_cache[BIP39_CACHE_SIZE];\n\n#endif\n\nconst char *mnemonic_generate(int strength)\n{\n\tif (strength % 32 || strength < 128 || strength > 256) {\n\t\treturn 0;\n\t}\n\tuint8_t data[32];\n\trandom_buffer(data, 32);\n\tconst char *r = mnemonic_from_data(data, strength / 8);\n\tmemzero(data, sizeof(data));\n\treturn r;\n}\n\nstatic CONFIDENTIAL char mnemo[24 * 10];\n\nconst char *mnemonic_from_data(const uint8_t *data, int len)\n{\n\tif (len % 4 || len < 16 || len > 32) {\n\t\treturn 0;\n\t}\n\n\tuint8_t bits[32 + 1];\n\n\tsha256_Raw(data, len, bits);\n\t// checksum\n\tbits[len] = bits[0];\n\t// data\n\tmemcpy(bits, data, len);\n\n\tint mlen = len * 3 / 4;\n\n\tint i, j, idx;\n\tchar *p = mnemo;\n\tfor (i = 0; i < mlen; i++) {\n\t\tidx = 0;\n\t\tfor (j = 0; j < 11; j++) {\n\t\t\tidx <<= 1;\n\t\t\tidx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0;\n\t\t}\n\t\tstrcpy(p, wordlist[idx]);\n\t\tp += strlen(wordlist[idx]);\n\t\t*p = (i < mlen - 1) ? ' ' : 0;\n\t\tp++;\n\t}\n\tmemzero(bits, sizeof(bits));\n\n\treturn mnemo;\n}\n\nvoid mnemonic_clear(void)\n{\n\tmemzero(mnemo, sizeof(mnemo));\n}\n\nint mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy)\n{\n\tif (!mnemonic) {\n\t\treturn 0;\n\t}\n\n\tuint32_t i = 0, n = 0;\n\n\twhile (mnemonic[i]) {\n\t\tif (mnemonic[i] == ' ') {\n\t\t\tn++;\n\t\t}\n\t\ti++;\n\t}\n\tn++;\n\n\t// check number of words\n\tif (n != 12 && n != 18 && n != 24) {\n\t\treturn 0;\n\t}\n\n\tchar current_word[10];\n\tuint32_t j, k, ki, bi = 0;\n\tuint8_t bits[32 + 1];\n\n\tmemzero(bits, sizeof(bits));\n\ti = 0;\n\twhile (mnemonic[i]) {\n\t\tj = 0;\n\t\twhile (mnemonic[i] != ' ' && mnemonic[i] != 0) {\n\t\t\tif (j >= sizeof(current_word) - 1) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tcurrent_word[j] = mnemonic[i];\n\t\t\ti++; j++;\n\t\t}\n\t\tcurrent_word[j] = 0;\n\t\tif (mnemonic[i] != 0) {\n\t\t\ti++;\n\t\t}\n\t\tk = 0;\n\t\tfor (;;) {\n\t\t\tif (!wordlist[k]) { // word not found\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (strcmp(current_word, wordlist[k]) == 0) { // word found on index k\n\t\t\t\tfor (ki = 0; ki < 11; ki++) {\n\t\t\t\t\tif (k & (1 << (10 - ki))) {\n\t\t\t\t\t\tbits[bi / 8] |= 1 << (7 - (bi % 8));\n\t\t\t\t\t}\n\t\t\t\t\tbi++;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tk++;\n\t\t}\n\t}\n\tif (bi != n * 11) {\n\t\treturn 0;\n\t}\n\tmemcpy(entropy, bits, sizeof(bits));\n\treturn n * 11;\n}\n\nint mnemonic_check(const char *mnemonic)\n{\n\tuint8_t bits[32 + 1];\n\tint seed_len = mnemonic_to_entropy(mnemonic, bits);\n\tif (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) {\n\t\treturn 0;\n\t}\n\tint words = seed_len / 11;\n\n\tuint8_t checksum = bits[words * 4 / 3];\n\tsha256_Raw(bits, words * 4 / 3, bits);\n\tif (words == 12) {\n\t\treturn (bits[0] & 0xF0) == (checksum & 0xF0); // compare first 4 bits\n\t} else if (words == 18) {\n\t\treturn (bits[0] & 0xFC) == (checksum & 0xFC); // compare first 6 bits\n\t} else if (words == 24) {\n\t\treturn bits[0] == checksum; // compare 8 bits\n\t}\n\treturn 0;\n}\n\n// passphrase must be at most 256 characters otherwise it would be truncated\nvoid mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total))\n{\n\tint mnemoniclen = strlen(mnemonic);\n\tint passphraselen = strlen(passphrase);\n#if USE_BIP39_CACHE\n\t// check cache\n\tif (mnemoniclen < 256 && passphraselen < 64) {\n\t\tfor (int i = 0; i < BIP39_CACHE_SIZE; i++) {\n\t\t\tif (!bip39_cache[i].set) continue;\n\t\t\tif (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue;\n\t\t\tif (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue;\n\t\t\t// found the correct entry\n\t\t\tmemcpy(seed, bip39_cache[i].seed, 512 / 8);\n\t\t\treturn;\n\t\t}\n\t}\n#endif\n\tuint8_t salt[8 + 256];\n\tmemcpy(salt, \"mnemonic\", 8);\n\tmemcpy(salt + 8, passphrase, passphraselen);\n\tstatic CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx;\n\tpbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, mnemoniclen, salt, passphraselen + 8, 1);\n\tif (progress_callback) {\n\t\tprogress_callback(0, BIP39_PBKDF2_ROUNDS);\n\t}\n\tfor (int i = 0; i < 16; i++) {\n\t\tpbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16);\n\t\tif (progress_callback) {\n\t\t\tprogress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16, BIP39_PBKDF2_ROUNDS);\n\t\t}\n\t}\n\tpbkdf2_hmac_sha512_Final(&pctx, seed);\n\tmemzero(salt, sizeof(salt));\n#if USE_BIP39_CACHE\n\t// store to cache\n\tif (mnemoniclen < 256 && passphraselen < 64) {\n\t\tbip39_cache[bip39_cache_index].set = true;\n\t\tstrcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic);\n\t\tstrcpy(bip39_cache[bip39_cache_index].passphrase, passphrase);\n\t\tmemcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8);\n\t\tbip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE;\n\t}\n#endif\n}\n\nconst char * const *mnemonic_wordlist(void)\n{\n\treturn wordlist;\n}\n"
  },
  {
    "path": "src/utility/trezor/bip39.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __BIP39_H__\n#define __BIP39_H__\n\n#include <stdint.h>\n\n#define BIP39_PBKDF2_ROUNDS 2048\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nconst char *mnemonic_generate(int strength);\t// strength in bits\nconst char *mnemonic_from_data(const uint8_t *data, int len);\nvoid mnemonic_clear(void);\n\nint mnemonic_check(const char *mnemonic);\n\nint mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy);\n\n// passphrase must be at most 256 characters otherwise it would be truncated\nvoid mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total));\n\nconst char * const *mnemonic_wordlist(void);\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/bip39_english.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\nstatic const char * const wordlist[] = {\n\"abandon\",\n\"ability\",\n\"able\",\n\"about\",\n\"above\",\n\"absent\",\n\"absorb\",\n\"abstract\",\n\"absurd\",\n\"abuse\",\n\"access\",\n\"accident\",\n\"account\",\n\"accuse\",\n\"achieve\",\n\"acid\",\n\"acoustic\",\n\"acquire\",\n\"across\",\n\"act\",\n\"action\",\n\"actor\",\n\"actress\",\n\"actual\",\n\"adapt\",\n\"add\",\n\"addict\",\n\"address\",\n\"adjust\",\n\"admit\",\n\"adult\",\n\"advance\",\n\"advice\",\n\"aerobic\",\n\"affair\",\n\"afford\",\n\"afraid\",\n\"again\",\n\"age\",\n\"agent\",\n\"agree\",\n\"ahead\",\n\"aim\",\n\"air\",\n\"airport\",\n\"aisle\",\n\"alarm\",\n\"album\",\n\"alcohol\",\n\"alert\",\n\"alien\",\n\"all\",\n\"alley\",\n\"allow\",\n\"almost\",\n\"alone\",\n\"alpha\",\n\"already\",\n\"also\",\n\"alter\",\n\"always\",\n\"amateur\",\n\"amazing\",\n\"among\",\n\"amount\",\n\"amused\",\n\"analyst\",\n\"anchor\",\n\"ancient\",\n\"anger\",\n\"angle\",\n\"angry\",\n\"animal\",\n\"ankle\",\n\"announce\",\n\"annual\",\n\"another\",\n\"answer\",\n\"antenna\",\n\"antique\",\n\"anxiety\",\n\"any\",\n\"apart\",\n\"apology\",\n\"appear\",\n\"apple\",\n\"approve\",\n\"april\",\n\"arch\",\n\"arctic\",\n\"area\",\n\"arena\",\n\"argue\",\n\"arm\",\n\"armed\",\n\"armor\",\n\"army\",\n\"around\",\n\"arrange\",\n\"arrest\",\n\"arrive\",\n\"arrow\",\n\"art\",\n\"artefact\",\n\"artist\",\n\"artwork\",\n\"ask\",\n\"aspect\",\n\"assault\",\n\"asset\",\n\"assist\",\n\"assume\",\n\"asthma\",\n\"athlete\",\n\"atom\",\n\"attack\",\n\"attend\",\n\"attitude\",\n\"attract\",\n\"auction\",\n\"audit\",\n\"august\",\n\"aunt\",\n\"author\",\n\"auto\",\n\"autumn\",\n\"average\",\n\"avocado\",\n\"avoid\",\n\"awake\",\n\"aware\",\n\"away\",\n\"awesome\",\n\"awful\",\n\"awkward\",\n\"axis\",\n\"baby\",\n\"bachelor\",\n\"bacon\",\n\"badge\",\n\"bag\",\n\"balance\",\n\"balcony\",\n\"ball\",\n\"bamboo\",\n\"banana\",\n\"banner\",\n\"bar\",\n\"barely\",\n\"bargain\",\n\"barrel\",\n\"base\",\n\"basic\",\n\"basket\",\n\"battle\",\n\"beach\",\n\"bean\",\n\"beauty\",\n\"because\",\n\"become\",\n\"beef\",\n\"before\",\n\"begin\",\n\"behave\",\n\"behind\",\n\"believe\",\n\"below\",\n\"belt\",\n\"bench\",\n\"benefit\",\n\"best\",\n\"betray\",\n\"better\",\n\"between\",\n\"beyond\",\n\"bicycle\",\n\"bid\",\n\"bike\",\n\"bind\",\n\"biology\",\n\"bird\",\n\"birth\",\n\"bitter\",\n\"black\",\n\"blade\",\n\"blame\",\n\"blanket\",\n\"blast\",\n\"bleak\",\n\"bless\",\n\"blind\",\n\"blood\",\n\"blossom\",\n\"blouse\",\n\"blue\",\n\"blur\",\n\"blush\",\n\"board\",\n\"boat\",\n\"body\",\n\"boil\",\n\"bomb\",\n\"bone\",\n\"bonus\",\n\"book\",\n\"boost\",\n\"border\",\n\"boring\",\n\"borrow\",\n\"boss\",\n\"bottom\",\n\"bounce\",\n\"box\",\n\"boy\",\n\"bracket\",\n\"brain\",\n\"brand\",\n\"brass\",\n\"brave\",\n\"bread\",\n\"breeze\",\n\"brick\",\n\"bridge\",\n\"brief\",\n\"bright\",\n\"bring\",\n\"brisk\",\n\"broccoli\",\n\"broken\",\n\"bronze\",\n\"broom\",\n\"brother\",\n\"brown\",\n\"brush\",\n\"bubble\",\n\"buddy\",\n\"budget\",\n\"buffalo\",\n\"build\",\n\"bulb\",\n\"bulk\",\n\"bullet\",\n\"bundle\",\n\"bunker\",\n\"burden\",\n\"burger\",\n\"burst\",\n\"bus\",\n\"business\",\n\"busy\",\n\"butter\",\n\"buyer\",\n\"buzz\",\n\"cabbage\",\n\"cabin\",\n\"cable\",\n\"cactus\",\n\"cage\",\n\"cake\",\n\"call\",\n\"calm\",\n\"camera\",\n\"camp\",\n\"can\",\n\"canal\",\n\"cancel\",\n\"candy\",\n\"cannon\",\n\"canoe\",\n\"canvas\",\n\"canyon\",\n\"capable\",\n\"capital\",\n\"captain\",\n\"car\",\n\"carbon\",\n\"card\",\n\"cargo\",\n\"carpet\",\n\"carry\",\n\"cart\",\n\"case\",\n\"cash\",\n\"casino\",\n\"castle\",\n\"casual\",\n\"cat\",\n\"catalog\",\n\"catch\",\n\"category\",\n\"cattle\",\n\"caught\",\n\"cause\",\n\"caution\",\n\"cave\",\n\"ceiling\",\n\"celery\",\n\"cement\",\n\"census\",\n\"century\",\n\"cereal\",\n\"certain\",\n\"chair\",\n\"chalk\",\n\"champion\",\n\"change\",\n\"chaos\",\n\"chapter\",\n\"charge\",\n\"chase\",\n\"chat\",\n\"cheap\",\n\"check\",\n\"cheese\",\n\"chef\",\n\"cherry\",\n\"chest\",\n\"chicken\",\n\"chief\",\n\"child\",\n\"chimney\",\n\"choice\",\n\"choose\",\n\"chronic\",\n\"chuckle\",\n\"chunk\",\n\"churn\",\n\"cigar\",\n\"cinnamon\",\n\"circle\",\n\"citizen\",\n\"city\",\n\"civil\",\n\"claim\",\n\"clap\",\n\"clarify\",\n\"claw\",\n\"clay\",\n\"clean\",\n\"clerk\",\n\"clever\",\n\"click\",\n\"client\",\n\"cliff\",\n\"climb\",\n\"clinic\",\n\"clip\",\n\"clock\",\n\"clog\",\n\"close\",\n\"cloth\",\n\"cloud\",\n\"clown\",\n\"club\",\n\"clump\",\n\"cluster\",\n\"clutch\",\n\"coach\",\n\"coast\",\n\"coconut\",\n\"code\",\n\"coffee\",\n\"coil\",\n\"coin\",\n\"collect\",\n\"color\",\n\"column\",\n\"combine\",\n\"come\",\n\"comfort\",\n\"comic\",\n\"common\",\n\"company\",\n\"concert\",\n\"conduct\",\n\"confirm\",\n\"congress\",\n\"connect\",\n\"consider\",\n\"control\",\n\"convince\",\n\"cook\",\n\"cool\",\n\"copper\",\n\"copy\",\n\"coral\",\n\"core\",\n\"corn\",\n\"correct\",\n\"cost\",\n\"cotton\",\n\"couch\",\n\"country\",\n\"couple\",\n\"course\",\n\"cousin\",\n\"cover\",\n\"coyote\",\n\"crack\",\n\"cradle\",\n\"craft\",\n\"cram\",\n\"crane\",\n\"crash\",\n\"crater\",\n\"crawl\",\n\"crazy\",\n\"cream\",\n\"credit\",\n\"creek\",\n\"crew\",\n\"cricket\",\n\"crime\",\n\"crisp\",\n\"critic\",\n\"crop\",\n\"cross\",\n\"crouch\",\n\"crowd\",\n\"crucial\",\n\"cruel\",\n\"cruise\",\n\"crumble\",\n\"crunch\",\n\"crush\",\n\"cry\",\n\"crystal\",\n\"cube\",\n\"culture\",\n\"cup\",\n\"cupboard\",\n\"curious\",\n\"current\",\n\"curtain\",\n\"curve\",\n\"cushion\",\n\"custom\",\n\"cute\",\n\"cycle\",\n\"dad\",\n\"damage\",\n\"damp\",\n\"dance\",\n\"danger\",\n\"daring\",\n\"dash\",\n\"daughter\",\n\"dawn\",\n\"day\",\n\"deal\",\n\"debate\",\n\"debris\",\n\"decade\",\n\"december\",\n\"decide\",\n\"decline\",\n\"decorate\",\n\"decrease\",\n\"deer\",\n\"defense\",\n\"define\",\n\"defy\",\n\"degree\",\n\"delay\",\n\"deliver\",\n\"demand\",\n\"demise\",\n\"denial\",\n\"dentist\",\n\"deny\",\n\"depart\",\n\"depend\",\n\"deposit\",\n\"depth\",\n\"deputy\",\n\"derive\",\n\"describe\",\n\"desert\",\n\"design\",\n\"desk\",\n\"despair\",\n\"destroy\",\n\"detail\",\n\"detect\",\n\"develop\",\n\"device\",\n\"devote\",\n\"diagram\",\n\"dial\",\n\"diamond\",\n\"diary\",\n\"dice\",\n\"diesel\",\n\"diet\",\n\"differ\",\n\"digital\",\n\"dignity\",\n\"dilemma\",\n\"dinner\",\n\"dinosaur\",\n\"direct\",\n\"dirt\",\n\"disagree\",\n\"discover\",\n\"disease\",\n\"dish\",\n\"dismiss\",\n\"disorder\",\n\"display\",\n\"distance\",\n\"divert\",\n\"divide\",\n\"divorce\",\n\"dizzy\",\n\"doctor\",\n\"document\",\n\"dog\",\n\"doll\",\n\"dolphin\",\n\"domain\",\n\"donate\",\n\"donkey\",\n\"donor\",\n\"door\",\n\"dose\",\n\"double\",\n\"dove\",\n\"draft\",\n\"dragon\",\n\"drama\",\n\"drastic\",\n\"draw\",\n\"dream\",\n\"dress\",\n\"drift\",\n\"drill\",\n\"drink\",\n\"drip\",\n\"drive\",\n\"drop\",\n\"drum\",\n\"dry\",\n\"duck\",\n\"dumb\",\n\"dune\",\n\"during\",\n\"dust\",\n\"dutch\",\n\"duty\",\n\"dwarf\",\n\"dynamic\",\n\"eager\",\n\"eagle\",\n\"early\",\n\"earn\",\n\"earth\",\n\"easily\",\n\"east\",\n\"easy\",\n\"echo\",\n\"ecology\",\n\"economy\",\n\"edge\",\n\"edit\",\n\"educate\",\n\"effort\",\n\"egg\",\n\"eight\",\n\"either\",\n\"elbow\",\n\"elder\",\n\"electric\",\n\"elegant\",\n\"element\",\n\"elephant\",\n\"elevator\",\n\"elite\",\n\"else\",\n\"embark\",\n\"embody\",\n\"embrace\",\n\"emerge\",\n\"emotion\",\n\"employ\",\n\"empower\",\n\"empty\",\n\"enable\",\n\"enact\",\n\"end\",\n\"endless\",\n\"endorse\",\n\"enemy\",\n\"energy\",\n\"enforce\",\n\"engage\",\n\"engine\",\n\"enhance\",\n\"enjoy\",\n\"enlist\",\n\"enough\",\n\"enrich\",\n\"enroll\",\n\"ensure\",\n\"enter\",\n\"entire\",\n\"entry\",\n\"envelope\",\n\"episode\",\n\"equal\",\n\"equip\",\n\"era\",\n\"erase\",\n\"erode\",\n\"erosion\",\n\"error\",\n\"erupt\",\n\"escape\",\n\"essay\",\n\"essence\",\n\"estate\",\n\"eternal\",\n\"ethics\",\n\"evidence\",\n\"evil\",\n\"evoke\",\n\"evolve\",\n\"exact\",\n\"example\",\n\"excess\",\n\"exchange\",\n\"excite\",\n\"exclude\",\n\"excuse\",\n\"execute\",\n\"exercise\",\n\"exhaust\",\n\"exhibit\",\n\"exile\",\n\"exist\",\n\"exit\",\n\"exotic\",\n\"expand\",\n\"expect\",\n\"expire\",\n\"explain\",\n\"expose\",\n\"express\",\n\"extend\",\n\"extra\",\n\"eye\",\n\"eyebrow\",\n\"fabric\",\n\"face\",\n\"faculty\",\n\"fade\",\n\"faint\",\n\"faith\",\n\"fall\",\n\"false\",\n\"fame\",\n\"family\",\n\"famous\",\n\"fan\",\n\"fancy\",\n\"fantasy\",\n\"farm\",\n\"fashion\",\n\"fat\",\n\"fatal\",\n\"father\",\n\"fatigue\",\n\"fault\",\n\"favorite\",\n\"feature\",\n\"february\",\n\"federal\",\n\"fee\",\n\"feed\",\n\"feel\",\n\"female\",\n\"fence\",\n\"festival\",\n\"fetch\",\n\"fever\",\n\"few\",\n\"fiber\",\n\"fiction\",\n\"field\",\n\"figure\",\n\"file\",\n\"film\",\n\"filter\",\n\"final\",\n\"find\",\n\"fine\",\n\"finger\",\n\"finish\",\n\"fire\",\n\"firm\",\n\"first\",\n\"fiscal\",\n\"fish\",\n\"fit\",\n\"fitness\",\n\"fix\",\n\"flag\",\n\"flame\",\n\"flash\",\n\"flat\",\n\"flavor\",\n\"flee\",\n\"flight\",\n\"flip\",\n\"float\",\n\"flock\",\n\"floor\",\n\"flower\",\n\"fluid\",\n\"flush\",\n\"fly\",\n\"foam\",\n\"focus\",\n\"fog\",\n\"foil\",\n\"fold\",\n\"follow\",\n\"food\",\n\"foot\",\n\"force\",\n\"forest\",\n\"forget\",\n\"fork\",\n\"fortune\",\n\"forum\",\n\"forward\",\n\"fossil\",\n\"foster\",\n\"found\",\n\"fox\",\n\"fragile\",\n\"frame\",\n\"frequent\",\n\"fresh\",\n\"friend\",\n\"fringe\",\n\"frog\",\n\"front\",\n\"frost\",\n\"frown\",\n\"frozen\",\n\"fruit\",\n\"fuel\",\n\"fun\",\n\"funny\",\n\"furnace\",\n\"fury\",\n\"future\",\n\"gadget\",\n\"gain\",\n\"galaxy\",\n\"gallery\",\n\"game\",\n\"gap\",\n\"garage\",\n\"garbage\",\n\"garden\",\n\"garlic\",\n\"garment\",\n\"gas\",\n\"gasp\",\n\"gate\",\n\"gather\",\n\"gauge\",\n\"gaze\",\n\"general\",\n\"genius\",\n\"genre\",\n\"gentle\",\n\"genuine\",\n\"gesture\",\n\"ghost\",\n\"giant\",\n\"gift\",\n\"giggle\",\n\"ginger\",\n\"giraffe\",\n\"girl\",\n\"give\",\n\"glad\",\n\"glance\",\n\"glare\",\n\"glass\",\n\"glide\",\n\"glimpse\",\n\"globe\",\n\"gloom\",\n\"glory\",\n\"glove\",\n\"glow\",\n\"glue\",\n\"goat\",\n\"goddess\",\n\"gold\",\n\"good\",\n\"goose\",\n\"gorilla\",\n\"gospel\",\n\"gossip\",\n\"govern\",\n\"gown\",\n\"grab\",\n\"grace\",\n\"grain\",\n\"grant\",\n\"grape\",\n\"grass\",\n\"gravity\",\n\"great\",\n\"green\",\n\"grid\",\n\"grief\",\n\"grit\",\n\"grocery\",\n\"group\",\n\"grow\",\n\"grunt\",\n\"guard\",\n\"guess\",\n\"guide\",\n\"guilt\",\n\"guitar\",\n\"gun\",\n\"gym\",\n\"habit\",\n\"hair\",\n\"half\",\n\"hammer\",\n\"hamster\",\n\"hand\",\n\"happy\",\n\"harbor\",\n\"hard\",\n\"harsh\",\n\"harvest\",\n\"hat\",\n\"have\",\n\"hawk\",\n\"hazard\",\n\"head\",\n\"health\",\n\"heart\",\n\"heavy\",\n\"hedgehog\",\n\"height\",\n\"hello\",\n\"helmet\",\n\"help\",\n\"hen\",\n\"hero\",\n\"hidden\",\n\"high\",\n\"hill\",\n\"hint\",\n\"hip\",\n\"hire\",\n\"history\",\n\"hobby\",\n\"hockey\",\n\"hold\",\n\"hole\",\n\"holiday\",\n\"hollow\",\n\"home\",\n\"honey\",\n\"hood\",\n\"hope\",\n\"horn\",\n\"horror\",\n\"horse\",\n\"hospital\",\n\"host\",\n\"hotel\",\n\"hour\",\n\"hover\",\n\"hub\",\n\"huge\",\n\"human\",\n\"humble\",\n\"humor\",\n\"hundred\",\n\"hungry\",\n\"hunt\",\n\"hurdle\",\n\"hurry\",\n\"hurt\",\n\"husband\",\n\"hybrid\",\n\"ice\",\n\"icon\",\n\"idea\",\n\"identify\",\n\"idle\",\n\"ignore\",\n\"ill\",\n\"illegal\",\n\"illness\",\n\"image\",\n\"imitate\",\n\"immense\",\n\"immune\",\n\"impact\",\n\"impose\",\n\"improve\",\n\"impulse\",\n\"inch\",\n\"include\",\n\"income\",\n\"increase\",\n\"index\",\n\"indicate\",\n\"indoor\",\n\"industry\",\n\"infant\",\n\"inflict\",\n\"inform\",\n\"inhale\",\n\"inherit\",\n\"initial\",\n\"inject\",\n\"injury\",\n\"inmate\",\n\"inner\",\n\"innocent\",\n\"input\",\n\"inquiry\",\n\"insane\",\n\"insect\",\n\"inside\",\n\"inspire\",\n\"install\",\n\"intact\",\n\"interest\",\n\"into\",\n\"invest\",\n\"invite\",\n\"involve\",\n\"iron\",\n\"island\",\n\"isolate\",\n\"issue\",\n\"item\",\n\"ivory\",\n\"jacket\",\n\"jaguar\",\n\"jar\",\n\"jazz\",\n\"jealous\",\n\"jeans\",\n\"jelly\",\n\"jewel\",\n\"job\",\n\"join\",\n\"joke\",\n\"journey\",\n\"joy\",\n\"judge\",\n\"juice\",\n\"jump\",\n\"jungle\",\n\"junior\",\n\"junk\",\n\"just\",\n\"kangaroo\",\n\"keen\",\n\"keep\",\n\"ketchup\",\n\"key\",\n\"kick\",\n\"kid\",\n\"kidney\",\n\"kind\",\n\"kingdom\",\n\"kiss\",\n\"kit\",\n\"kitchen\",\n\"kite\",\n\"kitten\",\n\"kiwi\",\n\"knee\",\n\"knife\",\n\"knock\",\n\"know\",\n\"lab\",\n\"label\",\n\"labor\",\n\"ladder\",\n\"lady\",\n\"lake\",\n\"lamp\",\n\"language\",\n\"laptop\",\n\"large\",\n\"later\",\n\"latin\",\n\"laugh\",\n\"laundry\",\n\"lava\",\n\"law\",\n\"lawn\",\n\"lawsuit\",\n\"layer\",\n\"lazy\",\n\"leader\",\n\"leaf\",\n\"learn\",\n\"leave\",\n\"lecture\",\n\"left\",\n\"leg\",\n\"legal\",\n\"legend\",\n\"leisure\",\n\"lemon\",\n\"lend\",\n\"length\",\n\"lens\",\n\"leopard\",\n\"lesson\",\n\"letter\",\n\"level\",\n\"liar\",\n\"liberty\",\n\"library\",\n\"license\",\n\"life\",\n\"lift\",\n\"light\",\n\"like\",\n\"limb\",\n\"limit\",\n\"link\",\n\"lion\",\n\"liquid\",\n\"list\",\n\"little\",\n\"live\",\n\"lizard\",\n\"load\",\n\"loan\",\n\"lobster\",\n\"local\",\n\"lock\",\n\"logic\",\n\"lonely\",\n\"long\",\n\"loop\",\n\"lottery\",\n\"loud\",\n\"lounge\",\n\"love\",\n\"loyal\",\n\"lucky\",\n\"luggage\",\n\"lumber\",\n\"lunar\",\n\"lunch\",\n\"luxury\",\n\"lyrics\",\n\"machine\",\n\"mad\",\n\"magic\",\n\"magnet\",\n\"maid\",\n\"mail\",\n\"main\",\n\"major\",\n\"make\",\n\"mammal\",\n\"man\",\n\"manage\",\n\"mandate\",\n\"mango\",\n\"mansion\",\n\"manual\",\n\"maple\",\n\"marble\",\n\"march\",\n\"margin\",\n\"marine\",\n\"market\",\n\"marriage\",\n\"mask\",\n\"mass\",\n\"master\",\n\"match\",\n\"material\",\n\"math\",\n\"matrix\",\n\"matter\",\n\"maximum\",\n\"maze\",\n\"meadow\",\n\"mean\",\n\"measure\",\n\"meat\",\n\"mechanic\",\n\"medal\",\n\"media\",\n\"melody\",\n\"melt\",\n\"member\",\n\"memory\",\n\"mention\",\n\"menu\",\n\"mercy\",\n\"merge\",\n\"merit\",\n\"merry\",\n\"mesh\",\n\"message\",\n\"metal\",\n\"method\",\n\"middle\",\n\"midnight\",\n\"milk\",\n\"million\",\n\"mimic\",\n\"mind\",\n\"minimum\",\n\"minor\",\n\"minute\",\n\"miracle\",\n\"mirror\",\n\"misery\",\n\"miss\",\n\"mistake\",\n\"mix\",\n\"mixed\",\n\"mixture\",\n\"mobile\",\n\"model\",\n\"modify\",\n\"mom\",\n\"moment\",\n\"monitor\",\n\"monkey\",\n\"monster\",\n\"month\",\n\"moon\",\n\"moral\",\n\"more\",\n\"morning\",\n\"mosquito\",\n\"mother\",\n\"motion\",\n\"motor\",\n\"mountain\",\n\"mouse\",\n\"move\",\n\"movie\",\n\"much\",\n\"muffin\",\n\"mule\",\n\"multiply\",\n\"muscle\",\n\"museum\",\n\"mushroom\",\n\"music\",\n\"must\",\n\"mutual\",\n\"myself\",\n\"mystery\",\n\"myth\",\n\"naive\",\n\"name\",\n\"napkin\",\n\"narrow\",\n\"nasty\",\n\"nation\",\n\"nature\",\n\"near\",\n\"neck\",\n\"need\",\n\"negative\",\n\"neglect\",\n\"neither\",\n\"nephew\",\n\"nerve\",\n\"nest\",\n\"net\",\n\"network\",\n\"neutral\",\n\"never\",\n\"news\",\n\"next\",\n\"nice\",\n\"night\",\n\"noble\",\n\"noise\",\n\"nominee\",\n\"noodle\",\n\"normal\",\n\"north\",\n\"nose\",\n\"notable\",\n\"note\",\n\"nothing\",\n\"notice\",\n\"novel\",\n\"now\",\n\"nuclear\",\n\"number\",\n\"nurse\",\n\"nut\",\n\"oak\",\n\"obey\",\n\"object\",\n\"oblige\",\n\"obscure\",\n\"observe\",\n\"obtain\",\n\"obvious\",\n\"occur\",\n\"ocean\",\n\"october\",\n\"odor\",\n\"off\",\n\"offer\",\n\"office\",\n\"often\",\n\"oil\",\n\"okay\",\n\"old\",\n\"olive\",\n\"olympic\",\n\"omit\",\n\"once\",\n\"one\",\n\"onion\",\n\"online\",\n\"only\",\n\"open\",\n\"opera\",\n\"opinion\",\n\"oppose\",\n\"option\",\n\"orange\",\n\"orbit\",\n\"orchard\",\n\"order\",\n\"ordinary\",\n\"organ\",\n\"orient\",\n\"original\",\n\"orphan\",\n\"ostrich\",\n\"other\",\n\"outdoor\",\n\"outer\",\n\"output\",\n\"outside\",\n\"oval\",\n\"oven\",\n\"over\",\n\"own\",\n\"owner\",\n\"oxygen\",\n\"oyster\",\n\"ozone\",\n\"pact\",\n\"paddle\",\n\"page\",\n\"pair\",\n\"palace\",\n\"palm\",\n\"panda\",\n\"panel\",\n\"panic\",\n\"panther\",\n\"paper\",\n\"parade\",\n\"parent\",\n\"park\",\n\"parrot\",\n\"party\",\n\"pass\",\n\"patch\",\n\"path\",\n\"patient\",\n\"patrol\",\n\"pattern\",\n\"pause\",\n\"pave\",\n\"payment\",\n\"peace\",\n\"peanut\",\n\"pear\",\n\"peasant\",\n\"pelican\",\n\"pen\",\n\"penalty\",\n\"pencil\",\n\"people\",\n\"pepper\",\n\"perfect\",\n\"permit\",\n\"person\",\n\"pet\",\n\"phone\",\n\"photo\",\n\"phrase\",\n\"physical\",\n\"piano\",\n\"picnic\",\n\"picture\",\n\"piece\",\n\"pig\",\n\"pigeon\",\n\"pill\",\n\"pilot\",\n\"pink\",\n\"pioneer\",\n\"pipe\",\n\"pistol\",\n\"pitch\",\n\"pizza\",\n\"place\",\n\"planet\",\n\"plastic\",\n\"plate\",\n\"play\",\n\"please\",\n\"pledge\",\n\"pluck\",\n\"plug\",\n\"plunge\",\n\"poem\",\n\"poet\",\n\"point\",\n\"polar\",\n\"pole\",\n\"police\",\n\"pond\",\n\"pony\",\n\"pool\",\n\"popular\",\n\"portion\",\n\"position\",\n\"possible\",\n\"post\",\n\"potato\",\n\"pottery\",\n\"poverty\",\n\"powder\",\n\"power\",\n\"practice\",\n\"praise\",\n\"predict\",\n\"prefer\",\n\"prepare\",\n\"present\",\n\"pretty\",\n\"prevent\",\n\"price\",\n\"pride\",\n\"primary\",\n\"print\",\n\"priority\",\n\"prison\",\n\"private\",\n\"prize\",\n\"problem\",\n\"process\",\n\"produce\",\n\"profit\",\n\"program\",\n\"project\",\n\"promote\",\n\"proof\",\n\"property\",\n\"prosper\",\n\"protect\",\n\"proud\",\n\"provide\",\n\"public\",\n\"pudding\",\n\"pull\",\n\"pulp\",\n\"pulse\",\n\"pumpkin\",\n\"punch\",\n\"pupil\",\n\"puppy\",\n\"purchase\",\n\"purity\",\n\"purpose\",\n\"purse\",\n\"push\",\n\"put\",\n\"puzzle\",\n\"pyramid\",\n\"quality\",\n\"quantum\",\n\"quarter\",\n\"question\",\n\"quick\",\n\"quit\",\n\"quiz\",\n\"quote\",\n\"rabbit\",\n\"raccoon\",\n\"race\",\n\"rack\",\n\"radar\",\n\"radio\",\n\"rail\",\n\"rain\",\n\"raise\",\n\"rally\",\n\"ramp\",\n\"ranch\",\n\"random\",\n\"range\",\n\"rapid\",\n\"rare\",\n\"rate\",\n\"rather\",\n\"raven\",\n\"raw\",\n\"razor\",\n\"ready\",\n\"real\",\n\"reason\",\n\"rebel\",\n\"rebuild\",\n\"recall\",\n\"receive\",\n\"recipe\",\n\"record\",\n\"recycle\",\n\"reduce\",\n\"reflect\",\n\"reform\",\n\"refuse\",\n\"region\",\n\"regret\",\n\"regular\",\n\"reject\",\n\"relax\",\n\"release\",\n\"relief\",\n\"rely\",\n\"remain\",\n\"remember\",\n\"remind\",\n\"remove\",\n\"render\",\n\"renew\",\n\"rent\",\n\"reopen\",\n\"repair\",\n\"repeat\",\n\"replace\",\n\"report\",\n\"require\",\n\"rescue\",\n\"resemble\",\n\"resist\",\n\"resource\",\n\"response\",\n\"result\",\n\"retire\",\n\"retreat\",\n\"return\",\n\"reunion\",\n\"reveal\",\n\"review\",\n\"reward\",\n\"rhythm\",\n\"rib\",\n\"ribbon\",\n\"rice\",\n\"rich\",\n\"ride\",\n\"ridge\",\n\"rifle\",\n\"right\",\n\"rigid\",\n\"ring\",\n\"riot\",\n\"ripple\",\n\"risk\",\n\"ritual\",\n\"rival\",\n\"river\",\n\"road\",\n\"roast\",\n\"robot\",\n\"robust\",\n\"rocket\",\n\"romance\",\n\"roof\",\n\"rookie\",\n\"room\",\n\"rose\",\n\"rotate\",\n\"rough\",\n\"round\",\n\"route\",\n\"royal\",\n\"rubber\",\n\"rude\",\n\"rug\",\n\"rule\",\n\"run\",\n\"runway\",\n\"rural\",\n\"sad\",\n\"saddle\",\n\"sadness\",\n\"safe\",\n\"sail\",\n\"salad\",\n\"salmon\",\n\"salon\",\n\"salt\",\n\"salute\",\n\"same\",\n\"sample\",\n\"sand\",\n\"satisfy\",\n\"satoshi\",\n\"sauce\",\n\"sausage\",\n\"save\",\n\"say\",\n\"scale\",\n\"scan\",\n\"scare\",\n\"scatter\",\n\"scene\",\n\"scheme\",\n\"school\",\n\"science\",\n\"scissors\",\n\"scorpion\",\n\"scout\",\n\"scrap\",\n\"screen\",\n\"script\",\n\"scrub\",\n\"sea\",\n\"search\",\n\"season\",\n\"seat\",\n\"second\",\n\"secret\",\n\"section\",\n\"security\",\n\"seed\",\n\"seek\",\n\"segment\",\n\"select\",\n\"sell\",\n\"seminar\",\n\"senior\",\n\"sense\",\n\"sentence\",\n\"series\",\n\"service\",\n\"session\",\n\"settle\",\n\"setup\",\n\"seven\",\n\"shadow\",\n\"shaft\",\n\"shallow\",\n\"share\",\n\"shed\",\n\"shell\",\n\"sheriff\",\n\"shield\",\n\"shift\",\n\"shine\",\n\"ship\",\n\"shiver\",\n\"shock\",\n\"shoe\",\n\"shoot\",\n\"shop\",\n\"short\",\n\"shoulder\",\n\"shove\",\n\"shrimp\",\n\"shrug\",\n\"shuffle\",\n\"shy\",\n\"sibling\",\n\"sick\",\n\"side\",\n\"siege\",\n\"sight\",\n\"sign\",\n\"silent\",\n\"silk\",\n\"silly\",\n\"silver\",\n\"similar\",\n\"simple\",\n\"since\",\n\"sing\",\n\"siren\",\n\"sister\",\n\"situate\",\n\"six\",\n\"size\",\n\"skate\",\n\"sketch\",\n\"ski\",\n\"skill\",\n\"skin\",\n\"skirt\",\n\"skull\",\n\"slab\",\n\"slam\",\n\"sleep\",\n\"slender\",\n\"slice\",\n\"slide\",\n\"slight\",\n\"slim\",\n\"slogan\",\n\"slot\",\n\"slow\",\n\"slush\",\n\"small\",\n\"smart\",\n\"smile\",\n\"smoke\",\n\"smooth\",\n\"snack\",\n\"snake\",\n\"snap\",\n\"sniff\",\n\"snow\",\n\"soap\",\n\"soccer\",\n\"social\",\n\"sock\",\n\"soda\",\n\"soft\",\n\"solar\",\n\"soldier\",\n\"solid\",\n\"solution\",\n\"solve\",\n\"someone\",\n\"song\",\n\"soon\",\n\"sorry\",\n\"sort\",\n\"soul\",\n\"sound\",\n\"soup\",\n\"source\",\n\"south\",\n\"space\",\n\"spare\",\n\"spatial\",\n\"spawn\",\n\"speak\",\n\"special\",\n\"speed\",\n\"spell\",\n\"spend\",\n\"sphere\",\n\"spice\",\n\"spider\",\n\"spike\",\n\"spin\",\n\"spirit\",\n\"split\",\n\"spoil\",\n\"sponsor\",\n\"spoon\",\n\"sport\",\n\"spot\",\n\"spray\",\n\"spread\",\n\"spring\",\n\"spy\",\n\"square\",\n\"squeeze\",\n\"squirrel\",\n\"stable\",\n\"stadium\",\n\"staff\",\n\"stage\",\n\"stairs\",\n\"stamp\",\n\"stand\",\n\"start\",\n\"state\",\n\"stay\",\n\"steak\",\n\"steel\",\n\"stem\",\n\"step\",\n\"stereo\",\n\"stick\",\n\"still\",\n\"sting\",\n\"stock\",\n\"stomach\",\n\"stone\",\n\"stool\",\n\"story\",\n\"stove\",\n\"strategy\",\n\"street\",\n\"strike\",\n\"strong\",\n\"struggle\",\n\"student\",\n\"stuff\",\n\"stumble\",\n\"style\",\n\"subject\",\n\"submit\",\n\"subway\",\n\"success\",\n\"such\",\n\"sudden\",\n\"suffer\",\n\"sugar\",\n\"suggest\",\n\"suit\",\n\"summer\",\n\"sun\",\n\"sunny\",\n\"sunset\",\n\"super\",\n\"supply\",\n\"supreme\",\n\"sure\",\n\"surface\",\n\"surge\",\n\"surprise\",\n\"surround\",\n\"survey\",\n\"suspect\",\n\"sustain\",\n\"swallow\",\n\"swamp\",\n\"swap\",\n\"swarm\",\n\"swear\",\n\"sweet\",\n\"swift\",\n\"swim\",\n\"swing\",\n\"switch\",\n\"sword\",\n\"symbol\",\n\"symptom\",\n\"syrup\",\n\"system\",\n\"table\",\n\"tackle\",\n\"tag\",\n\"tail\",\n\"talent\",\n\"talk\",\n\"tank\",\n\"tape\",\n\"target\",\n\"task\",\n\"taste\",\n\"tattoo\",\n\"taxi\",\n\"teach\",\n\"team\",\n\"tell\",\n\"ten\",\n\"tenant\",\n\"tennis\",\n\"tent\",\n\"term\",\n\"test\",\n\"text\",\n\"thank\",\n\"that\",\n\"theme\",\n\"then\",\n\"theory\",\n\"there\",\n\"they\",\n\"thing\",\n\"this\",\n\"thought\",\n\"three\",\n\"thrive\",\n\"throw\",\n\"thumb\",\n\"thunder\",\n\"ticket\",\n\"tide\",\n\"tiger\",\n\"tilt\",\n\"timber\",\n\"time\",\n\"tiny\",\n\"tip\",\n\"tired\",\n\"tissue\",\n\"title\",\n\"toast\",\n\"tobacco\",\n\"today\",\n\"toddler\",\n\"toe\",\n\"together\",\n\"toilet\",\n\"token\",\n\"tomato\",\n\"tomorrow\",\n\"tone\",\n\"tongue\",\n\"tonight\",\n\"tool\",\n\"tooth\",\n\"top\",\n\"topic\",\n\"topple\",\n\"torch\",\n\"tornado\",\n\"tortoise\",\n\"toss\",\n\"total\",\n\"tourist\",\n\"toward\",\n\"tower\",\n\"town\",\n\"toy\",\n\"track\",\n\"trade\",\n\"traffic\",\n\"tragic\",\n\"train\",\n\"transfer\",\n\"trap\",\n\"trash\",\n\"travel\",\n\"tray\",\n\"treat\",\n\"tree\",\n\"trend\",\n\"trial\",\n\"tribe\",\n\"trick\",\n\"trigger\",\n\"trim\",\n\"trip\",\n\"trophy\",\n\"trouble\",\n\"truck\",\n\"true\",\n\"truly\",\n\"trumpet\",\n\"trust\",\n\"truth\",\n\"try\",\n\"tube\",\n\"tuition\",\n\"tumble\",\n\"tuna\",\n\"tunnel\",\n\"turkey\",\n\"turn\",\n\"turtle\",\n\"twelve\",\n\"twenty\",\n\"twice\",\n\"twin\",\n\"twist\",\n\"two\",\n\"type\",\n\"typical\",\n\"ugly\",\n\"umbrella\",\n\"unable\",\n\"unaware\",\n\"uncle\",\n\"uncover\",\n\"under\",\n\"undo\",\n\"unfair\",\n\"unfold\",\n\"unhappy\",\n\"uniform\",\n\"unique\",\n\"unit\",\n\"universe\",\n\"unknown\",\n\"unlock\",\n\"until\",\n\"unusual\",\n\"unveil\",\n\"update\",\n\"upgrade\",\n\"uphold\",\n\"upon\",\n\"upper\",\n\"upset\",\n\"urban\",\n\"urge\",\n\"usage\",\n\"use\",\n\"used\",\n\"useful\",\n\"useless\",\n\"usual\",\n\"utility\",\n\"vacant\",\n\"vacuum\",\n\"vague\",\n\"valid\",\n\"valley\",\n\"valve\",\n\"van\",\n\"vanish\",\n\"vapor\",\n\"various\",\n\"vast\",\n\"vault\",\n\"vehicle\",\n\"velvet\",\n\"vendor\",\n\"venture\",\n\"venue\",\n\"verb\",\n\"verify\",\n\"version\",\n\"very\",\n\"vessel\",\n\"veteran\",\n\"viable\",\n\"vibrant\",\n\"vicious\",\n\"victory\",\n\"video\",\n\"view\",\n\"village\",\n\"vintage\",\n\"violin\",\n\"virtual\",\n\"virus\",\n\"visa\",\n\"visit\",\n\"visual\",\n\"vital\",\n\"vivid\",\n\"vocal\",\n\"voice\",\n\"void\",\n\"volcano\",\n\"volume\",\n\"vote\",\n\"voyage\",\n\"wage\",\n\"wagon\",\n\"wait\",\n\"walk\",\n\"wall\",\n\"walnut\",\n\"want\",\n\"warfare\",\n\"warm\",\n\"warrior\",\n\"wash\",\n\"wasp\",\n\"waste\",\n\"water\",\n\"wave\",\n\"way\",\n\"wealth\",\n\"weapon\",\n\"wear\",\n\"weasel\",\n\"weather\",\n\"web\",\n\"wedding\",\n\"weekend\",\n\"weird\",\n\"welcome\",\n\"west\",\n\"wet\",\n\"whale\",\n\"what\",\n\"wheat\",\n\"wheel\",\n\"when\",\n\"where\",\n\"whip\",\n\"whisper\",\n\"wide\",\n\"width\",\n\"wife\",\n\"wild\",\n\"will\",\n\"win\",\n\"window\",\n\"wine\",\n\"wing\",\n\"wink\",\n\"winner\",\n\"winter\",\n\"wire\",\n\"wisdom\",\n\"wise\",\n\"wish\",\n\"witness\",\n\"wolf\",\n\"woman\",\n\"wonder\",\n\"wood\",\n\"wool\",\n\"word\",\n\"work\",\n\"world\",\n\"worry\",\n\"worth\",\n\"wrap\",\n\"wreck\",\n\"wrestle\",\n\"wrist\",\n\"write\",\n\"wrong\",\n\"yard\",\n\"year\",\n\"yellow\",\n\"you\",\n\"young\",\n\"youth\",\n\"zebra\",\n\"zero\",\n\"zone\",\n\"zoo\",\n0,\n};\n"
  },
  {
    "path": "src/utility/trezor/ecdsa.c",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n * Copyright (c)      2015 Jochen Hoenicke\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"address.h\"\n#include \"bignum.h\"\n#include \"rand.h\"\n#include \"hmac.h\"\n#include \"ecdsa.h\"\n#include \"base58.h\"\n#include \"secp256k1.h\"\n#include \"rfc6979.h\"\n#include \"memzero.h\"\n\n// Set cp2 = cp1\nvoid point_copy(const curve_point *cp1, curve_point *cp2)\n{\n\t*cp2 = *cp1;\n}\n\n// cp2 = cp1 + cp2\nvoid point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2)\n{\n\tbignum256 lambda, inv, xr, yr;\n\n\tif (point_is_infinity(cp1)) {\n\t\treturn;\n\t}\n\tif (point_is_infinity(cp2)) {\n\t\tpoint_copy(cp1, cp2);\n\t\treturn;\n\t}\n\tif (point_is_equal(cp1, cp2)) {\n\t\tpoint_double(curve, cp2);\n\t\treturn;\n\t}\n\tif (point_is_negative_of(cp1, cp2)) {\n\t\tpoint_set_infinity(cp2);\n\t\treturn;\n\t}\n\n\tbn_subtractmod(&(cp2->x), &(cp1->x), &inv, &curve->prime);\n\tbn_inverse(&inv, &curve->prime);\n\tbn_subtractmod(&(cp2->y), &(cp1->y), &lambda, &curve->prime);\n\tbn_multiply(&inv, &lambda, &curve->prime);\n\n\t// xr = lambda^2 - x1 - x2\n\txr = lambda;\n\tbn_multiply(&xr, &xr, &curve->prime);\n\tyr = cp1->x;\n\tbn_addmod(&yr, &(cp2->x), &curve->prime);\n\tbn_subtractmod(&xr, &yr, &xr, &curve->prime);\n\tbn_fast_mod(&xr, &curve->prime);\n\tbn_mod(&xr, &curve->prime);\n\n\t// yr = lambda (x1 - xr) - y1\n\tbn_subtractmod(&(cp1->x), &xr, &yr, &curve->prime);\n\tbn_multiply(&lambda, &yr, &curve->prime);\n\tbn_subtractmod(&yr, &(cp1->y), &yr, &curve->prime);\n\tbn_fast_mod(&yr, &curve->prime);\n\tbn_mod(&yr, &curve->prime);\n\n\tcp2->x = xr;\n\tcp2->y = yr;\n}\n\n// cp = cp + cp\nvoid point_double(const ecdsa_curve *curve, curve_point *cp)\n{\n\tbignum256 lambda, xr, yr;\n\n\tif (point_is_infinity(cp)) {\n\t\treturn;\n\t}\n\tif (bn_is_zero(&(cp->y))) {\n\t\tpoint_set_infinity(cp);\n\t\treturn;\n\t}\n\n\t// lambda = (3 x^2 + a) / (2 y)\n\tlambda = cp->y;\n\tbn_mult_k(&lambda, 2, &curve->prime);\n\tbn_inverse(&lambda, &curve->prime);\n\n\txr = cp->x;\n\tbn_multiply(&xr, &xr, &curve->prime);\n\tbn_mult_k(&xr, 3, &curve->prime);\n\tbn_subi(&xr, -curve->a, &curve->prime);\n\tbn_multiply(&xr, &lambda, &curve->prime);\n\n\t// xr = lambda^2 - 2*x\n\txr = lambda;\n\tbn_multiply(&xr, &xr, &curve->prime);\n\tyr = cp->x;\n\tbn_lshift(&yr);\n\tbn_subtractmod(&xr, &yr, &xr, &curve->prime);\n\tbn_fast_mod(&xr, &curve->prime);\n\tbn_mod(&xr, &curve->prime);\n\n\t// yr = lambda (x - xr) - y\n\tbn_subtractmod(&(cp->x), &xr, &yr, &curve->prime);\n\tbn_multiply(&lambda, &yr, &curve->prime);\n\tbn_subtractmod(&yr, &(cp->y), &yr, &curve->prime);\n\tbn_fast_mod(&yr, &curve->prime);\n\tbn_mod(&yr, &curve->prime);\n\n\tcp->x = xr;\n\tcp->y = yr;\n}\n\n// set point to internal representation of point at infinity\nvoid point_set_infinity(curve_point *p)\n{\n\tbn_zero(&(p->x));\n\tbn_zero(&(p->y));\n}\n\n// return true iff p represent point at infinity\n// both coords are zero in internal representation\nint point_is_infinity(const curve_point *p)\n{\n\treturn bn_is_zero(&(p->x)) && bn_is_zero(&(p->y));\n}\n\n// return true iff both points are equal\nint point_is_equal(const curve_point *p, const curve_point *q)\n{\n\treturn bn_is_equal(&(p->x), &(q->x)) && bn_is_equal(&(p->y), &(q->y));\n}\n\n// returns true iff p == -q\n// expects p and q be valid points on curve other than point at infinity\nint point_is_negative_of(const curve_point *p, const curve_point *q)\n{\n\t// if P == (x, y), then -P would be (x, -y) on this curve\n\tif (!bn_is_equal(&(p->x), &(q->x))) {\n\t\treturn 0;\n\t}\n\n\t// we shouldn't hit this for a valid point\n\tif (bn_is_zero(&(p->y))) {\n\t\treturn 0;\n\t}\n\n\treturn !bn_is_equal(&(p->y), &(q->y));\n}\n\n// Negate a (modulo prime) if cond is 0xffffffff, keep it if cond is 0.\n// The timing of this function does not depend on cond.\nvoid conditional_negate(uint32_t cond, bignum256 *a, const bignum256 *prime)\n{\n\tint j;\n\tuint32_t tmp = 1;\n\tassert(a->val[8] < 0x20000);\n\tfor (j = 0; j < 8; j++) {\n\t\ttmp += 0x3fffffff + 2*prime->val[j] - a->val[j];\n\t\ta->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond);\n\t\ttmp >>= 30;\n\t}\n\ttmp += 0x3fffffff + 2*prime->val[j] - a->val[j];\n\ta->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond);\n\tassert(a->val[8] < 0x20000);\n}\n\ntypedef struct jacobian_curve_point {\n\tbignum256 x, y, z;\n} jacobian_curve_point;\n\n// generate random K for signing/side-channel noise\nstatic void generate_k_random(bignum256 *k, const bignum256 *prime) {\n\tdo {\n\t\tint i;\n\t\tfor (i = 0; i < 8; i++) {\n\t\t\tk->val[i] = random32() & 0x3FFFFFFF;\n\t\t}\n\t\tk->val[8] = random32() & 0xFFFF;\n\t\t// check that k is in range and not zero.\n\t} while (bn_is_zero(k) || !bn_is_less(k, prime));\n}\n\nvoid curve_to_jacobian(const curve_point *p, jacobian_curve_point *jp, const bignum256 *prime) {\n\t// randomize z coordinate\n\tgenerate_k_random(&jp->z, prime);\n\n\tjp->x = jp->z;\n\tbn_multiply(&jp->z, &jp->x, prime);\n\t// x = z^2\n\tjp->y = jp->x;\n\tbn_multiply(&jp->z, &jp->y, prime);\n\t// y = z^3\n\n\tbn_multiply(&p->x, &jp->x, prime);\n\tbn_multiply(&p->y, &jp->y, prime);\n}\n\nvoid jacobian_to_curve(const jacobian_curve_point *jp, curve_point *p, const bignum256 *prime) {\n\tp->y = jp->z;\n\tbn_inverse(&p->y, prime);\n\t// p->y = z^-1\n\tp->x = p->y;\n\tbn_multiply(&p->x, &p->x, prime);\n\t// p->x = z^-2\n\tbn_multiply(&p->x, &p->y, prime);\n\t// p->y = z^-3\n\tbn_multiply(&jp->x, &p->x, prime);\n\t// p->x = jp->x * z^-2\n\tbn_multiply(&jp->y, &p->y, prime);\n\t// p->y = jp->y * z^-3\n\tbn_mod(&p->x, prime);\n\tbn_mod(&p->y, prime);\n}\n\nvoid point_jacobian_add(const curve_point *p1, jacobian_curve_point *p2, const ecdsa_curve *curve) {\n\tbignum256 r, h, r2;\n\tbignum256 hcby, hsqx;\n\tbignum256 xz, yz, az;\n\tint is_doubling;\n\tconst bignum256 *prime = &curve->prime;\n\tint a = curve->a;\n\n\tassert (-3 <= a && a <= 0);\n\n\t/* First we bring p1 to the same denominator:\n\t * x1' := x1 * z2^2\n\t * y1' := y1 * z2^3\n\t */\n\t/*\n\t * lambda  = ((y1' - y2)/z2^3) / ((x1' - x2)/z2^2)\n\t *         = (y1' - y2) / (x1' - x2) z2\n\t * x3/z3^2 = lambda^2 - (x1' + x2)/z2^2\n\t * y3/z3^3 = 1/2 lambda * (2x3/z3^2 - (x1' + x2)/z2^2) + (y1'+y2)/z2^3\n\t *\n\t * For the special case x1=x2, y1=y2 (doubling) we have\n\t * lambda = 3/2 ((x2/z2^2)^2 + a) / (y2/z2^3)\n\t *        = 3/2 (x2^2 + a*z2^4) / y2*z2)\n\t *\n\t * to get rid of fraction we write lambda as\n\t * lambda = r / (h*z2)\n\t * with  r = is_doubling ? 3/2 x2^2 + az2^4 : (y1 - y2)\n\t *       h = is_doubling ?      y1+y2       : (x1 - x2)\n\t *\n\t * With z3 = h*z2  (the denominator of lambda)\n\t * we get x3 = lambda^2*z3^2 - (x1' + x2)/z2^2*z3^2\n\t *           = r^2 - h^2 * (x1' + x2)\n\t *    and y3 = 1/2 r * (2x3 - h^2*(x1' + x2)) + h^3*(y1' + y2)\n\t */\n\n\t/* h = x1 - x2\n\t * r = y1 - y2\n\t * x3 = r^2 - h^3 - 2*h^2*x2\n\t * y3 = r*(h^2*x2 - x3) - h^3*y2\n\t * z3 = h*z2\n\t */\n\n\txz = p2->z;\n\tbn_multiply(&xz, &xz, prime); // xz = z2^2\n\tyz = p2->z;\n\tbn_multiply(&xz, &yz, prime); // yz = z2^3\n\n\tif (a != 0) {\n\t\taz  = xz;\n\t\tbn_multiply(&az, &az, prime);   // az = z2^4\n\t\tbn_mult_k(&az, -a, prime);      // az = -az2^4\n\t}\n\n\tbn_multiply(&p1->x, &xz, prime);        // xz = x1' = x1*z2^2;\n\th = xz;\n\tbn_subtractmod(&h, &p2->x, &h, prime);\n\tbn_fast_mod(&h, prime);\n\t// h = x1' - x2;\n\n\tbn_add(&xz, &p2->x);\n\t// xz = x1' + x2\n\n\t// check for h == 0 % prime.  Note that h never normalizes to\n\t// zero, since h = x1' + 2*prime - x2 > 0 and a positive\n\t// multiple of prime is always normalized to prime by\n\t// bn_fast_mod.\n\tis_doubling = bn_is_equal(&h, prime);\n\n\tbn_multiply(&p1->y, &yz, prime);        // yz = y1' = y1*z2^3;\n\tbn_subtractmod(&yz, &p2->y, &r, prime);\n\t// r = y1' - y2;\n\n\tbn_add(&yz, &p2->y);\n\t// yz = y1' + y2\n\n\tr2 = p2->x;\n\tbn_multiply(&r2, &r2, prime);\n\tbn_mult_k(&r2, 3, prime);\n\n\tif (a != 0) {\n\t\t// subtract -a z2^4, i.e, add a z2^4\n\t\tbn_subtractmod(&r2, &az, &r2, prime);\n\t}\n\tbn_cmov(&r, is_doubling, &r2, &r);\n\tbn_cmov(&h, is_doubling, &yz, &h);\n\n\n\t// hsqx = h^2\n\thsqx = h;\n\tbn_multiply(&hsqx, &hsqx, prime);\n\n\t// hcby = h^3\n\thcby = h;\n\tbn_multiply(&hsqx, &hcby, prime);\n\n\t// hsqx = h^2 * (x1 + x2)\n\tbn_multiply(&xz, &hsqx, prime);\n\n\t// hcby = h^3 * (y1 + y2)\n\tbn_multiply(&yz, &hcby, prime);\n\n\t// z3 = h*z2\n\tbn_multiply(&h, &p2->z, prime);\n\n\t// x3 = r^2 - h^2 (x1 + x2)\n\tp2->x = r;\n\tbn_multiply(&p2->x, &p2->x, prime);\n\tbn_subtractmod(&p2->x, &hsqx, &p2->x, prime);\n\tbn_fast_mod(&p2->x, prime);\n\n\t// y3 = 1/2 (r*(h^2 (x1 + x2) - 2x3) - h^3 (y1 + y2))\n\tbn_subtractmod(&hsqx, &p2->x, &p2->y, prime);\n\tbn_subtractmod(&p2->y, &p2->x, &p2->y, prime);\n\tbn_multiply(&r, &p2->y, prime);\n\tbn_subtractmod(&p2->y, &hcby, &p2->y, prime);\n\tbn_mult_half(&p2->y, prime);\n\tbn_fast_mod(&p2->y, prime);\n}\n\nvoid point_jacobian_double(jacobian_curve_point *p, const ecdsa_curve *curve) {\n\tbignum256 az4, m, msq, ysq, xysq;\n\tconst bignum256 *prime = &curve->prime;\n\n\tassert (-3 <= curve->a && curve->a <= 0);\n\t/* usual algorithm:\n\t *\n\t * lambda  = (3((x/z^2)^2 + a) / 2y/z^3) = (3x^2 + az^4)/2yz\n\t * x3/z3^2 = lambda^2 - 2x/z^2\n\t * y3/z3^3 = lambda * (x/z^2 - x3/z3^2) - y/z^3\n\t *\n\t * to get rid of fraction we set\n\t *  m = (3 x^2 + az^4) / 2\n\t * Hence,\n\t *  lambda = m / yz = m / z3\n\t *\n\t * With z3 = yz  (the denominator of lambda)\n\t * we get x3 = lambda^2*z3^2 - 2*x/z^2*z3^2\n\t *           = m^2 - 2*xy^2\n\t *    and y3 = (lambda * (x/z^2 - x3/z3^2) - y/z^3) * z3^3\n\t *           = m * (xy^2 - x3) - y^4\n\t */\n\n\t/* m = (3*x^2 + a z^4) / 2\n\t * x3 = m^2 - 2*xy^2\n\t * y3 = m*(xy^2 - x3) - 8y^4\n\t * z3 = y*z\n\t */\n\n\tm = p->x;\n\tbn_multiply(&m, &m, prime);\n\tbn_mult_k(&m, 3, prime);\n\n\taz4 = p->z;\n\tbn_multiply(&az4, &az4, prime);\n\tbn_multiply(&az4, &az4, prime);\n\tbn_mult_k(&az4, -curve->a, prime);\n\tbn_subtractmod(&m, &az4, &m, prime);\n\tbn_mult_half(&m, prime);\n\n\t// msq = m^2\n\tmsq = m;\n\tbn_multiply(&msq, &msq, prime);\n\t// ysq = y^2\n\tysq = p->y;\n\tbn_multiply(&ysq, &ysq, prime);\n\t// xysq = xy^2\n\txysq = p->x;\n\tbn_multiply(&ysq, &xysq, prime);\n\n\t// z3 = yz\n\tbn_multiply(&p->y, &p->z, prime);\n\n\t// x3 = m^2 - 2*xy^2\n\tp->x = xysq;\n\tbn_lshift(&p->x);\n\tbn_fast_mod(&p->x, prime);\n\tbn_subtractmod(&msq, &p->x, &p->x, prime);\n\tbn_fast_mod(&p->x, prime);\n\n\t// y3 = m*(xy^2 - x3) - y^4\n\tbn_subtractmod(&xysq, &p->x, &p->y, prime);\n\tbn_multiply(&m, &p->y, prime);\n\tbn_multiply(&ysq, &ysq, prime);\n\tbn_subtractmod(&p->y, &ysq, &p->y, prime);\n\tbn_fast_mod(&p->y, prime);\n}\n\n// res = k * p\nvoid point_multiply(const ecdsa_curve *curve, const bignum256 *k, const curve_point *p, curve_point *res)\n{\n\t// this algorithm is loosely based on\n\t//  Katsuyuki Okeya and Tsuyoshi Takagi, The Width-w NAF Method Provides\n\t//  Small Memory and Fast Elliptic Scalar Multiplications Secure against\n\t//  Side Channel Attacks.\n\tassert (bn_is_less(k, &curve->order));\n\n\tint i, j;\n\tstatic CONFIDENTIAL bignum256 a;\n\tuint32_t *aptr;\n\tuint32_t abits;\n\tint ashift;\n\tuint32_t is_even = (k->val[0] & 1) - 1;\n\tuint32_t bits, sign, nsign;\n\tstatic CONFIDENTIAL jacobian_curve_point jres;\n\tcurve_point pmult[8];\n\tconst bignum256 *prime = &curve->prime;\n\n\t// is_even = 0xffffffff if k is even, 0 otherwise.\n\n\t// add 2^256.\n\t// make number odd: subtract curve->order if even\n\tuint32_t tmp = 1;\n\tuint32_t is_non_zero = 0;\n\tfor (j = 0; j < 8; j++) {\n\t\tis_non_zero |= k->val[j];\n\t\ttmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even);\n\t\ta.val[j] = tmp & 0x3fffffff;\n\t\ttmp >>= 30;\n\t}\n\tis_non_zero |= k->val[j];\n\ta.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even);\n\tassert((a.val[0] & 1) != 0);\n\n\t// special case 0*p:  just return zero. We don't care about constant time.\n\tif (!is_non_zero) {\n\t\tpoint_set_infinity(res);\n\t\treturn;\n\t}\n\n\t// Now a = k + 2^256 (mod curve->order) and a is odd.\n\t//\n\t// The idea is to bring the new a into the form.\n\t// sum_{i=0..64} a[i] 16^i,  where |a[i]| < 16 and a[i] is odd.\n\t// a[0] is odd, since a is odd.  If a[i] would be even, we can\n\t// add 1 to it and subtract 16 from a[i-1].  Afterwards,\n\t// a[64] = 1, which is the 2^256 that we added before.\n\t//\n\t// Since k = a - 2^256 (mod curve->order), we can compute\n\t//   k*p = sum_{i=0..63} a[i] 16^i * p\n\t//\n\t// We compute |a[i]| * p in advance for all possible\n\t// values of |a[i]| * p.  pmult[i] = (2*i+1) * p\n\t// We compute p, 3*p, ..., 15*p and store it in the table pmult.\n\t// store p^2 temporarily in pmult[7]\n\tpmult[7] = *p;\n\tpoint_double(curve, &pmult[7]);\n\t// compute 3*p, etc by repeatedly adding p^2.\n\tpmult[0] = *p;\n\tfor (i = 1; i < 8; i++) {\n\t\tpmult[i] = pmult[7];\n\t\tpoint_add(curve, &pmult[i-1], &pmult[i]);\n\t}\n\n\t// now compute  res = sum_{i=0..63} a[i] * 16^i * p step by step,\n\t// starting with i = 63.\n\t// initialize jres = |a[63]| * p.\n\t// Note that a[i] = a>>(4*i) & 0xf if (a&0x10) != 0\n\t// and - (16 - (a>>(4*i) & 0xf)) otherwise.   We can compute this as\n\t//   ((a ^ (((a >> 4) & 1) - 1)) & 0xf) >> 1\n\t// since a is odd.\n\taptr = &a.val[8];\n\tabits = *aptr;\n\tashift = 12;\n\tbits = abits >> ashift;\n\tsign = (bits >> 4) - 1;\n\tbits ^= sign;\n\tbits &= 15;\n\tcurve_to_jacobian(&pmult[bits>>1], &jres, prime);\n\tfor (i = 62; i >= 0; i--) {\n\t\t// sign = sign(a[i+1])  (0xffffffff for negative, 0 for positive)\n\t\t// invariant jres = (-1)^sign sum_{j=i+1..63} (a[j] * 16^{j-i-1} * p)\n\t\t// abits >> (ashift - 4) = lowbits(a >> (i*4))\n\n\t\tpoint_jacobian_double(&jres, curve);\n\t\tpoint_jacobian_double(&jres, curve);\n\t\tpoint_jacobian_double(&jres, curve);\n\t\tpoint_jacobian_double(&jres, curve);\n\n\t\t// get lowest 5 bits of a >> (i*4).\n\t\tashift -= 4;\n\t\tif (ashift < 0) {\n\t\t\t// the condition only depends on the iteration number and\n\t\t\t// leaks no private information to a side-channel.\n\t\t\tbits = abits << (-ashift);\n\t\t\tabits = *(--aptr);\n\t\t\tashift += 30;\n\t\t\tbits |= abits >> ashift;\n\t\t} else {\n\t\t\tbits = abits >> ashift;\n\t\t}\n\t\tbits &= 31;\n\t\tnsign = (bits >> 4) - 1;\n\t\tbits ^= nsign;\n\t\tbits &= 15;\n\n\t\t// negate last result to make signs of this round and the\n\t\t// last round equal.\n\t\tconditional_negate(sign ^ nsign, &jres.z, prime);\n\n\t\t// add odd factor\n\t\tpoint_jacobian_add(&pmult[bits >> 1], &jres, curve);\n\t\tsign = nsign;\n\t}\n\tconditional_negate(sign, &jres.z, prime);\n\tjacobian_to_curve(&jres, res, prime);\n\tmemzero(&a, sizeof(a));\n\tmemzero(&jres, sizeof(jres));\n}\n\n#if USE_PRECOMPUTED_CP\n\n// res = k * G\n// k must be a normalized number with 0 <= k < curve->order\nvoid scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res)\n{\n\tassert (bn_is_less(k, &curve->order));\n\n\tint i, j;\n\tstatic CONFIDENTIAL bignum256 a;\n\tuint32_t is_even = (k->val[0] & 1) - 1;\n\tuint32_t lowbits;\n\tstatic CONFIDENTIAL jacobian_curve_point jres;\n\tconst bignum256 *prime = &curve->prime;\n\n\t// is_even = 0xffffffff if k is even, 0 otherwise.\n\n\t// add 2^256.\n\t// make number odd: subtract curve->order if even\n\tuint32_t tmp = 1;\n\tuint32_t is_non_zero = 0;\n\tfor (j = 0; j < 8; j++) {\n\t\tis_non_zero |= k->val[j];\n\t\ttmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even);\n\t\ta.val[j] = tmp & 0x3fffffff;\n\t\ttmp >>= 30;\n\t}\n\tis_non_zero |= k->val[j];\n\ta.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even);\n\tassert((a.val[0] & 1) != 0);\n\n\t// special case 0*G:  just return zero. We don't care about constant time.\n\tif (!is_non_zero) {\n\t\tpoint_set_infinity(res);\n\t\treturn;\n\t}\n\n\t// Now a = k + 2^256 (mod curve->order) and a is odd.\n\t//\n\t// The idea is to bring the new a into the form.\n\t// sum_{i=0..64} a[i] 16^i,  where |a[i]| < 16 and a[i] is odd.\n\t// a[0] is odd, since a is odd.  If a[i] would be even, we can\n\t// add 1 to it and subtract 16 from a[i-1].  Afterwards,\n\t// a[64] = 1, which is the 2^256 that we added before.\n\t//\n\t// Since k = a - 2^256 (mod curve->order), we can compute\n\t//   k*G = sum_{i=0..63} a[i] 16^i * G\n\t//\n\t// We have a big table curve->cp that stores all possible\n\t// values of |a[i]| 16^i * G.\n\t// curve->cp[i][j] = (2*j+1) * 16^i * G\n\n\t// now compute  res = sum_{i=0..63} a[i] * 16^i * G step by step.\n\t// initial res = |a[0]| * G.  Note that a[0] = a & 0xf if (a&0x10) != 0\n\t// and - (16 - (a & 0xf)) otherwise.   We can compute this as\n\t//   ((a ^ (((a >> 4) & 1) - 1)) & 0xf) >> 1\n\t// since a is odd.\n\tlowbits = a.val[0] & ((1 << 5) - 1);\n\tlowbits ^= (lowbits >> 4) - 1;\n\tlowbits &= 15;\n\tcurve_to_jacobian(&curve->cp[0][lowbits >> 1], &jres, prime);\n\tfor (i = 1; i < 64; i ++) {\n\t\t// invariant res = sign(a[i-1]) sum_{j=0..i-1} (a[j] * 16^j * G)\n\n\t\t// shift a by 4 places.\n\t\tfor (j = 0; j < 8; j++) {\n\t\t\ta.val[j] = (a.val[j] >> 4) | ((a.val[j + 1] & 0xf) << 26);\n\t\t}\n\t\ta.val[j] >>= 4;\n\t\t// a = old(a)>>(4*i)\n\t\t// a is even iff sign(a[i-1]) = -1\n\n\t\tlowbits = a.val[0] & ((1 << 5) - 1);\n\t\tlowbits ^= (lowbits >> 4) - 1;\n\t\tlowbits &= 15;\n\t\t// negate last result to make signs of this round and the\n\t\t// last round equal.\n\t\tconditional_negate((lowbits & 1) - 1, &jres.y, prime);\n\n\t\t// add odd factor\n\t\tpoint_jacobian_add(&curve->cp[i][lowbits >> 1], &jres, curve);\n\t}\n\tconditional_negate(((a.val[0] >> 4) & 1) - 1, &jres.y, prime);\n\tjacobian_to_curve(&jres, res, prime);\n\tmemzero(&a, sizeof(a));\n\tmemzero(&jres, sizeof(jres));\n}\n\n#else\n\nvoid scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res)\n{\n\tpoint_multiply(curve, k, &curve->G, res);\n}\n\n#endif\n\nint ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *pub_key, uint8_t *session_key)\n{\n\tcurve_point point;\n\tif (!ecdsa_read_pubkey(curve, pub_key, &point)) {\n\t\treturn 1;\n\t}\n\n\tbignum256 k;\n\tbn_read_be(priv_key, &k);\n\tpoint_multiply(curve, &k, &point, &point);\n\tmemzero(&k, sizeof(k));\n\n\tsession_key[0] = 0x04;\n\tbn_write_be(&point.x, session_key + 1);\n\tbn_write_be(&point.y, session_key + 33);\n\tmemzero(&point, sizeof(point));\n\n\treturn 0;\n}\n\n// void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) {\n// \tuint8_t bx[2*32];\n// \tuint8_t buf[32 + 1 + 2*32];\n//\n// \tmemcpy(bx, priv_key, 32);\n// \tmemcpy(bx+32, hash, 32);\n//\n// \tmemset(state->v, 1, sizeof(state->v));\n// \tmemset(state->k, 0, sizeof(state->k));\n//\n// \tmemcpy(buf, state->v, sizeof(state->v));\n// \tbuf[sizeof(state->v)] = 0x00;\n// \tmemcpy(buf + sizeof(state->v) + 1, bx, 64);\n// \thmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k);\n// \thmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);\n//\n// \tmemcpy(buf, state->v, sizeof(state->v));\n// \tbuf[sizeof(state->v)] = 0x01;\n// \tmemcpy(buf + sizeof(state->v) + 1, bx, 64);\n// \thmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k);\n// \thmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);\n//\n// \tmemzero(bx, sizeof(bx));\n// \tmemzero(buf, sizeof(buf));\n// }\n\n// generate next number from deterministic random number generator\n// void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state)\n// {\n// \tuint8_t buf[32 + 1];\n//\n// \thmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);\n// \tmemcpy(buf, state->v, sizeof(state->v));\n// \tbuf[sizeof(state->v)] = 0x00;\n// \thmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k);\n// \thmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);\n// \tmemcpy(rnd, buf, 32);\n// \tmemzero(buf, sizeof(buf));\n// }\n//\n// // generate K in a deterministic way, according to RFC6979\n// // http://tools.ietf.org/html/rfc6979\n// void generate_k_rfc6979(bignum256 *k, rfc6979_state *state)\n// {\n// \tuint8_t buf[32];\n// \tgenerate_rfc6979(buf, state);\n// \tbn_read_be(buf, k);\n// \tmemzero(buf, sizeof(buf));\n// }\n\n// msg is a data to be signed\n// msg_len is the message length\nint ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]))\n{\n\tuint8_t hash[32];\n\thasher_Raw(hasher_sign, msg, msg_len, hash);\n\tint res = ecdsa_sign_digest(curve, priv_key, hash, sig, pby, is_canonical);\n\tmemzero(hash, sizeof(hash));\n\treturn res;\n\n}\n\n// uses secp256k1 curve\n// priv_key is a 32 byte big endian stored number\n// sig is 64 bytes long array for the signature\n// digest is 32 bytes of digest\n// is_canonical is an optional function that checks if the signature\n// conforms to additional coin-specific rules.\nint ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]))\n{\n\tint i;\n\tcurve_point R;\n\tbignum256 k, z, randk;\n\tbignum256 *s = &R.y;\n\tuint8_t by; // signature recovery byte\n\n#if USE_RFC6979\n\trfc6979_state rng;\n\tinit_rfc6979(priv_key, digest, &rng);\n#endif\n\n\tbn_read_be(digest, &z);\n\n\tfor (i = 0; i < 10000; i++) {\n\n#if USE_RFC6979\n\t\t// generate K deterministically\n\t\tgenerate_k_rfc6979(&k, &rng);\n\t\t// if k is too big or too small, we don't like it\n\t\tif (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) {\n\t\t\tcontinue;\n\t\t}\n#else\n\t\t// generate random number k\n\t\tgenerate_k_random(&k, &curve->order);\n#endif\n\n\t\t// compute k*G\n\t\tscalar_multiply(curve, &k, &R);\n\t\tby = R.y.val[0] & 1;\n\t\t// r = (rx mod n)\n\t\tif (!bn_is_less(&R.x, &curve->order)) {\n\t\t\tbn_subtract(&R.x, &curve->order, &R.x);\n\t\t\tby |= 2;\n\t\t}\n\t\t// if r is zero, we retry\n\t\tif (bn_is_zero(&R.x)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// randomize operations to counter side-channel attacks\n\t\tgenerate_k_random(&randk, &curve->order);\n\t\tbn_multiply(&randk, &k, &curve->order); // k*rand\n\t\tbn_inverse(&k, &curve->order);         // (k*rand)^-1\n\t\tbn_read_be(priv_key, s);               // priv\n\t\tbn_multiply(&R.x, s, &curve->order);   // R.x*priv\n\t\tbn_add(s, &z);                         // R.x*priv + z\n\t\tbn_multiply(&k, s, &curve->order);     // (k*rand)^-1 (R.x*priv + z)\n\t\tbn_multiply(&randk, s, &curve->order);  // k^-1 (R.x*priv + z)\n\t\tbn_mod(s, &curve->order);\n\t\t// if s is zero, we retry\n\t\tif (bn_is_zero(s)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// if S > order/2 => S = -S\n\t\tif (bn_is_less(&curve->order_half, s)) {\n\t\t\tbn_subtract(&curve->order, s, s);\n\t\t\tby ^= 1;\n\t\t}\n\t\t// we are done, R.x and s is the result signature\n\t\tbn_write_be(&R.x, sig);\n\t\tbn_write_be(s, sig + 32);\n\n\t\t// check if the signature is acceptable or retry\n\t\tif (is_canonical && !is_canonical(by, sig)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (pby) {\n\t\t\t*pby = by;\n\t\t}\n\n\t\tmemzero(&k, sizeof(k));\n\t\tmemzero(&randk, sizeof(randk));\n#if USE_RFC6979\n\t\tmemzero(&rng, sizeof(rng));\n#endif\n\t\treturn 0;\n\t}\n\n\t// Too many retries without a valid signature\n\t// -> fail with an error\n\tmemzero(&k, sizeof(k));\n\tmemzero(&randk, sizeof(randk));\n#if USE_RFC6979\n\tmemzero(&rng, sizeof(rng));\n#endif\n\treturn -1;\n}\n\nvoid ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key)\n{\n\tcurve_point R;\n\tbignum256 k;\n\n\tbn_read_be(priv_key, &k);\n\t// compute k*G\n\tscalar_multiply(curve, &k, &R);\n\tpub_key[0] = 0x02 | (R.y.val[0] & 0x01);\n\tbn_write_be(&R.x, pub_key + 1);\n\tmemzero(&R, sizeof(R));\n\tmemzero(&k, sizeof(k));\n}\n\nvoid ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key)\n{\n\tcurve_point R;\n\tbignum256 k;\n\n\tbn_read_be(priv_key, &k);\n\t// compute k*G\n\tscalar_multiply(curve, &k, &R);\n\tpub_key[0] = 0x04;\n\tbn_write_be(&R.x, pub_key + 1);\n\tbn_write_be(&R.y, pub_key + 33);\n\tmemzero(&R, sizeof(R));\n\tmemzero(&k, sizeof(k));\n}\n\nint ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed)\n{\n\tcurve_point pub;\n\n\tif (!ecdsa_read_pubkey(curve, pub_key, &pub)) {\n\t\treturn 0;\n\t}\n\n\tuncompressed[0] = 4;\n\tbn_write_be(&pub.x, uncompressed + 1);\n\tbn_write_be(&pub.y, uncompressed + 33);\n\n\treturn 1;\n}\n\nvoid ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey, uint8_t *pubkeyhash)\n{\n\tuint8_t h[HASHER_DIGEST_LENGTH];\n\tif (pub_key[0] == 0x04) {  // uncompressed format\n\t\thasher_Raw(hasher_pubkey, pub_key, 65, h);\n\t} else if (pub_key[0] == 0x00) { // point at infinity\n\t\thasher_Raw(hasher_pubkey, pub_key,  1, h);\n\t} else { // expecting compressed format\n\t\thasher_Raw(hasher_pubkey, pub_key, 33, h);\n\t}\n\tmemcpy(pubkeyhash, h, 20);\n\tmemzero(h, sizeof(h));\n}\n\nvoid ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw)\n{\n\tsize_t prefix_len = address_prefix_bytes_len(version);\n\taddress_write_prefix_bytes(version, addr_raw);\n\tecdsa_get_pubkeyhash(pub_key, hasher_pubkey, addr_raw + prefix_len);\n}\n\nvoid ecdsa_get_address(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize)\n{\n\tuint8_t raw[MAX_ADDR_RAW_SIZE];\n\tsize_t prefix_len = address_prefix_bytes_len(version);\n\tecdsa_get_address_raw(pub_key, version, hasher_pubkey, raw);\n\tbase58_encode_check(raw, 20 + prefix_len, hasher_base58, addr, addrsize);\n\t// not as important to clear this one, but we might as well\n\tmemzero(raw, sizeof(raw));\n}\n\nvoid ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw)\n{\n\tuint8_t buf[32 + 2];\n\tbuf[0] = 0; // version byte\n\tbuf[1] = 20; // push 20 bytes\n\tecdsa_get_pubkeyhash(pub_key, hasher_pubkey, buf + 2);\n\tsize_t prefix_len = address_prefix_bytes_len(version);\n\taddress_write_prefix_bytes(version, addr_raw);\n\thasher_Raw(hasher_pubkey, buf, 22, addr_raw + prefix_len);\n}\n\nvoid ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize)\n{\n\tuint8_t raw[MAX_ADDR_RAW_SIZE];\n\tsize_t prefix_len = address_prefix_bytes_len(version);\n\tecdsa_get_address_segwit_p2sh_raw(pub_key, version, hasher_pubkey, raw);\n\tbase58_encode_check(raw, prefix_len + 20, hasher_base58, addr, addrsize);\n\tmemzero(raw, sizeof(raw));\n}\n\nvoid ecdsa_get_wif(const uint8_t *priv_key, uint32_t version, HasherType hasher_base58, char *wif, int wifsize)\n{\n\tuint8_t wif_raw[MAX_WIF_RAW_SIZE];\n\tsize_t prefix_len = address_prefix_bytes_len(version);\n\taddress_write_prefix_bytes(version, wif_raw);\n\tmemcpy(wif_raw + prefix_len, priv_key, 32);\n\twif_raw[prefix_len + 32] = 0x01;\n\tbase58_encode_check(wif_raw, prefix_len + 32 + 1, hasher_base58, wif, wifsize);\n\t// private keys running around our stack can cause trouble\n\tmemzero(wif_raw, sizeof(wif_raw));\n}\n\nint ecdsa_address_decode(const char *addr, uint32_t version, HasherType hasher_base58, uint8_t *out)\n{\n\tif (!addr) return 0;\n\tint prefix_len = address_prefix_bytes_len(version);\n\treturn base58_decode_check(addr, hasher_base58, out, 20 + prefix_len) == 20 + prefix_len\n\t\t&& address_check_prefix(out, version);\n}\n\nvoid uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y)\n{\n\t// y^2 = x^3 + a*x + b\n\tmemcpy(y, x, sizeof(bignum256));         // y is x\n\tbn_multiply(x, y, &curve->prime);        // y is x^2\n\tbn_subi(y, -curve->a, &curve->prime);    // y is x^2 + a\n\tbn_multiply(x, y, &curve->prime);        // y is x^3 + ax\n\tbn_add(y, &curve->b);                    // y is x^3 + ax + b\n\tbn_sqrt(y, &curve->prime);               // y = sqrt(y)\n\tif ((odd & 0x01) != (y->val[0] & 1)) {\n\t\tbn_subtract(&curve->prime, y, y);   // y = -y\n\t}\n}\n\nint ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_point *pub)\n{\n\tif (!curve) {\n\t\tcurve = &secp256k1;\n\t}\n\tif (pub_key[0] == 0x04) {\n\t\tbn_read_be(pub_key + 1, &(pub->x));\n\t\tbn_read_be(pub_key + 33, &(pub->y));\n\t\treturn ecdsa_validate_pubkey(curve, pub);\n\t}\n\tif (pub_key[0] == 0x02 || pub_key[0] == 0x03) { // compute missing y coords\n\t\tbn_read_be(pub_key + 1, &(pub->x));\n\t\tuncompress_coords(curve, pub_key[0], &(pub->x), &(pub->y));\n\t\treturn ecdsa_validate_pubkey(curve, pub);\n\t}\n\t// error\n\treturn 0;\n}\n\n// Verifies that:\n//   - pub is not the point at infinity.\n//   - pub->x and pub->y are in range [0,p-1].\n//   - pub is on the curve.\n\nint ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub)\n{\n\tbignum256 y_2, x3_ax_b;\n\n\tif (point_is_infinity(pub)) {\n\t\treturn 0;\n\t}\n\n\tif (!bn_is_less(&(pub->x), &curve->prime) || !bn_is_less(&(pub->y), &curve->prime)) {\n\t\treturn 0;\n\t}\n\n\tmemcpy(&y_2, &(pub->y), sizeof(bignum256));\n\tmemcpy(&x3_ax_b, &(pub->x), sizeof(bignum256));\n\n\t// y^2\n\tbn_multiply(&(pub->y), &y_2, &curve->prime);\n\tbn_mod(&y_2, &curve->prime);\n\n\t// x^3 + ax + b\n\tbn_multiply(&(pub->x), &x3_ax_b, &curve->prime);  // x^2\n\tbn_subi(&x3_ax_b, -curve->a, &curve->prime);      // x^2 + a\n\tbn_multiply(&(pub->x), &x3_ax_b, &curve->prime);  // x^3 + ax\n\tbn_addmod(&x3_ax_b, &curve->b, &curve->prime);    // x^3 + ax + b\n\tbn_mod(&x3_ax_b, &curve->prime);\n\n\tif (!bn_is_equal(&x3_ax_b, &y_2)) {\n\t\treturn 0;\n\t}\n\n\treturn 1;\n}\n\n// uses secp256k1 curve\n// pub_key - 65 bytes uncompressed key\n// signature - 64 bytes signature\n// msg is a data that was signed\n// msg_len is the message length\n\nint ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len)\n{\n\tuint8_t hash[32];\n\thasher_Raw(hasher_sign, msg, msg_len, hash);\n\tint res = ecdsa_verify_digest(curve, pub_key, sig, hash);\n\tmemzero(hash, sizeof(hash));\n\treturn res;\n}\n\n// Compute public key from signature and recovery id.\n// returns 0 if the key is successfully recovered\nint ecdsa_recover_pub_from_sig (const ecdsa_curve *curve, uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest, int recid)\n{\n\tbignum256 r, s, e;\n\tcurve_point cp, cp2;\n\n\t// read r and s\n\tbn_read_be(sig, &r);\n\tbn_read_be(sig + 32, &s);\n\tif (!bn_is_less(&r, &curve->order) || bn_is_zero(&r)) {\n\t\treturn 1;\n\t}\n\tif (!bn_is_less(&s, &curve->order) || bn_is_zero(&s)) {\n\t\treturn 1;\n\t}\n\t// cp = R = k * G (k is secret nonce when signing)\n\tmemcpy(&cp.x, &r, sizeof(bignum256));\n\tif (recid & 2) {\n\t\tbn_add(&cp.x, &curve->order);\n\t\tif (!bn_is_less(&cp.x, &curve->prime)) {\n\t\t\treturn 1;\n\t\t}\n\t}\n\t// compute y from x\n\tuncompress_coords(curve, recid & 1, &cp.x, &cp.y);\n\tif (!ecdsa_validate_pubkey(curve, &cp)) {\n\t\treturn 1;\n\t}\n\t// e = -digest\n\tbn_read_be(digest, &e);\n\tbn_subtractmod(&curve->order, &e, &e, &curve->order);\n\tbn_fast_mod(&e, &curve->order);\n\tbn_mod(&e, &curve->order);\n\t// r := r^-1\n\tbn_inverse(&r, &curve->order);\n\t// cp := s * R = s * k *G\n\tpoint_multiply(curve, &s, &cp, &cp);\n\t// cp2 := -digest * G\n\tscalar_multiply(curve, &e, &cp2);\n\t// cp := (s * k - digest) * G = (r*priv) * G = r * Pub\n\tpoint_add(curve, &cp2, &cp);\n\t// cp := r^{-1} * r * Pub = Pub\n\tpoint_multiply(curve, &r, &cp, &cp);\n\tpub_key[0] = 0x04;\n\tbn_write_be(&cp.x, pub_key + 1);\n\tbn_write_be(&cp.y, pub_key + 33);\n\treturn 0;\n}\n\n// returns 0 if verification succeeded\nint ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest)\n{\n\tcurve_point pub, res;\n\tbignum256 r, s, z;\n\n\tif (!ecdsa_read_pubkey(curve, pub_key, &pub)) {\n\t\treturn 1;\n\t}\n\n\tbn_read_be(sig, &r);\n\tbn_read_be(sig + 32, &s);\n\n\tbn_read_be(digest, &z);\n\n\tif (bn_is_zero(&r) || bn_is_zero(&s) ||\n\t\t(!bn_is_less(&r, &curve->order)) ||\n\t\t(!bn_is_less(&s, &curve->order))) return 2;\n\n\tbn_inverse(&s, &curve->order); // s^-1\n\tbn_multiply(&s, &z, &curve->order); // z*s^-1\n\tbn_mod(&z, &curve->order);\n\tbn_multiply(&r, &s, &curve->order); // r*s^-1\n\tbn_mod(&s, &curve->order);\n\n\tint result = 0;\n\tif (bn_is_zero(&z)) {\n\t\t// our message hashes to zero\n\t\t// I don't expect this to happen any time soon\n\t\tresult = 3;\n\t} else {\n\t\tscalar_multiply(curve, &z, &res);\n\t}\n\n\tif (result == 0) {\n\t\t// both pub and res can be infinity, can have y = 0 OR can be equal -> false negative\n\t\tpoint_multiply(curve, &s, &pub, &pub);\n\t\tpoint_add(curve, &pub, &res);\n\t\tbn_mod(&(res.x), &curve->order);\n\t\t// signature does not match\n\t\tif (!bn_is_equal(&res.x, &r)) {\n\t\t\tresult = 5;\n\t\t}\n\t}\n\n\tmemzero(&pub, sizeof(pub));\n\tmemzero(&res, sizeof(res));\n\tmemzero(&r, sizeof(r));\n\tmemzero(&s, sizeof(s));\n\tmemzero(&z, sizeof(z));\n\n\t// all OK\n\treturn result;\n}\n\nint ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der)\n{\n\tint i;\n\tuint8_t *p = der, *len, *len1, *len2;\n\t*p = 0x30; p++;                        // sequence\n\t*p = 0x00; len = p; p++;               // len(sequence)\n\n\t*p = 0x02; p++;                        // integer\n\t*p = 0x00; len1 = p; p++;              // len(integer)\n\n\t// process R\n\ti = 0;\n\twhile (sig[i] == 0 && i < 32) { i++; } // skip leading zeroes\n\tif (sig[i] >= 0x80) { // put zero in output if MSB set\n\t\t*p = 0x00; p++; *len1 = *len1 + 1;\n\t}\n\twhile (i < 32) { // copy bytes to output\n\t\t*p = sig[i]; p++; *len1 = *len1 + 1; i++;\n\t}\n\n\t*p = 0x02; p++;                        // integer\n\t*p = 0x00; len2 = p; p++;              // len(integer)\n\n\t// process S\n\ti = 32;\n\twhile (sig[i] == 0 && i < 64) { i++; } // skip leading zeroes\n\tif (sig[i] >= 0x80) { // put zero in output if MSB set\n\t\t*p = 0x00; p++; *len2 = *len2 + 1;\n\t}\n\twhile (i < 64) { // copy bytes to output\n\t\t*p = sig[i]; p++; *len2 = *len2 + 1; i++;\n\t}\n\n\t*len = *len1 + *len2 + 4;\n\treturn *len + 2;\n}\n"
  },
  {
    "path": "src/utility/trezor/ecdsa.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __ECDSA_H__\n#define __ECDSA_H__\n\n#include <stdint.h>\n#include \"options.h\"\n#include \"bignum.h\"\n#include \"hasher.h\"\n\n// curve point x and y\ntypedef struct {\n\tbignum256 x, y;\n} curve_point;\n\ntypedef struct {\n\n\tbignum256 prime;       // prime order of the finite field\n\tcurve_point G;         // initial curve point\n\tbignum256 order;       // order of G\n\tbignum256 order_half;  // order of G divided by 2\n\tint       a;           // coefficient 'a' of the elliptic curve\n\tbignum256 b;           // coefficient 'b' of the elliptic curve\n\n#if USE_PRECOMPUTED_CP\n\tconst curve_point cp[64][8];\n#endif\n\n} ecdsa_curve;\n\n// 4 byte prefix + 40 byte data (segwit)\n// 1 byte prefix + 64 byte data (cashaddr)\n#define MAX_ADDR_RAW_SIZE 65\n// bottle neck is cashaddr\n// segwit is at most 90 characters plus NUL separator\n// cashaddr: human readable prefix + 1 separator + 104 data + 8 checksum + 1 NUL\n// we choose 130 as maximum (including NUL character)\n#define MAX_ADDR_SIZE 130\n// 4 byte prefix + 32 byte privkey + 1 byte compressed marker\n#define MAX_WIF_RAW_SIZE (4 + 32 + 1)\n// (4 + 32 + 1 + 4 [checksum]) * 8 / log2(58) plus NUL.\n#define MAX_WIF_SIZE (57)\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nvoid point_copy(const curve_point *cp1, curve_point *cp2);\nvoid point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2);\nvoid point_double(const ecdsa_curve *curve, curve_point *cp);\nvoid point_multiply(const ecdsa_curve *curve, const bignum256 *k, const curve_point *p, curve_point *res);\nvoid point_set_infinity(curve_point *p);\nint point_is_infinity(const curve_point *p);\nint point_is_equal(const curve_point *p, const curve_point *q);\nint point_is_negative_of(const curve_point *p, const curve_point *q);\nvoid scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res);\nint ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *pub_key, uint8_t *session_key);\nvoid uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y);\nint ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed);\n\nint ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));\nint ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));\nvoid ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key);\nvoid ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key);\nvoid ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey, uint8_t *pubkeyhash);\nvoid ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw);\nvoid ecdsa_get_address(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize);\nvoid ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw);\nvoid ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize);\nvoid ecdsa_get_wif(const uint8_t *priv_key, uint32_t version, HasherType hasher_base58, char *wif, int wifsize);\n\nint ecdsa_address_decode(const char *addr, uint32_t version, HasherType hasher_base58, uint8_t *out);\nint ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_point *pub);\nint ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub);\nint ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len);\nint ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest);\nint ecdsa_recover_pub_from_sig (const ecdsa_curve *curve, uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest, int recid);\nint ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der);\n\n#ifdef __cplusplus\n} /* end of extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/hasher.c",
    "content": "/**\n * Copyright (c) 2017 Saleem Rashid\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include \"hasher.h\"\n#include \"ripemd160.h\"\n\nvoid hasher_Init(Hasher *hasher, HasherType type) {\n\thasher->type = type;\n\n\tswitch (hasher->type) {\n\tcase HASHER_SHA2:\n\tcase HASHER_SHA2D:\n\tcase HASHER_SHA2_RIPEMD:\n\t\tsha256_Init(&hasher->ctx.sha2);\n\t\tbreak;\n\tcase HASHER_SHA3:\n#if USE_KECCAK\n\tcase HASHER_SHA3K:\n#endif\n\t\tsha3_256_Init(&hasher->ctx.sha3);\n\t\tbreak;\n\t}\n}\n\nvoid hasher_Reset(Hasher *hasher) {\n\thasher_Init(hasher, hasher->type);\n}\n\nvoid hasher_Update(Hasher *hasher, const uint8_t *data, size_t length) {\n\tswitch (hasher->type) {\n\tcase HASHER_SHA2:\n\tcase HASHER_SHA2D:\n\tcase HASHER_SHA2_RIPEMD:\n\t\tsha256_Update(&hasher->ctx.sha2, data, length);\n\t\tbreak;\n\tcase HASHER_SHA3:\n#if USE_KECCAK\n\tcase HASHER_SHA3K:\n#endif\n\t\tsha3_Update(&hasher->ctx.sha3, data, length);\n\t\tbreak;\n\t}\n}\n\nvoid hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]) {\n\tswitch (hasher->type) {\n\tcase HASHER_SHA2:\n\t\tsha256_Final(&hasher->ctx.sha2, hash);\n\t\tbreak;\n\tcase HASHER_SHA2D:\n\t\tsha256_Final(&hasher->ctx.sha2, hash);\n\t\thasher_Raw(HASHER_SHA2, hash, HASHER_DIGEST_LENGTH, hash);\n\t\tbreak;\n\tcase HASHER_SHA2_RIPEMD:\n\t\tsha256_Final(&hasher->ctx.sha2, hash);\n\t\tripemd160(hash, HASHER_DIGEST_LENGTH, hash);\n\t\tbreak;\n\tcase HASHER_SHA3:\n\t\tsha3_Final(&hasher->ctx.sha3, hash);\n\t\tbreak;\n#if USE_KECCAK\n\tcase HASHER_SHA3K:\n\t\tkeccak_Final(&hasher->ctx.sha3, hash);\n\t\tbreak;\n#endif\n\t}\n}\n\nvoid hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]) {\n\tHasher hasher;\n\n\thasher_Init(&hasher, type);\n\thasher_Update(&hasher, data, length);\n\thasher_Final(&hasher, hash);\n}\n"
  },
  {
    "path": "src/utility/trezor/hasher.h",
    "content": "/**\n * Copyright (c) 2017 Saleem Rashid\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __HASHER_H__\n#define __HASHER_H__\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"sha2.h\"\n#include \"sha3.h\"\n\n#define HASHER_DIGEST_LENGTH 32\n\ntypedef enum {\n    HASHER_SHA2,\n    HASHER_SHA2D,\n    HASHER_SHA2_RIPEMD,\n\n    HASHER_SHA3,\n#if USE_KECCAK\n    HASHER_SHA3K,\n#endif\n} HasherType;\n\ntypedef struct {\n    HasherType type;\n\n    union {\n        SHA256_CTX sha2;        // for HASHER_SHA2{,D}\n        SHA3_CTX sha3;          // for HASHER_SHA3{,K}\n    } ctx;\n} Hasher;\n\nvoid hasher_Init(Hasher *hasher, HasherType type);\nvoid hasher_Reset(Hasher *hasher);\nvoid hasher_Update(Hasher *hasher, const uint8_t *data, size_t length);\nvoid hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]);\n\nvoid hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]);\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/hmac.c",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n#include <string.h>\n\n#include \"hmac.h\"\n#include \"memzero.h\"\n\n// add way how to mark confidential data\n#ifndef CONFIDENTIAL\n#define CONFIDENTIAL\n#endif\n\nvoid ubtc_hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen)\n{\n\tstatic CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH];\n\tmemset(i_key_pad, 0, SHA256_BLOCK_LENGTH);\n\tif (keylen > SHA256_BLOCK_LENGTH) {\n\t\tsha256_Raw(key, keylen, i_key_pad);\n\t} else {\n\t\tmemcpy(i_key_pad, key, keylen);\n\t}\n\tfor (int i = 0; i < SHA256_BLOCK_LENGTH; i++) {\n\t\thctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;\n\t\ti_key_pad[i] ^= 0x36;\n\t}\n\tsha256_Init(&(hctx->ctx));\n\tsha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH);\n\tmemzero(i_key_pad, sizeof(i_key_pad));\n}\n\nvoid ubtc_hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen)\n{\n\tsha256_Update(&(hctx->ctx), msg, msglen);\n}\n\nvoid ubtc_hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac)\n{\n\tsha256_Final(&(hctx->ctx), hmac);\n\tsha256_Init(&(hctx->ctx));\n\tsha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH);\n\tsha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH);\n\tsha256_Final(&(hctx->ctx), hmac);\n\tmemzero(hctx, sizeof(HMAC_SHA256_CTX));\n}\n\nvoid ubtc_hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac)\n{\n\tstatic CONFIDENTIAL HMAC_SHA256_CTX hctx;\n\tubtc_hmac_sha256_Init(&hctx, key, keylen);\n\tubtc_hmac_sha256_Update(&hctx, msg, msglen);\n\tubtc_hmac_sha256_Final(&hctx, hmac);\n}\n\nvoid ubtc_hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest)\n{\n\tstatic CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH/sizeof(uint32_t)];\n\n\tmemzero(key_pad, sizeof(key_pad));\n\tif (keylen > SHA256_BLOCK_LENGTH) {\n\t\tstatic CONFIDENTIAL SHA256_CTX context;\n\t\tsha256_Init(&context);\n\t\tsha256_Update(&context, key, keylen);\n\t\tsha256_Final(&context, (uint8_t*)key_pad);\n\t} else {\n\t\tmemcpy(key_pad, key, keylen);\n\t}\n\n\t/* compute o_key_pad and its digest */\n\tfor (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) {\n\t\tuint32_t data;\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\tREVERSE32(key_pad[i], data);\n#else\n\t\tdata = key_pad[i];\n#endif\n\t\tkey_pad[i] = data ^ 0x5c5c5c5c;\n\t}\n\tsha256_Transform(sha256_initial_hash_value, key_pad, opad_digest);\n\n\t/* convert o_key_pad to i_key_pad and compute its digest */\n\tfor (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) {\n\t\tkey_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636;\n\t}\n\tsha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest);\n\tmemzero(key_pad, sizeof(key_pad));\n}\n\nvoid ubtc_hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen)\n{\n\tstatic CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH];\n\tmemset(i_key_pad, 0, SHA512_BLOCK_LENGTH);\n\tif (keylen > SHA512_BLOCK_LENGTH) {\n\t\tsha512_Raw(key, keylen, i_key_pad);\n\t} else {\n\t\tmemcpy(i_key_pad, key, keylen);\n\t}\n\tfor (int i = 0; i < SHA512_BLOCK_LENGTH; i++) {\n\t\thctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;\n\t\ti_key_pad[i] ^= 0x36;\n\t}\n\tsha512_Init(&(hctx->ctx));\n\tsha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH);\n\tmemzero(i_key_pad, sizeof(i_key_pad));\n}\n\nvoid ubtc_hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen)\n{\n\tsha512_Update(&(hctx->ctx), msg, msglen);\n}\n\nvoid ubtc_hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac)\n{\n\tsha512_Final(&(hctx->ctx), hmac);\n\tsha512_Init(&(hctx->ctx));\n\tsha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH);\n\tsha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH);\n\tsha512_Final(&(hctx->ctx), hmac);\n\tmemzero(hctx, sizeof(HMAC_SHA512_CTX));\n}\n\nvoid ubtc_hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac)\n{\n\tHMAC_SHA512_CTX hctx;\n\tubtc_hmac_sha512_Init(&hctx, key, keylen);\n\tubtc_hmac_sha512_Update(&hctx, msg, msglen);\n\tubtc_hmac_sha512_Final(&hctx, hmac);\n}\n\nvoid ubtc_hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest)\n{\n\tstatic CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH/sizeof(uint64_t)];\n\n\tmemzero(key_pad, sizeof(key_pad));\n\tif (keylen > SHA512_BLOCK_LENGTH) {\n\t\tstatic CONFIDENTIAL SHA512_CTX context;\n\t\tsha512_Init(&context);\n\t\tsha512_Update(&context, key, keylen);\n\t\tsha512_Final(&context, (uint8_t*)key_pad);\n\t} else {\n\t\tmemcpy(key_pad, key, keylen);\n\t}\n\n\t/* compute o_key_pad and its digest */\n\tfor (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) {\n\t\tuint64_t data;\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\tREVERSE64(key_pad[i], data);\n#else\n\t\tdata = key_pad[i];\n#endif\n\t\tkey_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c;\n\t}\n\tsha512_Transform(sha512_initial_hash_value, key_pad, opad_digest);\n\n\t/* convert o_key_pad to i_key_pad and compute its digest */\n\tfor (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) {\n\t\tkey_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636;\n\t}\n\tsha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest);\n\tmemzero(key_pad, sizeof(key_pad));\n}\n"
  },
  {
    "path": "src/utility/trezor/hmac.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT HMAC_SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __HMAC_H__\n#define __HMAC_H__\n\n#include <stdint.h>\n#include \"sha2.h\"\n\ntypedef struct _HMAC_SHA256_CTX {\n\tuint8_t o_key_pad[SHA256_BLOCK_LENGTH];\n\tSHA256_CTX ctx;\n} HMAC_SHA256_CTX;\n\ntypedef struct _HMAC_SHA512_CTX {\n\tuint8_t o_key_pad[SHA512_BLOCK_LENGTH];\n\tSHA512_CTX ctx;\n} HMAC_SHA512_CTX;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nvoid ubtc_hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen);\nvoid ubtc_hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen);\nvoid ubtc_hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac);\nvoid ubtc_hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac);\nvoid ubtc_hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest);\n\nvoid ubtc_hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen);\nvoid ubtc_hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen);\nvoid ubtc_hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac);\nvoid ubtc_hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac);\nvoid ubtc_hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest);\n\n#ifdef __cplusplus\n} /* end of extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/memzero.c",
    "content": "#include <string.h>\n\nvoid memzero(void *s, size_t n)\n{\n\tmemset(s, 0, n);\n}\n"
  },
  {
    "path": "src/utility/trezor/memzero.h",
    "content": "#ifndef __MEMZERO_H__\n#define __MEMZERO_H__\n\n#include <stddef.h>\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nvoid memzero(void *s, size_t n);\n\n#ifdef __cplusplus\n} /* end of extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/options.h",
    "content": "/**\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __OPTIONS_H__\n#define __OPTIONS_H__\n\n// use precomputed Curve Points (some scalar multiples of curve base point G)\n#ifndef USE_PRECOMPUTED_CP\n#define USE_PRECOMPUTED_CP 1\n#endif\n\n// use fast inverse method\n#ifndef USE_INVERSE_FAST\n#define USE_INVERSE_FAST 1\n#endif\n\n// support for printing bignum256 structures via printf\n#ifndef USE_BN_PRINT\n#define USE_BN_PRINT 0\n#endif\n\n// use deterministic signatures\n#ifndef USE_RFC6979\n#define USE_RFC6979 1\n#endif\n\n// implement BIP32 caching\n#ifndef USE_BIP32_CACHE\n#define USE_BIP32_CACHE 1\n#define BIP32_CACHE_SIZE 10\n#define BIP32_CACHE_MAXDEPTH 8\n#endif\n\n// support constructing BIP32 nodes from ed25519 and curve25519 curves.\n#ifndef USE_BIP32_25519_CURVES\n#define USE_BIP32_25519_CURVES    0\n#endif\n\n// implement BIP39 caching\n#ifndef USE_BIP39_CACHE\n#define USE_BIP39_CACHE 1\n#define BIP39_CACHE_SIZE 4\n#endif\n\n// support Ethereum operations\n#ifndef USE_ETHEREUM\n#define USE_ETHEREUM 0\n#endif\n\n// support Graphene operations (STEEM, BitShares)\n#ifndef USE_GRAPHENE\n#define USE_GRAPHENE 0\n#endif\n\n// support NEM operations\n#ifndef USE_NEM\n#define USE_NEM 0\n#endif\n\n// support MONERO operations\n#ifndef USE_MONERO\n#define USE_MONERO 0\n#endif\n\n// support CARDANO operations\n#ifndef USE_CARDANO\n#define USE_CARDANO 0\n#endif\n\n// support Keccak hashing\n#ifndef USE_KECCAK\n#define USE_KECCAK 0\n#endif\n\n// add way how to mark confidential data\n#ifndef CONFIDENTIAL\n#define CONFIDENTIAL\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/pbkdf2.c",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <string.h>\n#include \"pbkdf2.h\"\n#include \"hmac.h\"\n#include \"sha2.h\"\n#include \"memzero.h\"\n\nvoid pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr)\n{\n\tSHA256_CTX ctx;\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tREVERSE32(blocknr, blocknr);\n#endif\n\n\tubtc_hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig);\n\tmemzero(pctx->g, sizeof(pctx->g));\n\tpctx->g[8] = 0x80000000;\n\tpctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;\n\n\tmemcpy (ctx.state, pctx->idig, sizeof(pctx->idig));\n\tctx.bitcount = SHA256_BLOCK_LENGTH * 8;\n\tsha256_Update(&ctx, salt, saltlen);\n\tsha256_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr));\n\tsha256_Final(&ctx, (uint8_t*)pctx->g);\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tfor (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {\n\t\tREVERSE32(pctx->g[k], pctx->g[k]);\n\t}\n#endif\n\tsha256_Transform(pctx->odig, pctx->g, pctx->g);\n\tmemcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH);\n\tpctx->first = 1;\n}\n\nvoid pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations)\n{\n\tfor (uint32_t i = pctx->first; i < iterations; i++) {\n\t\tsha256_Transform(pctx->idig, pctx->g, pctx->g);\n\t\tsha256_Transform(pctx->odig, pctx->g, pctx->g);\n\t\tfor (uint32_t j = 0; j < SHA256_DIGEST_LENGTH/sizeof(uint32_t); j++) {\n\t\t\tpctx->f[j] ^= pctx->g[j];\n\t\t}\n\t}\n\tpctx->first = 0;\n}\n\nvoid pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key)\n{\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tfor (uint32_t k = 0; k < SHA256_DIGEST_LENGTH/sizeof(uint32_t); k++) {\n\t\tREVERSE32(pctx->f[k], pctx->f[k]);\n\t}\n#endif\n\tmemcpy(key, pctx->f, SHA256_DIGEST_LENGTH);\n\tmemzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX));\n}\n\nvoid pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen)\n{\n\tuint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH;\n\tuint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH;\n\tif (last_block_size) {\n\t\tblocks_count++;\n\t} else {\n\t\tlast_block_size = SHA256_DIGEST_LENGTH;\n\t}\n\tfor (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {\n\t\tPBKDF2_HMAC_SHA256_CTX pctx;\n\t\tpbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr);\n\t\tpbkdf2_hmac_sha256_Update(&pctx, iterations);\n\t\tuint8_t digest[SHA256_DIGEST_LENGTH];\n\t\tpbkdf2_hmac_sha256_Final(&pctx, digest);\n\t\tuint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH;\n\t\tif (blocknr < blocks_count) {\n\t\t\tmemcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH);\n\t\t} else {\n\t\t\tmemcpy(key + key_offset, digest, last_block_size);\n\t\t}\n\t}\n}\n\nvoid pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr)\n{\n\tSHA512_CTX ctx;\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tREVERSE32(blocknr, blocknr);\n#endif\n\n\tubtc_hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig);\n\tmemzero(pctx->g, sizeof(pctx->g));\n\tpctx->g[8] = 0x8000000000000000;\n\tpctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8;\n\n\tmemcpy (ctx.state, pctx->idig, sizeof(pctx->idig));\n\tctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8;\n\tctx.bitcount[1] = 0;\n\tsha512_Update(&ctx, salt, saltlen);\n\tsha512_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr));\n\tsha512_Final(&ctx, (uint8_t*)pctx->g);\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tfor (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {\n\t\tREVERSE64(pctx->g[k], pctx->g[k]);\n\t}\n#endif\n\tsha512_Transform(pctx->odig, pctx->g, pctx->g);\n\tmemcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH);\n\tpctx->first = 1;\n}\n\nvoid pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations)\n{\n\tfor (uint32_t i = pctx->first; i < iterations; i++) {\n\t\tsha512_Transform(pctx->idig, pctx->g, pctx->g);\n\t\tsha512_Transform(pctx->odig, pctx->g, pctx->g);\n\t\tfor (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) {\n\t\t\tpctx->f[j] ^= pctx->g[j];\n\t\t}\n\t}\n\tpctx->first = 0;\n}\n\nvoid pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key)\n{\n#if BYTE_ORDER == LITTLE_ENDIAN\n\tfor (uint32_t k = 0; k < SHA512_DIGEST_LENGTH/sizeof(uint64_t); k++) {\n\t\tREVERSE64(pctx->f[k], pctx->f[k]);\n\t}\n#endif\n\tmemcpy(key, pctx->f, SHA512_DIGEST_LENGTH);\n\tmemzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));\n}\n\nvoid pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen)\n{\n\tuint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH;\n\tuint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH;\n\tif (last_block_size) {\n\t\tblocks_count++;\n\t} else {\n\t\tlast_block_size = SHA512_DIGEST_LENGTH;\n\t}\n\tfor (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {\n\t\tPBKDF2_HMAC_SHA512_CTX pctx;\n\t\tpbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr);\n\t\tpbkdf2_hmac_sha512_Update(&pctx, iterations);\n\t\tuint8_t digest[SHA512_DIGEST_LENGTH];\n\t\tpbkdf2_hmac_sha512_Final(&pctx, digest);\n\t\tuint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH;\n\t\tif (blocknr < blocks_count) {\n\t\t\tmemcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH);\n\t\t} else {\n\t\t\tmemcpy(key + key_offset, digest, last_block_size);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/utility/trezor/pbkdf2.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __PBKDF2_H__\n#define __PBKDF2_H__\n\n#include <stdint.h>\n#include \"sha2.h\"\n\ntypedef struct _PBKDF2_HMAC_SHA256_CTX {\n\tuint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];\n\tuint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];\n\tuint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];\n\tuint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];\n\tchar first;\n} PBKDF2_HMAC_SHA256_CTX;\n\ntypedef struct _PBKDF2_HMAC_SHA512_CTX {\n\tuint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];\n\tuint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];\n\tuint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];\n\tuint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];\n\tchar first;\n} PBKDF2_HMAC_SHA512_CTX;\n\nvoid pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr);\nvoid pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations);\nvoid pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key);\nvoid pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen);\n\nvoid pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr);\nvoid pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations);\nvoid pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key);\nvoid pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen);\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/rand.c",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n// Node: heavily edited by uBitcoin developers with inspiration from micropython source code.\n\n#include \"rand.h\"\n#include \"sha2.h\"\n#include <string.h>\n\n// esp boards\n#if defined(ESP_PLATFORM)\n\n  #include <esp_system.h>\n  uint32_t __attribute__((weak)) random32(void){\n    return esp_random();\n  }\n\n#elif defined(ESP8266)\n  // see http://esp8266-re.foogod.com/wiki/Random_Number_Generator\n  #define WDEV_HWRNG ((volatile uint32_t*)0x3ff20e44)\n  uint32_t __attribute__((weak)) random32(void){\n    uint32_t rngint = 0;\n    uint32_t v = 0;\n    for(int i=0; i<4; i++){\n      v = (*WDEV_HWRNG);\n      rngint = (rngint << 8) | v;\n    }\n    return rngint;\n  }\n\n// stm boards\n#elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32G0)\n\n  #if defined(RNG)\n\n    // taken from micropython source code\n    #define RNG_TIMEOUT_MS (10)\n\n    uint32_t __attribute__((weak)) random32(void) {\n        // Enable the RNG peripheral if it's not already enabled\n        if (!(RNG->CR & RNG_CR_RNGEN)) {\n            #if defined(STM32H7)\n            // Set RNG Clock source\n            __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);\n            __HAL_RCC_RNG_CONFIG(RCC_RNGCLKSOURCE_PLL);\n            #endif\n            __HAL_RCC_RNG_CLK_ENABLE();\n            RNG->CR |= RNG_CR_RNGEN;\n        }\n\n        // Wait for a new random number to be ready, takes on the order of 10us\n        uint32_t start = HAL_GetTick();\n        while (!(RNG->SR & RNG_SR_DRDY)) {\n            if (HAL_GetTick() - start >= RNG_TIMEOUT_MS) {\n                return 0;\n            }\n        }\n\n        // Get and return the new random number\n        return RNG->DR;\n    }\n  #else\n\n    // fallback to prng\n    #define UBTC_USE_PRNG\n\n  #endif // defined RNG\n\n// PC\n#elif defined(__unix__) || defined(__APPLE__) || defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) || defined(__ANDROID__)\n\n// rand from os random source\n#include <stdlib.h>\n\nuint32_t __attribute__((weak)) random32(void){\n    return (uint32_t)rand();\n}\n\n#else\n\n// fallback to prng\n#define UBTC_USE_PRNG\n\n#endif\n\n// fallback option if no RNG on this platform\n#ifdef UBTC_USE_PRNG\n\n#pragma message(\"\\nWARGNING! RANDOM NUMBER GENERATOR IS NOT SUPPORTED ON THIS PLATFORM! \\n\\\nPseudo-random generator will be used unless you define\\n\\\nyour own random function like so: \\n\\n\\\nextern \\\"C\\\" { \\n\\\n  uint32_t random32(){\\n\\\n    ...get random value somehow...\\n\\\n    return value;\\n\\\n  }\\n\\\n}\")\n\n\nuint32_t __attribute__((weak)) random32(void) {\n    static uint32_t pad = 0xeda4baba, n = 69, d = 233;\n    static uint8_t dat = 0;\n\n    pad += dat + d * n;\n    pad = (pad << 3) + (pad >> 29);\n    n = pad | 2;\n    d ^= (pad << 31) + (pad >> 1);\n    dat ^= (char)pad ^ (d >> 8) ^ 1;\n\n    return pad ^ (d << 5) ^ (pad >> 18) ^ (dat << 1);\n}\n\n#endif // UBTC_USE_PRNG\n\n//\n// The following code is platform independent\n//\n\nvoid __attribute__((weak)) random_buffer(uint8_t *buf, size_t len)\n{\n\tuint32_t r = 0;\n\tfor (size_t i = 0; i < len; i++) {\n\t\tif (i % 4 == 0) {\n\t\t\tr = random32();\n\t\t}\n\t\tbuf[i] = (r >> ((i % 4) * 8)) & 0xFF;\n\t}\n}\n\nuint32_t random_uniform(uint32_t n)\n{\n\tuint32_t x, max = 0xFFFFFFFF - (0xFFFFFFFF % n);\n\twhile ((x = random32()) >= max);\n\treturn x / (max / n);\n}\n\nvoid random_permute(char *str, size_t len)\n{\n\tfor (int i = len - 1; i >= 1; i--) {\n\t\tint j = random_uniform(i + 1);\n\t\tchar t = str[j];\n\t\tstr[j] = str[i];\n\t\tstr[i] = t;\n\t}\n}\n"
  },
  {
    "path": "src/utility/trezor/rand.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __RAND_H__\n#define __RAND_H__\n\n#include <stdint.h>\n#include <stdlib.h>\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nuint32_t random32(void);\nvoid random_buffer(uint8_t *buf, size_t len);\n\nuint32_t random_uniform(uint32_t n);\nvoid random_permute(char *buf, size_t len);\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/rfc6979.c",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n * Copyright (c)      2015 Jochen Hoenicke\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include <string.h>\n#include \"rfc6979.h\"\n#include \"hmac.h\"\n#include \"memzero.h\"\n\nvoid init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) {\n\tuint8_t bx[2*32];\n\tuint8_t buf[32 + 1 + 2*32];\n\n\tmemcpy(bx, priv_key, 32);\n\tmemcpy(bx+32, hash, 32);\n\n\tmemset(state->v, 1, sizeof(state->v));\n\tmemset(state->k, 0, sizeof(state->k));\n\n\tmemcpy(buf, state->v, sizeof(state->v));\n\tbuf[sizeof(state->v)] = 0x00;\n\tmemcpy(buf + sizeof(state->v) + 1, bx, 64);\n\tubtc_hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k);\n\tubtc_hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);\n\n\tmemcpy(buf, state->v, sizeof(state->v));\n\tbuf[sizeof(state->v)] = 0x01;\n\tmemcpy(buf + sizeof(state->v) + 1, bx, 64);\n\tubtc_hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k);\n\tubtc_hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);\n\n\tmemzero(bx, sizeof(bx));\n\tmemzero(buf, sizeof(buf));\n}\n\n// generate next number from deterministic random number generator\nvoid generate_rfc6979(uint8_t rnd[32], rfc6979_state *state)\n{\n\tuint8_t buf[32 + 1];\n\n\tubtc_hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);\n\tmemcpy(buf, state->v, sizeof(state->v));\n\tbuf[sizeof(state->v)] = 0x00;\n\tubtc_hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k);\n\tubtc_hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);\n\tmemcpy(rnd, buf, 32);\n\tmemzero(buf, sizeof(buf));\n}\n\n// generate K in a deterministic way, according to RFC6979\n// http://tools.ietf.org/html/rfc6979\nvoid generate_k_rfc6979(bignum256 *k, rfc6979_state *state)\n{\n\tuint8_t buf[32];\n\tgenerate_rfc6979(buf, state);\n\tbn_read_be(buf, k);\n\tmemzero(buf, sizeof(buf));\n}\n"
  },
  {
    "path": "src/utility/trezor/rfc6979.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n * Copyright (c) 2015-2017 Jochen Hoenicke\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __RFC6979_H__\n#define __RFC6979_H__\n\n#include <stdint.h>\n#include \"bignum.h\"\n\n// rfc6979 pseudo random number generator state\ntypedef struct {\n\tuint8_t v[32], k[32];\n} rfc6979_state;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nvoid init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *rng);\nvoid generate_rfc6979(uint8_t rnd[32], rfc6979_state *rng);\nvoid generate_k_rfc6979(bignum256 *k, rfc6979_state *rng);\n\n#ifdef __cplusplus\n} /* end of extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/ripemd160.c",
    "content": "/*\n *  RIPE MD-160 implementation\n *\n *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\n *  SPDX-License-Identifier: Apache-2.0\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n *  not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *  This file is part of mbed TLS (https://tls.mbed.org)\n */\n\n/*\n *  The RIPEMD-160 algorithm was designed by RIPE in 1996\n *  http://homes.esat.kuleuven.be/~bosselae/ripemd160.html\n *  http://ehash.iaik.tugraz.at/wiki/RIPEMD-160\n */\n\n#include <string.h>\n\n#include \"ripemd160.h\"\n#include \"memzero.h\"\n\n/*\n * 32-bit integer manipulation macros (little endian)\n */\n#ifndef GET_UINT32_LE\n#define GET_UINT32_LE(n,b,i)                            \\\n{                                                       \\\n    (n) = ( (uint32_t) (b)[(i)    ]       )             \\\n        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \\\n        | ( (uint32_t) (b)[(i) + 2] << 16 )             \\\n        | ( (uint32_t) (b)[(i) + 3] << 24 );            \\\n}\n#endif\n\n#ifndef PUT_UINT32_LE\n#define PUT_UINT32_LE(n,b,i)                                    \\\n{                                                               \\\n    (b)[(i)    ] = (uint8_t) ( ( (n)       ) & 0xFF );    \\\n    (b)[(i) + 1] = (uint8_t) ( ( (n) >>  8 ) & 0xFF );    \\\n    (b)[(i) + 2] = (uint8_t) ( ( (n) >> 16 ) & 0xFF );    \\\n    (b)[(i) + 3] = (uint8_t) ( ( (n) >> 24 ) & 0xFF );    \\\n}\n#endif\n\n/*\n * RIPEMD-160 context setup\n */\nvoid ripemd160_Init(RIPEMD160_CTX *ctx)\n{\n    memset(ctx, 0, sizeof(RIPEMD160_CTX));\n    ctx->total[0] = 0;\n    ctx->total[1] = 0;\n    ctx->state[0] = 0x67452301;\n    ctx->state[1] = 0xEFCDAB89;\n    ctx->state[2] = 0x98BADCFE;\n    ctx->state[3] = 0x10325476;\n    ctx->state[4] = 0xC3D2E1F0;\n}\n\n#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT)\n/*\n * Process one block\n */\nvoid ripemd160_process( RIPEMD160_CTX *ctx, const uint8_t data[RIPEMD160_BLOCK_LENGTH] )\n{\n    uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16];\n\n    GET_UINT32_LE( X[ 0], data,  0 );\n    GET_UINT32_LE( X[ 1], data,  4 );\n    GET_UINT32_LE( X[ 2], data,  8 );\n    GET_UINT32_LE( X[ 3], data, 12 );\n    GET_UINT32_LE( X[ 4], data, 16 );\n    GET_UINT32_LE( X[ 5], data, 20 );\n    GET_UINT32_LE( X[ 6], data, 24 );\n    GET_UINT32_LE( X[ 7], data, 28 );\n    GET_UINT32_LE( X[ 8], data, 32 );\n    GET_UINT32_LE( X[ 9], data, 36 );\n    GET_UINT32_LE( X[10], data, 40 );\n    GET_UINT32_LE( X[11], data, 44 );\n    GET_UINT32_LE( X[12], data, 48 );\n    GET_UINT32_LE( X[13], data, 52 );\n    GET_UINT32_LE( X[14], data, 56 );\n    GET_UINT32_LE( X[15], data, 60 );\n\n    A = Ap = ctx->state[0];\n    B = Bp = ctx->state[1];\n    C = Cp = ctx->state[2];\n    D = Dp = ctx->state[3];\n    E = Ep = ctx->state[4];\n\n#define F1( x, y, z )   ( x ^ y ^ z )\n#define F2( x, y, z )   ( ( x & y ) | ( ~x & z ) )\n#define F3( x, y, z )   ( ( x | ~y ) ^ z )\n#define F4( x, y, z )   ( ( x & z ) | ( y & ~z ) )\n#define F5( x, y, z )   ( x ^ ( y | ~z ) )\n\n#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) )\n\n#define P( a, b, c, d, e, r, s, f, k )      \\\n    a += f( b, c, d ) + X[r] + k;           \\\n    a = S( a, s ) + e;                      \\\n    c = S( c, 10 );\n\n#define P2( a, b, c, d, e, r, s, rp, sp )   \\\n    P( a, b, c, d, e, r, s, F, K );         \\\n    P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp );\n\n#define F   F1\n#define K   0x00000000\n#define Fp  F5\n#define Kp  0x50A28BE6\n    P2( A, B, C, D, E,  0, 11,  5,  8 );\n    P2( E, A, B, C, D,  1, 14, 14,  9 );\n    P2( D, E, A, B, C,  2, 15,  7,  9 );\n    P2( C, D, E, A, B,  3, 12,  0, 11 );\n    P2( B, C, D, E, A,  4,  5,  9, 13 );\n    P2( A, B, C, D, E,  5,  8,  2, 15 );\n    P2( E, A, B, C, D,  6,  7, 11, 15 );\n    P2( D, E, A, B, C,  7,  9,  4,  5 );\n    P2( C, D, E, A, B,  8, 11, 13,  7 );\n    P2( B, C, D, E, A,  9, 13,  6,  7 );\n    P2( A, B, C, D, E, 10, 14, 15,  8 );\n    P2( E, A, B, C, D, 11, 15,  8, 11 );\n    P2( D, E, A, B, C, 12,  6,  1, 14 );\n    P2( C, D, E, A, B, 13,  7, 10, 14 );\n    P2( B, C, D, E, A, 14,  9,  3, 12 );\n    P2( A, B, C, D, E, 15,  8, 12,  6 );\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n#define F   F2\n#define K   0x5A827999\n#define Fp  F4\n#define Kp  0x5C4DD124\n    P2( E, A, B, C, D,  7,  7,  6,  9 );\n    P2( D, E, A, B, C,  4,  6, 11, 13 );\n    P2( C, D, E, A, B, 13,  8,  3, 15 );\n    P2( B, C, D, E, A,  1, 13,  7,  7 );\n    P2( A, B, C, D, E, 10, 11,  0, 12 );\n    P2( E, A, B, C, D,  6,  9, 13,  8 );\n    P2( D, E, A, B, C, 15,  7,  5,  9 );\n    P2( C, D, E, A, B,  3, 15, 10, 11 );\n    P2( B, C, D, E, A, 12,  7, 14,  7 );\n    P2( A, B, C, D, E,  0, 12, 15,  7 );\n    P2( E, A, B, C, D,  9, 15,  8, 12 );\n    P2( D, E, A, B, C,  5,  9, 12,  7 );\n    P2( C, D, E, A, B,  2, 11,  4,  6 );\n    P2( B, C, D, E, A, 14,  7,  9, 15 );\n    P2( A, B, C, D, E, 11, 13,  1, 13 );\n    P2( E, A, B, C, D,  8, 12,  2, 11 );\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n#define F   F3\n#define K   0x6ED9EBA1\n#define Fp  F3\n#define Kp  0x6D703EF3\n    P2( D, E, A, B, C,  3, 11, 15,  9 );\n    P2( C, D, E, A, B, 10, 13,  5,  7 );\n    P2( B, C, D, E, A, 14,  6,  1, 15 );\n    P2( A, B, C, D, E,  4,  7,  3, 11 );\n    P2( E, A, B, C, D,  9, 14,  7,  8 );\n    P2( D, E, A, B, C, 15,  9, 14,  6 );\n    P2( C, D, E, A, B,  8, 13,  6,  6 );\n    P2( B, C, D, E, A,  1, 15,  9, 14 );\n    P2( A, B, C, D, E,  2, 14, 11, 12 );\n    P2( E, A, B, C, D,  7,  8,  8, 13 );\n    P2( D, E, A, B, C,  0, 13, 12,  5 );\n    P2( C, D, E, A, B,  6,  6,  2, 14 );\n    P2( B, C, D, E, A, 13,  5, 10, 13 );\n    P2( A, B, C, D, E, 11, 12,  0, 13 );\n    P2( E, A, B, C, D,  5,  7,  4,  7 );\n    P2( D, E, A, B, C, 12,  5, 13,  5 );\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n#define F   F4\n#define K   0x8F1BBCDC\n#define Fp  F2\n#define Kp  0x7A6D76E9\n    P2( C, D, E, A, B,  1, 11,  8, 15 );\n    P2( B, C, D, E, A,  9, 12,  6,  5 );\n    P2( A, B, C, D, E, 11, 14,  4,  8 );\n    P2( E, A, B, C, D, 10, 15,  1, 11 );\n    P2( D, E, A, B, C,  0, 14,  3, 14 );\n    P2( C, D, E, A, B,  8, 15, 11, 14 );\n    P2( B, C, D, E, A, 12,  9, 15,  6 );\n    P2( A, B, C, D, E,  4,  8,  0, 14 );\n    P2( E, A, B, C, D, 13,  9,  5,  6 );\n    P2( D, E, A, B, C,  3, 14, 12,  9 );\n    P2( C, D, E, A, B,  7,  5,  2, 12 );\n    P2( B, C, D, E, A, 15,  6, 13,  9 );\n    P2( A, B, C, D, E, 14,  8,  9, 12 );\n    P2( E, A, B, C, D,  5,  6,  7,  5 );\n    P2( D, E, A, B, C,  6,  5, 10, 15 );\n    P2( C, D, E, A, B,  2, 12, 14,  8 );\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n#define F   F5\n#define K   0xA953FD4E\n#define Fp  F1\n#define Kp  0x00000000\n    P2( B, C, D, E, A,  4,  9, 12,  8 );\n    P2( A, B, C, D, E,  0, 15, 15,  5 );\n    P2( E, A, B, C, D,  5,  5, 10, 12 );\n    P2( D, E, A, B, C,  9, 11,  4,  9 );\n    P2( C, D, E, A, B,  7,  6,  1, 12 );\n    P2( B, C, D, E, A, 12,  8,  5,  5 );\n    P2( A, B, C, D, E,  2, 13,  8, 14 );\n    P2( E, A, B, C, D, 10, 12,  7,  6 );\n    P2( D, E, A, B, C, 14,  5,  6,  8 );\n    P2( C, D, E, A, B,  1, 12,  2, 13 );\n    P2( B, C, D, E, A,  3, 13, 13,  6 );\n    P2( A, B, C, D, E,  8, 14, 14,  5 );\n    P2( E, A, B, C, D, 11, 11,  0, 15 );\n    P2( D, E, A, B, C,  6,  8,  3, 13 );\n    P2( C, D, E, A, B, 15,  5,  9, 11 );\n    P2( B, C, D, E, A, 13,  6, 11, 11 );\n#undef F\n#undef K\n#undef Fp\n#undef Kp\n\n    C             = ctx->state[1] + C + Dp;\n    ctx->state[1] = ctx->state[2] + D + Ep;\n    ctx->state[2] = ctx->state[3] + E + Ap;\n    ctx->state[3] = ctx->state[4] + A + Bp;\n    ctx->state[4] = ctx->state[0] + B + Cp;\n    ctx->state[0] = C;\n}\n#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */\n\n/*\n * RIPEMD-160 process buffer\n */\nvoid ripemd160_Update( RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen )\n{\n    uint32_t fill;\n    uint32_t left;\n\n    if( ilen == 0 )\n        return;\n\n    left = ctx->total[0] & 0x3F;\n    fill = RIPEMD160_BLOCK_LENGTH - left;\n\n    ctx->total[0] += (uint32_t) ilen;\n    ctx->total[0] &= 0xFFFFFFFF;\n\n    if( ctx->total[0] < (uint32_t) ilen )\n        ctx->total[1]++;\n\n    if( left && ilen >= fill )\n    {\n        memcpy( (void *) (ctx->buffer + left), input, fill );\n        ripemd160_process( ctx, ctx->buffer );\n        input += fill;\n        ilen  -= fill;\n        left = 0;\n    }\n\n    while( ilen >= RIPEMD160_BLOCK_LENGTH )\n    {\n        ripemd160_process( ctx, input );\n        input += RIPEMD160_BLOCK_LENGTH;\n        ilen  -= RIPEMD160_BLOCK_LENGTH;\n    }\n\n    if( ilen > 0 )\n    {\n        memcpy( (void *) (ctx->buffer + left), input, ilen );\n    }\n}\n\nstatic const uint8_t ripemd160_padding[RIPEMD160_BLOCK_LENGTH] =\n{\n 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n};\n\n/*\n * RIPEMD-160 final digest\n */\nvoid ripemd160_Final( RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH] )\n{\n    uint32_t last, padn;\n    uint32_t high, low;\n    uint8_t msglen[8];\n\n    high = ( ctx->total[0] >> 29 )\n         | ( ctx->total[1] <<  3 );\n    low  = ( ctx->total[0] <<  3 );\n\n    PUT_UINT32_LE( low,  msglen, 0 );\n    PUT_UINT32_LE( high, msglen, 4 );\n\n    last = ctx->total[0] & 0x3F;\n    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );\n\n    ripemd160_Update( ctx, ripemd160_padding, padn );\n    ripemd160_Update( ctx, msglen, 8 );\n\n    PUT_UINT32_LE( ctx->state[0], output,  0 );\n    PUT_UINT32_LE( ctx->state[1], output,  4 );\n    PUT_UINT32_LE( ctx->state[2], output,  8 );\n    PUT_UINT32_LE( ctx->state[3], output, 12 );\n    PUT_UINT32_LE( ctx->state[4], output, 16 );\n\n    memzero(ctx, sizeof(RIPEMD160_CTX));\n}\n\n/*\n * output = RIPEMD-160( input buffer )\n */\nvoid ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH])\n{\n    RIPEMD160_CTX ctx;\n    ripemd160_Init( &ctx );\n    ripemd160_Update( &ctx, msg, msg_len );\n    ripemd160_Final( &ctx, hash );\n}\n"
  },
  {
    "path": "src/utility/trezor/ripemd160.h",
    "content": "#ifndef __RIPEMD160_H__\n#define __RIPEMD160_H__\n\n#include <stdint.h>\n\n#define RIPEMD160_BLOCK_LENGTH   64\n#define RIPEMD160_DIGEST_LENGTH  20\n\ntypedef struct _RIPEMD160_CTX {\n    uint32_t total[2];    /*!< number of bytes processed  */\n    uint32_t state[5];    /*!< intermediate digest state  */\n    uint8_t buffer[RIPEMD160_BLOCK_LENGTH];   /*!< data block being processed */\n} RIPEMD160_CTX;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nvoid ripemd160_Init(RIPEMD160_CTX *ctx);\nvoid ripemd160_Update(RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen);\nvoid ripemd160_Final(RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH]);\nvoid ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH]);\n\n#ifdef __cplusplus\n} /* end of extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/secp256k1.c",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#include \"secp256k1.h\"\n\nconst ecdsa_curve secp256k1 = {\n\t/* .prime */ {\n\t\t/*.val =*/ {0x3ffffc2f, 0x3ffffffb, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}\n\t},\n\n\t/* G */ {\n\t\t/*.x =*/{/*.val =*/{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb, 0x70b0702, 0x18a573a, 0xbbac55a, 0x199fbe77, 0x79be}},\n\t\t/*.y =*/{/*.val =*/{0x3b10d4b8, 0x311f423f, 0x28554199, 0x5ed1229, 0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8, 0x483a}}\n\t},\n\n\t/* order */ {\n\t\t/*.val =*/{0x10364141, 0x3f497a33, 0x348a03bb, 0x2bb739ab, 0x3ffffeba, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}\n\t},\n\n\t/* order_half */ {\n\t\t/*.val =*/{0x281b20a0, 0x3fa4bd19, 0x3a4501dd, 0x15db9cd5, 0x3fffff5d, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x7fff}\n\t},\n\n\t/* a */\t0,\n\n\t/* b */ {\n\t\t/*.val =*/{7}\n\t}\n\n#if USE_PRECOMPUTED_CP\n\t,\n\t/* cp */ {\n#include \"secp256k1.table\"\n\t}\n#endif\n};\n\nconst curve_info secp256k1_info = {\n\t.bip32_name = \"Bitcoin seed\",\n\t.params = &secp256k1,\n\t.hasher_base58 = HASHER_SHA2D,\n\t.hasher_sign = HASHER_SHA2D,\n\t.hasher_pubkey = HASHER_SHA2_RIPEMD,\n\t.hasher_script = HASHER_SHA2,\n};\n\n// const curve_info secp256k1_decred_info = {\n// \t.bip32_name = \"Bitcoin seed\",\n// \t.params = &secp256k1,\n// \t.hasher_base58 = HASHER_BLAKED,\n// \t.hasher_sign = HASHER_BLAKE,\n// \t.hasher_pubkey = HASHER_BLAKE_RIPEMD,\n// \t.hasher_script = HASHER_BLAKE,\n// };\n//\n// const curve_info secp256k1_groestl_info = {\n// \t.bip32_name = \"Bitcoin seed\",\n// \t.params = &secp256k1,\n// \t.hasher_base58 = HASHER_GROESTLD_TRUNC,\n// \t.hasher_sign = HASHER_SHA2,\n// \t.hasher_pubkey = HASHER_SHA2_RIPEMD,\n// \t.hasher_script = HASHER_SHA2,\n// };\n//\n// const curve_info secp256k1_smart_info = {\n// \t.bip32_name = \"Bitcoin seed\",\n// \t.params = &secp256k1,\n// \t.hasher_base58 = HASHER_SHA3K,\n// \t.hasher_sign = HASHER_SHA2,\n// \t.hasher_pubkey = HASHER_SHA2_RIPEMD,\n// \t.hasher_script = HASHER_SHA2,\n// };\n"
  },
  {
    "path": "src/utility/trezor/secp256k1.h",
    "content": "/**\n * Copyright (c) 2013-2014 Tomas Dzetkulic\n * Copyright (c) 2013-2014 Pavol Rusnak\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included\n * in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES\n * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n#ifndef __SECP256K1_H__\n#define __SECP256K1_H__\n\n#include <stdint.h>\n\n#include \"ecdsa.h\"\n#include \"bip32.h\"\n\nextern const ecdsa_curve secp256k1;\nextern const curve_info secp256k1_info;\n// extern const curve_info secp256k1_decred_info;\n// extern const curve_info secp256k1_groestl_info;\n// extern const curve_info secp256k1_smart_info;\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/secp256k1.table",
    "content": "\t{\n\t\t/*  1*16^0*G: */\n\t\t{{{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb, 0x070b0702, 0x018a573a, 0x0bbac55a, 0x199fbe77, 0x79be}},\n\t\t {{0x3b10d4b8, 0x311f423f, 0x28554199, 0x05ed1229, 0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8, 0x483a}}},\n\t\t/*  3*16^0*G: */\n\t\t{{{0x3ce036f9, 0x1807c44e, 0x36f99b08, 0x0c721160, 0x1d5229b5, 0x113e17e2, 0x0c310493, 0x22806496, 0xf930}},\n\t\t {{0x04b8e672, 0x32e7f5d6, 0x0c2231b6, 0x002a664d, 0x37f35665, 0x0cdf98a8, 0x1e8140fe, 0x1ec3d8cb, 0x388f}}},\n\t\t/*  5*16^0*G: */\n\t\t{{{0x3240efe4, 0x2ea355a6, 0x0619ab7c, 0x22e12f77, 0x1c5128e8, 0x129c9429, 0x3209355b, 0x37934681, 0x2f8b}},\n\t\t {{0x26ac62d6, 0x32a1f4ea, 0x30d6840d, 0x2209c6ea, 0x09c426f7, 0x2ea7769b, 0x1e3d6d4d, 0x08898db9, 0xd8ac}}},\n\t\t/*  7*16^0*G: */\n\t\t{{{0x0ac4f9bc, 0x24af77b7, 0x330e39ce, 0x1066df80, 0x2a7a0e3d, 0x23cd97cb, 0x1b4eaa39, 0x3c191b97, 0x5cbd}},\n\t\t {{0x087264da, 0x142098a0, 0x3fde7b5a, 0x04f42e04, 0x1a54dba8, 0x1e35b618, 0x15960a31, 0x32902e89, 0x6aeb}}},\n\t\t/*  9*16^0*G: */\n\t\t{{{0x3c27ccbe, 0x0d7c4437, 0x057e714c, 0x25e5a5d3, 0x159abde0, 0x345e2a7d, 0x3f65309a, 0x2138bc31, 0xacd4}},\n\t\t {{0x064f9c37, 0x173098ab, 0x35f8e0f0, 0x3622290d, 0x3b61e9ad, 0x2025c5d8, 0x3d9fd643, 0x22486c29, 0xcc33}}},\n\t\t/* 11*16^0*G: */\n\t\t{{{0x1da008cb, 0x2fb05e25, 0x1c17891b, 0x126602f9, 0x065aac56, 0x1091adc3, 0x1411e5ef, 0x39fe162a, 0x774a}},\n\t\t {{0x0953c61b, 0x0075d327, 0x3f9d6a83, 0x0b6c78b7, 0x37b36537, 0x0f755b5e, 0x35e19024, 0x280cbada, 0xd984}}},\n\t\t/* 13*16^0*G: */\n\t\t{{{0x19405aa8, 0x3bb77e3c, 0x10e58cdd, 0x1d7ef198, 0x348651b0, 0x0748170d, 0x1288bc7d, 0x1cf0b65d, 0xf287}},\n\t\t {{0x1b03ed81, 0x26d72d4b, 0x21fa91f2, 0x0681b694, 0x0daf473a, 0x084bad97, 0x00a89758, 0x240ba362, 0x0ab0}}},\n\t\t/* 15*16^0*G: */\n\t\t{{{0x227e080e, 0x12b6f3e3, 0x085f79e4, 0x39651bcf, 0x1ff41131, 0x196b8c25, 0x3ea965a4, 0x1353df50, 0xd792}},\n\t\t {{0x36a26b58, 0x1413727f, 0x096d3a5c, 0x102bcaf6, 0x0c6defea, 0x10bb08a3, 0x072a6838, 0x0a1caa1b, 0x581e}}}\n\t},\n\t{\n\t\t/*  1*16^1*G: */\n\t\t{{{0x2a6dec0a, 0x113ba278, 0x07a5ae9c, 0x28c4da6e, 0x023e97b2, 0x06aaf087, 0x29ec5301, 0x33a4ed67, 0xe60f}},\n\t\t {{0x29616821, 0x07ccb339, 0x0d23f0be, 0x25a24791, 0x39371012, 0x267cd3d5, 0x195929db, 0x141ce679, 0xf7e3}}},\n\t\t/*  3*16^1*G: */\n\t\t{{{0x1118e5c3, 0x2f61c2a8, 0x12bebc19, 0x15e6c9d1, 0x265b4bfc, 0x0595bbd3, 0x1307db44, 0x0cd76591, 0x6eca}},\n\t\t {{0x05a08668, 0x2628bde0, 0x3f8ec344, 0x125a8e8e, 0x3875a03a, 0x3d5e41d2, 0x20710592, 0x08ed5e9e, 0xd501}}},\n\t\t/*  5*16^1*G: */\n\t\t{{{0x0f87f62e, 0x3b34c785, 0x37161270, 0x39b98e18, 0x0659f010, 0x31d13b4d, 0x390ec0d7, 0x0eefbc6f, 0xe962}},\n\t\t {{0x244ee737, 0x0c04fabe, 0x168844e5, 0x1810f277, 0x1aa929fe, 0x3a54ea3b, 0x299e9e0f, 0x1d0ed2f0, 0x38a9}}},\n\t\t/*  7*16^1*G: */\n\t\t{{{0x2a8d733c, 0x2c2ab7e0, 0x2fca8f9e, 0x309d2fd8, 0x00d682ff, 0x128dbc82, 0x21dba088, 0x375cf945, 0xbc82}},\n\t\t {{0x347797f0, 0x39e18413, 0x33897301, 0x24e82eb9, 0x1f02dfae, 0x26d2fdc6, 0x31cac54a, 0x230e8112, 0xe5f2}}},\n\t\t/*  9*16^1*G: */\n\t\t{{{0x1fbc7671, 0x1fbf88c5, 0x2858e32d, 0x0fc6f214, 0x18f49074, 0x0a47385e, 0x17211d20, 0x049231d9, 0x8e3d}},\n\t\t {{0x18717dec, 0x3bc77190, 0x23e144a7, 0x0d4aeaa9, 0x13e90eb9, 0x1203864e, 0x3cb81f64, 0x123843b3, 0x099a}}},\n\t\t/* 11*16^1*G: */\n\t\t{{{0x3eb31db2, 0x0ca1d0ca, 0x0f506a0f, 0x32ba09e2, 0x08a2b68f, 0x2864fb42, 0x0a498896, 0x246a888d, 0x78a8}},\n\t\t {{0x39fa4343, 0x01a7588e, 0x000b82d3, 0x0de6f376, 0x302df654, 0x17c9549c, 0x035cbfcf, 0x28d6fad4, 0x6912}}},\n\t\t/* 13*16^1*G: */\n\t\t{{{0x0db0e595, 0x14d23dde, 0x3a082bb6, 0x058f2e7e, 0x2076eba7, 0x38dd9605, 0x31b17d7c, 0x1e061576, 0x7d86}},\n\t\t {{0x3c733de8, 0x265478ea, 0x225d5329, 0x0de11383, 0x0f883829, 0x18b8afb5, 0x2f8772e5, 0x26b7fb21, 0xe2b9}}},\n\t\t/* 15*16^1*G: */\n\t\t{{{0x16060dfc, 0x023fbe14, 0x05e6a2a0, 0x1517e108, 0x1ab08676, 0x252e7710, 0x02ac8484, 0x0c43c016, 0xddc5}},\n\t\t {{0x27820ca8, 0x2d7e2adb, 0x3d04730f, 0x36ebf1aa, 0x0f0e9041, 0x06adb732, 0x19692019, 0x0bcebc83, 0xba0d}}}\n\t},\n\t{\n\t\t/*  1*16^2*G: */\n\t\t{{{0x15f51508, 0x191b88ff, 0x1ac1ca10, 0x30e72af5, 0x2de238d8, 0x29b8f85c, 0x209d9ea2, 0x098c84b1, 0x8282}},\n\t\t {{0x36e26caf, 0x0c6dbabf, 0x37b17bed, 0x3584eb0b, 0x360ace62, 0x095ba0c2, 0x3dfe45e8, 0x2a026155, 0x11f8}}},\n\t\t/*  3*16^2*G: */\n\t\t{{{0x257e8dfa, 0x33f032e7, 0x3c7e184f, 0x20246468, 0x298ca009, 0x28c3e2b2, 0x19c4c0d9, 0x33cbfc1e, 0x8262}},\n\t\t {{0x3bac376a, 0x173fe363, 0x314c4783, 0x2dbb4cca, 0x334f3457, 0x3b88bb16, 0x09e4e66f, 0x25788244, 0x83fd}}},\n\t\t/*  5*16^2*G: */\n\t\t{{{0x026bdb6f, 0x014b922c, 0x3734b949, 0x2906f51e, 0x299c877c, 0x0416c933, 0x0ddd5168, 0x1722c768, 0x1982}},\n\t\t {{0x049cfc9b, 0x177dc213, 0x0f6d3a6b, 0x3a7bb323, 0x359f6ceb, 0x09873253, 0x0878f320, 0x0c43c353, 0x6294}}},\n\t\t/*  7*16^2*G: */\n\t\t{{{0x3d82824c, 0x03b42548, 0x21534e65, 0x29638d17, 0x02999edf, 0x17d5bb1b, 0x0191443c, 0x361b0458, 0x6f12}},\n\t\t {{0x06eb34d0, 0x15e70d20, 0x054bc5b8, 0x07249042, 0x22376939, 0x2653cff5, 0x3bfa0875, 0x3dfd12ac, 0x5c4f}}},\n\t\t/*  9*16^2*G: */\n\t\t{{{0x1b453629, 0x1db7700b, 0x359e6030, 0x33f73703, 0x3abef645, 0x189c5a88, 0x2aa5d142, 0x231be682, 0x203a}},\n\t\t {{0x3ff89f84, 0x25c71e14, 0x1285ed45, 0x1b7ac971, 0x01061268, 0x31db457d, 0x1d9b936c, 0x02d4f797, 0x3b0f}}},\n\t\t/* 11*16^2*G: */\n\t\t{{{0x246c7ecb, 0x20c4c377, 0x1bb4ce97, 0x0ebb4ff9, 0x26e1ec9d, 0x3bdccd21, 0x34181c81, 0x32bacf40, 0x6e2a}},\n\t\t {{0x2ebc8720, 0x1124807b, 0x367512c8, 0x31c1ae46, 0x3b643afa, 0x03136bc3, 0x3ee149d8, 0x2919e5fb, 0x9e61}}},\n\t\t/* 13*16^2*G: */\n\t\t{{{0x30a4147e, 0x2dc063cf, 0x375f201e, 0x11f762fd, 0x090a5827, 0x05c5fa29, 0x1156baf6, 0x0124ba7a, 0xd5a7}},\n\t\t {{0x33fb65ff, 0x392cf2e0, 0x167f57f8, 0x3136611e, 0x1e0532f4, 0x242641d9, 0x389c6fc4, 0x09bd76ea, 0x9db5}}},\n\t\t/* 15*16^2*G: */\n\t\t{{{0x18edcec6, 0x3b76d1af, 0x3634f454, 0x018730b4, 0x2cdac6a1, 0x0fbf18c0, 0x18ba8052, 0x0466aaf8, 0x38c5}},\n\t\t {{0x1933db08, 0x15b82fec, 0x35530a64, 0x285b208a, 0x1f282f28, 0x32cb689d, 0x1732a668, 0x3748a176, 0xe649}}}\n\t},\n\t{\n\t\t/*  1*16^3*G: */\n\t\t{{{0x11e5b739, 0x0ff396d5, 0x12222ed7, 0x2e4e0cff, 0x3c846de0, 0x26731b1b, 0x3865a72f, 0x0567dca2, 0x175e}},\n\t\t {{0x29fed695, 0x3be9bffb, 0x124345c6, 0x2d6556b7, 0x371f5eac, 0x3e5e947f, 0x079eba4e, 0x1b83678f, 0xd350}}},\n\t\t/*  3*16^3*G: */\n\t\t{{{0x05041216, 0x16dfe3c7, 0x02b836a6, 0x1ccd7da1, 0x2fed523f, 0x2d67bf70, 0x3acf4128, 0x0c5ec87d, 0xda75}},\n\t\t {{0x2e708572, 0x2bb4ca61, 0x37acedad, 0x2ab01eb9, 0x2d7fc6e9, 0x27886cd0, 0x2d5f0df1, 0x2811afdc, 0x73f8}}},\n\t\t/*  5*16^3*G: */\n\t\t{{{0x2465a930, 0x0050f9c7, 0x31352fdb, 0x21fc705a, 0x02eb1e25, 0x0f16312a, 0x349d7057, 0x316d23a5, 0x1c71}},\n\t\t {{0x034638b5, 0x361cfdb3, 0x3174d471, 0x0d178fed, 0x0bb68c79, 0x0fc7ca09, 0x1fa0c271, 0x30cd3a3d, 0x4a91}}},\n\t\t/*  7*16^3*G: */\n\t\t{{{0x3adb6ee7, 0x0c636b96, 0x344a077e, 0x143750c9, 0x1b4c9c78, 0x3a0dea42, 0x1a566936, 0x12bf07cc, 0xd84e}},\n\t\t {{0x142ebed2, 0x0b555b9b, 0x2a3e6498, 0x362b25d2, 0x25de4dfd, 0x0e3563d5, 0x379ce12a, 0x20269f1e, 0xe525}}},\n\t\t/*  9*16^3*G: */\n\t\t{{{0x249e6d10, 0x253a7b3e, 0x2ac99d23, 0x02b7fceb, 0x3f6ed3f6, 0x08ae4a17, 0x2814d41b, 0x1112f799, 0xf3d4}},\n\t\t {{0x1347da3f, 0x280e3301, 0x29d6c630, 0x06b69433, 0x0a4b5bfc, 0x2e56b066, 0x0163d4ba, 0x0937e9bc, 0x0a43}}},\n\t\t/* 11*16^3*G: */\n\t\t{{{0x29d33a07, 0x232cd01b, 0x239bcab4, 0x1cbb822a, 0x3df4044e, 0x21548336, 0x01d89f90, 0x194b2767, 0xae30}},\n\t\t {{0x20a0b2a6, 0x121c303d, 0x3d7e95c7, 0x270dfd77, 0x38d5cf1c, 0x339f4cf6, 0x3fe57efc, 0x3670e358, 0x6cb9}}},\n\t\t/* 13*16^3*G: */\n\t\t{{{0x0c28caca, 0x165952e4, 0x08281da7, 0x1a71eef3, 0x388c9a18, 0x05f9d60c, 0x1e1c815e, 0x06ca96f5, 0xd8dc}},\n\t\t {{0x23b3ec7a, 0x36d9dba8, 0x08128f6c, 0x0c574b3b, 0x247d947d, 0x36369080, 0x2c7d58c6, 0x02b649f3, 0x8cec}}},\n\t\t/* 15*16^3*G: */\n\t\t{{{0x3bc4416f, 0x2487ed98, 0x30b04028, 0x2bbf48fc, 0x32f31da7, 0x1096a340, 0x04eccd59, 0x38a4b17e, 0x2749}},\n\t\t {{0x3c6bbd8e, 0x3a62f78b, 0x2e961057, 0x27a7ed97, 0x0adb3ef5, 0x3652643f, 0x32bc4403, 0x0b538dd9, 0x50cc}}}\n\t},\n\t{\n\t\t/*  1*16^4*G: */\n\t\t{{{0x03ff4640, 0x09aeb63e, 0x1552ffe5, 0x11071f95, 0x262ee053, 0x3ab016d8, 0x00c9c99c, 0x243511ec, 0x363d}},\n\t\t {{0x3bee9de9, 0x0800f1fc, 0x0199ecb6, 0x2e6a2402, 0x33363145, 0x2d114e5f, 0x32221953, 0x1ceb7f1c, 0x04e2}}},\n\t\t/*  3*16^4*G: */\n\t\t{{{0x36e55dc8, 0x2e24485b, 0x2ca04394, 0x3e56adba, 0x1094426f, 0x12910301, 0x1ffb2ba8, 0x1011e431, 0x4431}},\n\t\t {{0x1be323b3, 0x076512bb, 0x2aa2e503, 0x1a8a6de7, 0x02fed7a6, 0x260dfd59, 0x366f8fe9, 0x3050b994, 0x96b0}}},\n\t\t/*  5*16^4*G: */\n\t\t{{{0x301b23a8, 0x3fa52175, 0x287ee0ad, 0x1edf51c2, 0x21089dab, 0x090f56e4, 0x0a87c126, 0x3fa3619b, 0x9e22}},\n\t\t {{0x0884edae, 0x1e904f14, 0x3511cecf, 0x3df2527e, 0x1c1533c0, 0x3cfc0826, 0x22d10177, 0x3c3a7284, 0xfd2f}}},\n\t\t/*  7*16^4*G: */\n\t\t{{{0x071a70e4, 0x35d022fc, 0x35cf475d, 0x17b947d7, 0x05306dcd, 0x35a7991c, 0x22a8d2ed, 0x3db540f3, 0x508d}},\n\t\t {{0x29950984, 0x3cb96fdc, 0x28aadfed, 0x300c8a3b, 0x3e49c54e, 0x0c12a9cc, 0x3c42d777, 0x10e6e4ce, 0x154c}}},\n\t\t/*  9*16^4*G: */\n\t\t{{{0x0e1abe11, 0x3abf69db, 0x1cb220f6, 0x2e487096, 0x0125b2da, 0x37d6064c, 0x09763338, 0x3fe11544, 0xe3db}},\n\t\t {{0x1fa8de63, 0x2d26b552, 0x06b5c414, 0x325f640f, 0x0a8ef3d3, 0x23e9d76e, 0x01421643, 0x3e42668d, 0x06f2}}},\n\t\t/* 11*16^4*G: */\n\t\t{{{0x03593449, 0x33c6c8d8, 0x02a46ffd, 0x06df04b9, 0x3d014af6, 0x36704e81, 0x2940d878, 0x381931f7, 0x19ac}},\n\t\t {{0x2df83631, 0x29052e4e, 0x084068a3, 0x1c42e7d0, 0x002c46ac, 0x2f5ce765, 0x0a333bfe, 0x2480d49a, 0xe379}}},\n\t\t/* 13*16^4*G: */\n\t\t{{{0x0cba6b63, 0x38fa624b, 0x10b3bb5e, 0x03f99d3f, 0x288e310a, 0x30cc8a3a, 0x07daa108, 0x033b083e, 0xd874}},\n\t\t {{0x2934c5f3, 0x3ba8db01, 0x381694ab, 0x0413d730, 0x3ac37d40, 0x29bba640, 0x132bf378, 0x304cf1ae, 0x6472}}},\n\t\t/* 15*16^4*G: */\n\t\t{{{0x1b3ec038, 0x0653fcb0, 0x20c6b276, 0x3f545ab9, 0x290a50d9, 0x20f9d8bc, 0x06083648, 0x0cce46d4, 0x58ac}},\n\t\t {{0x10246279, 0x1baa8fc4, 0x34fbbca1, 0x06410f02, 0x11fe9702, 0x1e4927a6, 0x092d9787, 0x35c1b557, 0x9163}}}\n\t},\n\t{\n\t\t/*  1*16^5*G: */\n\t\t{{{0x1ffdf80c, 0x27de6957, 0x15bcd1b6, 0x3929e068, 0x05638843, 0x0912d6dd, 0x3c2be8c6, 0x17c5977c, 0x8b4b}},\n\t\t {{0x1fd4fd36, 0x0fbfc319, 0x162ee56b, 0x38cd9518, 0x30da04f9, 0x2f5e04ea, 0x308b4b3f, 0x029bda34, 0x4aad}}},\n\t\t/*  3*16^5*G: */\n\t\t{{{0x355812dd, 0x028a960b, 0x12d30e2a, 0x1119c8d5, 0x18f78e3d, 0x2afb5b01, 0x3352f0b6, 0x2f5ea4bf, 0x7029}},\n\t\t {{0x1a2d2927, 0x087319ac, 0x3b2c73c7, 0x36ba1090, 0x0683ac47, 0x19512b8c, 0x0b3d27dd, 0x3eb6bf7a, 0xb0ee}}},\n\t\t/*  5*16^5*G: */\n\t\t{{{0x3d486ed1, 0x27395a0e, 0x1565b6a4, 0x116fae92, 0x0f756057, 0x35042763, 0x25c99009, 0x3b72bab9, 0x9ccf}},\n\t\t {{0x35e95d8d, 0x3db567b5, 0x1592aa24, 0x0859d65a, 0x0b341124, 0x08920480, 0x232cfb61, 0x135c4f5a, 0x7c2f}}},\n\t\t/*  7*16^5*G: */\n\t\t{{{0x1bd0eaca, 0x081ac69d, 0x22d4ab7a, 0x31d15dae, 0x24df19d0, 0x23f78cf2, 0x1414335a, 0x12e1d8d0, 0xcd9a}},\n\t\t {{0x2bff4acc, 0x39bebed6, 0x16f634f6, 0x09ece3bb, 0x3ea08b01, 0x1222ba4c, 0x0f23e815, 0x161e687a, 0xf045}}},\n\t\t/*  9*16^5*G: */\n\t\t{{{0x07bc57c6, 0x08254e8f, 0x2b276cbf, 0x00f5e88f, 0x16309449, 0x3cb4ba4f, 0x19bea884, 0x220be23b, 0xad09}},\n\t\t {{0x2e4a0ab8, 0x28cb03b6, 0x190e2d3c, 0x0c474dcd, 0x1abe5f7b, 0x061b1ca7, 0x3a52ba28, 0x302310be, 0x7243}}},\n\t\t/* 11*16^5*G: */\n\t\t{{{0x2ba56302, 0x2a0c31ca, 0x30f1862e, 0x01aa4deb, 0x3ad2e0f5, 0x368b4aa7, 0x0a41f1ea, 0x0a42bacf, 0xd9d1}},\n\t\t {{0x08291c29, 0x2ab76bea, 0x3a74f2ae, 0x0e6bb367, 0x2386e417, 0x1c5719c9, 0x13eed029, 0x0c44fb0b, 0x7eb5}}},\n\t\t/* 13*16^5*G: */\n\t\t{{{0x34d1243a, 0x2b34dc13, 0x354a5fdb, 0x2c49808f, 0x3f558402, 0x3486b018, 0x16cef91c, 0x1e7794e7, 0xbc50}},\n\t\t {{0x055db68a, 0x172545a2, 0x1f47169f, 0x1fb93d6c, 0x3fc8d75f, 0x31cae537, 0x05cbb8ee, 0x0a8ece9c, 0x6506}}},\n\t\t/* 15*16^5*G: */\n\t\t{{{0x374a3f9f, 0x2349139a, 0x00981690, 0x21e99977, 0x32625ac2, 0x37aab9f6, 0x3c7e8913, 0x29df9417, 0x4d31}},\n\t\t {{0x301e0ba7, 0x3f2c0904, 0x2e00a754, 0x3dbed46d, 0x002753cb, 0x063ce31e, 0x0575b06b, 0x07b25826, 0x2224}}}\n\t},\n\t{\n\t\t/*  1*16^6*G: */\n\t\t{{{0x1232fcda, 0x2d845649, 0x2c0e77bc, 0x0036ffe9, 0x1548c7b7, 0x1dc7002f, 0x3996d6bf, 0x2ea9b976, 0x723c}},\n\t\t {{0x1eb39f5f, 0x07701a76, 0x37949480, 0x1828194d, 0x024d6e26, 0x044dd222, 0x0c498a92, 0x19ed5657, 0x96e8}}},\n\t\t/*  3*16^6*G: */\n\t\t{{{0x00633cb1, 0x159f827a, 0x1d021132, 0x168892da, 0x181fcb57, 0x189cc848, 0x2cad400c, 0x273cc5ea, 0x6dde}},\n\t\t {{0x27ce6b34, 0x1f7526a9, 0x3859ef35, 0x2c9ff6b3, 0x3a66a880, 0x27be1a86, 0x3e41d5c9, 0x3ef9e9c1, 0x9188}}},\n\t\t/*  5*16^6*G: */\n\t\t{{{0x2933f3c5, 0x06694634, 0x1f125224, 0x1683dc45, 0x07b85008, 0x12edfe39, 0x1cde813c, 0x29cb356d, 0x486f}},\n\t\t {{0x0afb0f53, 0x2b529c6b, 0x30f23b79, 0x366de0f3, 0x08f19f62, 0x3122ebb3, 0x3dd43e48, 0x08c67d5a, 0x62e1}}},\n\t\t/*  7*16^6*G: */\n\t\t{{{0x1e99f728, 0x2f565089, 0x2f12204e, 0x1cdd7ef9, 0x2a530367, 0x13fc9edd, 0x0af4fb66, 0x1a5d2a25, 0x2479}},\n\t\t {{0x2baaebff, 0x1e80145b, 0x175a2d83, 0x36fcf025, 0x0d664a5a, 0x0ba1f9f6, 0x33001ec5, 0x23511a23, 0xe3d7}}},\n\t\t/*  9*16^6*G: */\n\t\t{{{0x2fb0079a, 0x27831b50, 0x3926049c, 0x1be7bdc8, 0x33832491, 0x2967b9da, 0x15ff0631, 0x32f6a8f5, 0x2f39}},\n\t\t {{0x2c5690ba, 0x388a5cc0, 0x02a0230f, 0x3ecfef22, 0x0da58b9b, 0x24db409e, 0x239834da, 0x36f784e1, 0xabea}}},\n\t\t/* 11*16^6*G: */\n\t\t{{{0x24f7ab73, 0x24cc02cb, 0x14443a77, 0x38f53aa7, 0x34aed262, 0x0e7a1b14, 0x161ba56a, 0x075b0c9f, 0xe5a3}},\n\t\t {{0x30561f42, 0x244e8ff1, 0x00cba213, 0x2311126a, 0x0ece5dbf, 0x062a5de9, 0x29d7a0c1, 0x230f6347, 0x3778}}},\n\t\t/* 13*16^6*G: */\n\t\t{{{0x014dcd86, 0x23e4a68f, 0x2bf71b58, 0x31750825, 0x11dcf11f, 0x03766081, 0x13447df5, 0x27528345, 0xcc38}},\n\t\t {{0x08f0a873, 0x23adb767, 0x27e78746, 0x315f863f, 0x2910ca05, 0x1a2f6efa, 0x2bbed9b5, 0x13f5983d, 0x93ae}}},\n\t\t/* 15*16^6*G: */\n\t\t{{{0x38819311, 0x13e71bad, 0x08771472, 0x0f87b884, 0x35ed1f0b, 0x0285f833, 0x1e902375, 0x2472275c, 0x7f92}},\n\t\t {{0x2c2eb125, 0x2a7e6d5e, 0x086a174a, 0x02aa9027, 0x2415b612, 0x037a3114, 0x03ef0f5d, 0x034418fb, 0x9da0}}}\n\t},\n\t{\n\t\t/*  1*16^7*G: */\n\t\t{{{0x0e7dd7fa, 0x294cfb28, 0x3a919839, 0x11e5848d, 0x02d3b509, 0x3fbb204b, 0x2bf98ba5, 0x293524ef, 0xeebf}},\n\t\t {{0x21de8999, 0x37f53f6b, 0x311f712d, 0x393370e9, 0x38089d9a, 0x39fb6bc5, 0x2f0f269e, 0x2328e5c3, 0x5d9a}}},\n\t\t/*  3*16^7*G: */\n\t\t{{{0x3b7ceceb, 0x0fd9e3fe, 0x097faf0f, 0x2967e4e2, 0x2e681473, 0x3ee049bd, 0x2d45036f, 0x2188109d, 0x437a}},\n\t\t {{0x16c181e1, 0x0d8ef30d, 0x08f97827, 0x0883f3f7, 0x1297ff87, 0x23fada67, 0x2c32f69b, 0x1ae84fba, 0x0b91}}},\n\t\t/*  5*16^7*G: */\n\t\t{{{0x097f96f2, 0x1635ca78, 0x2c8735cd, 0x208d4a74, 0x3cc27335, 0x2df8ee68, 0x089bc83c, 0x27c4f8a9, 0xa9ef}},\n\t\t {{0x16c04be4, 0x00f556c1, 0x29b4702c, 0x13e26bd6, 0x3b613db7, 0x1bb8583a, 0x19d7cd95, 0x33396515, 0xe814}}},\n\t\t/*  7*16^7*G: */\n\t\t{{{0x350cf77e, 0x302ad684, 0x0a8ab0db, 0x36fd5d15, 0x2a064207, 0x209f5a7e, 0x135be553, 0x01507b87, 0x66d8}},\n\t\t {{0x20eaa3a6, 0x297e5ebe, 0x3b1b76d2, 0x112d0ead, 0x1613f694, 0x0750814d, 0x3fb42c3f, 0x37f9ccbf, 0x51cf}}},\n\t\t/*  9*16^7*G: */\n\t\t{{{0x07213a5a, 0x0d5218a2, 0x05fa62b9, 0x1cc8129e, 0x0cc3c80b, 0x14228719, 0x03fa2bf3, 0x01784d94, 0x62ac}},\n\t\t {{0x346a9e45, 0x04348703, 0x17994efc, 0x16424060, 0x292579e5, 0x179e781e, 0x1a6e4d39, 0x2f7ce834, 0x236f}}},\n\t\t/* 11*16^7*G: */\n\t\t{{{0x27bad12b, 0x0c3f5261, 0x2f66e1ec, 0x357a803a, 0x2f2db385, 0x184ebd71, 0x08f5b5bf, 0x31125c91, 0xca13}},\n\t\t {{0x1723b0f2, 0x25a67d1a, 0x1a575668, 0x1c2adc44, 0x2da3d663, 0x17e993aa, 0x287c8ac1, 0x0260d870, 0x83aa}}},\n\t\t/* 13*16^7*G: */\n\t\t{{{0x1c80414e, 0x36bb97e5, 0x166cf7fd, 0x3be2a18b, 0x209e4914, 0x04713d11, 0x12ae85ac, 0x2c4069c1, 0x1cec}},\n\t\t {{0x12169a3b, 0x32ba524b, 0x07231d0d, 0x1d55f951, 0x2dad1690, 0x2a8ca0d7, 0x17cfb4e5, 0x1819a582, 0xf343}}},\n\t\t/* 15*16^7*G: */\n\t\t{{{0x0ed810a9, 0x13d6f231, 0x0700155c, 0x22274fcf, 0x1f23924f, 0x036bd7c7, 0x38f9cc95, 0x241d4135, 0x2a69}},\n\t\t {{0x3a9b4728, 0x3e1ace23, 0x2c145c7c, 0x1f51fa5f, 0x3b04fc66, 0x3161a553, 0x1ffdac3e, 0x00e6db0f, 0x54f9}}}\n\t},\n\t{\n\t\t/*  1*16^8*G: */\n\t\t{{{0x39a48db0, 0x3f5e0d6c, 0x33c03bfe, 0x048568a6, 0x3bde459f, 0x0742826d, 0x27167279, 0x11369a5b, 0x100f}},\n\t\t {{0x2bc65a09, 0x3ef57358, 0x35195ac0, 0x3fd2863f, 0x090666b7, 0x23ccc030, 0x00b772ec, 0x384c64a8, 0xcdd9}}},\n\t\t/*  3*16^8*G: */\n\t\t{{{0x15bc15b4, 0x32e684d2, 0x25a2ee69, 0x1d40a391, 0x17ca8d92, 0x163ba73b, 0x2adc9ed8, 0x038b947b, 0x10e9}},\n\t\t {{0x18aa258d, 0x13af9825, 0x2bb6a883, 0x296258c0, 0x2d1f754c, 0x1ea3185a, 0x1e0424d5, 0x0dc0e035, 0xc68a}}},\n\t\t/*  5*16^8*G: */\n\t\t{{{0x3fe75269, 0x374ff0c0, 0x13d33182, 0x1de8f301, 0x0b7dcda3, 0x16e42dc5, 0x01638457, 0x0bd0b695, 0xf742}},\n\t\t {{0x17e49bd5, 0x22603a1c, 0x0a398e01, 0x2ce88dfd, 0x3635977f, 0x339f72e7, 0x3093fd18, 0x0bc68cc4, 0x406c}}},\n\t\t/*  7*16^8*G: */\n\t\t{{{0x35a7175f, 0x14ed9a5b, 0x31cf42a6, 0x2e39dc74, 0x15debbed, 0x1e69560b, 0x03cff728, 0x2b4105f5, 0x2d8c}},\n\t\t {{0x3b9d592a, 0x3cdeee46, 0x0b5e5e0c, 0x211aff67, 0x2c9d377a, 0x08cbe984, 0x0a94a7bb, 0x0ee0cc63, 0xc73f}}},\n\t\t/*  9*16^8*G: */\n\t\t{{{0x14b51045, 0x0d326f0e, 0x31c25b3e, 0x31b225bc, 0x28cf73bb, 0x1cf53ac7, 0x26ea58ae, 0x3f476e62, 0x1ecb}},\n\t\t {{0x02c70026, 0x0e99c404, 0x036422d5, 0x240191ad, 0x1a9b38b1, 0x342ec612, 0x1c3a6447, 0x388c22e6, 0x1cf6}}},\n\t\t/* 11*16^8*G: */\n\t\t{{{0x29358533, 0x1eb35d9b, 0x0fb4b9df, 0x2a4cfe75, 0x132a8c10, 0x25568a47, 0x3752883e, 0x25317f95, 0x9a08}},\n\t\t {{0x0360ba08, 0x2cf87177, 0x380ddadf, 0x29b96f6e, 0x0fc32165, 0x05f57e55, 0x38fc31f9, 0x20f10806, 0xa798}}},\n\t\t/* 13*16^8*G: */\n\t\t{{{0x198ef7f6, 0x25101758, 0x2078f9f6, 0x08fcfdde, 0x38aea659, 0x272149ce, 0x3d2e35bd, 0x361276d3, 0x664d}},\n\t\t {{0x1d1eac94, 0x1d25bfcd, 0x38e6ecee, 0x0f4eacc6, 0x0458cffc, 0x12339774, 0x27932a14, 0x0805c5fc, 0xad51}}},\n\t\t/* 15*16^8*G: */\n\t\t{{{0x03c934b3, 0x03029adf, 0x30ae2c4e, 0x0c7d6016, 0x11a7022b, 0x07659a60, 0x0b863823, 0x0ea4ddf4, 0x8211}},\n\t\t {{0x042c6a0f, 0x1f9798ab, 0x24468037, 0x07df09a6, 0x20c628aa, 0x19b3cad6, 0x23666084, 0x2e36b26b, 0x8da1}}}\n\t},\n\t{\n\t\t/*  1*16^9*G: */\n\t\t{{{0x2534fd2d, 0x322b379b, 0x0f3b3852, 0x1fe35119, 0x04c017a7, 0x2489e928, 0x3ed1b1dc, 0x06f898b1, 0xe103}},\n\t\t {{0x1456a00d, 0x113c63ca, 0x21ced79a, 0x24b75067, 0x17535af2, 0x1a905d96, 0x0405e6bb, 0x1864a250, 0x9d70}}},\n\t\t/*  3*16^9*G: */\n\t\t{{{0x2f028d83, 0x1e588ebb, 0x27439615, 0x25649b6e, 0x1e69db61, 0x2af96857, 0x385ec6a5, 0x3df138f1, 0xa7eb}},\n\t\t {{0x19d0bed1, 0x1900e4ae, 0x30539199, 0x28e249d2, 0x04804b47, 0x271cddc1, 0x362d5cfd, 0x054beff8, 0x6205}}},\n\t\t/*  5*16^9*G: */\n\t\t{{{0x27dd5cfa, 0x2b839008, 0x309d4b5b, 0x227144df, 0x2346336a, 0x31a94d09, 0x24f4c1cd, 0x282372c0, 0x5b5c}},\n\t\t {{0x1e48e98c, 0x19929be6, 0x33269d3e, 0x3419f32b, 0x069094bf, 0x07c33aa2, 0x15825e99, 0x2dbdc2a8, 0x3ecc}}},\n\t\t/*  7*16^9*G: */\n\t\t{{{0x23531f82, 0x2e54a38c, 0x10c2c9f2, 0x144c9aec, 0x022c29ff, 0x3cf9d227, 0x14bb5cce, 0x09ab3044, 0x046f}},\n\t\t {{0x0bceda07, 0x1417f22c, 0x2b55c7fa, 0x09651736, 0x032579d0, 0x0dc2b0bf, 0x382eace2, 0x12cc58d6, 0x6b80}}},\n\t\t/*  9*16^9*G: */\n\t\t{{{0x10432711, 0x02c550dc, 0x1916b906, 0x0502cbf7, 0x19645acf, 0x25bc3c22, 0x0efb535f, 0x09b64c78, 0xc119}},\n\t\t {{0x2fe2610c, 0x1249878b, 0x0f34055e, 0x2ae48b28, 0x0cc6cf83, 0x252fc61b, 0x1b689184, 0x3e331f49, 0x8be1}}},\n\t\t/* 11*16^9*G: */\n\t\t{{{0x21257963, 0x05e61d3e, 0x34aa861c, 0x006354b0, 0x0979c45b, 0x2ed52d4e, 0x08f2e6cd, 0x11ba7ada, 0x6908}},\n\t\t {{0x066f9835, 0x295d9665, 0x1c92b253, 0x2f0f2a08, 0x2fbb7f6c, 0x05c093e4, 0x3ebc5b40, 0x17f2dfcf, 0xe248}}},\n\t\t/* 13*16^9*G: */\n\t\t{{{0x1ee23ace, 0x3444e52f, 0x14dd2fd2, 0x321f196d, 0x232915de, 0x1d54b7d2, 0x220babba, 0x3dfee324, 0xfb3d}},\n\t\t {{0x1722e8de, 0x0277bd32, 0x2d27f5ee, 0x1c9c50bf, 0x3ab58a9e, 0x09455036, 0x33c5652a, 0x0a6f0471, 0x510e}}},\n\t\t/* 15*16^9*G: */\n\t\t{{{0x10272351, 0x181f3fbd, 0x19ff1098, 0x1cd2cf7e, 0x31cd4170, 0x228facea, 0x0518b3eb, 0x17b093d7, 0x6dd8}},\n\t\t {{0x3fc7664b, 0x2c1fe8ad, 0x3e0817c9, 0x1f1bfdf0, 0x1c41b787, 0x101fe6bd, 0x3427e09d, 0x19fd0487, 0x16ea}}}\n\t},\n\t{\n\t\t/*  1*16^10*G: */\n\t\t{{{0x1094696d, 0x3579a236, 0x01d6af52, 0x3e2c99a9, 0x3bd7ec5c, 0x0a0e7c50, 0x15b530ac, 0x1b2b91b5, 0xfeea}},\n\t\t {{0x18090088, 0x05577afc, 0x041442d3, 0x072255f3, 0x3ecd5c98, 0x39384afc, 0x0e1bab06, 0x1adb25f7, 0xe57c}}},\n\t\t/*  3*16^10*G: */\n\t\t{{{0x08dfd587, 0x1e4d86ed, 0x1b026560, 0x312e8e32, 0x35a12d5e, 0x19eaa8b3, 0x0508b348, 0x2d06eb3d, 0x5084}},\n\t\t {{0x11470e89, 0x39e7a5fe, 0x091f5606, 0x2dbd581a, 0x2927475d, 0x2a9b2154, 0x00d31619, 0x18c68766, 0x34a9}}},\n\t\t/*  5*16^10*G: */\n\t\t{{{0x3ab34cc6, 0x0208c985, 0x0f30a12d, 0x030a5d9f, 0x0d7128c8, 0x2cfc7f46, 0x2d5ea53f, 0x300f8190, 0x4f14}},\n\t\t {{0x187e681f, 0x17b094be, 0x281dd022, 0x378f33a3, 0x262540b9, 0x0e9c3d0e, 0x0e894c65, 0x342a32a9, 0x7b53}}},\n\t\t/*  7*16^10*G: */\n\t\t{{{0x1241d90d, 0x109dc404, 0x32444f83, 0x073c5076, 0x1dd363e8, 0x10d8257b, 0x39ed1d41, 0x2e1f9271, 0xa74d}},\n\t\t {{0x3f7adad4, 0x0c9462e0, 0x0a0a313f, 0x3b9424d1, 0x0171c8a9, 0x37422962, 0x3eef327f, 0x24736bc8, 0xf786}}},\n\t\t/*  9*16^10*G: */\n\t\t{{{0x31c1ae1f, 0x17b32888, 0x2cd40b2a, 0x1b9631a2, 0x23565845, 0x373513ae, 0x2a2cf9ac, 0x3e95d12e, 0x6901}},\n\t\t {{0x122838b0, 0x3e0cc197, 0x1c77a930, 0x27cee979, 0x1c900dd7, 0x2d4e030a, 0x3c212461, 0x1722089c, 0x35de}}},\n\t\t/* 11*16^10*G: */\n\t\t{{{0x327a4bdb, 0x2c0c4206, 0x1494cac4, 0x1a9b410d, 0x3ba35d04, 0x12d90fc6, 0x38127a24, 0x360b4750, 0x8d3c}},\n\t\t {{0x269a8a2c, 0x0f4d31f3, 0x30ad296c, 0x38e01f4d, 0x36236ed4, 0x3efe7401, 0x241f470c, 0x0958603b, 0x9bd4}}},\n\t\t/* 13*16^10*G: */\n\t\t{{{0x34ec1d2d, 0x10334f1a, 0x27d8f454, 0x0267d71b, 0x3b691fd9, 0x2759ca59, 0x24739afe, 0x20d8f581, 0xeaf9}},\n\t\t {{0x0c838452, 0x33f9d581, 0x3e84b53f, 0x3d4b5515, 0x3199aaa9, 0x08a2839a, 0x38d22775, 0x060e9ff9, 0xe518}}},\n\t\t/* 15*16^10*G: */\n\t\t{{{0x045ae767, 0x32cd6fdc, 0x289771cb, 0x1cea72e7, 0x06e5d8c2, 0x103814b0, 0x1b63466f, 0x2f458ebb, 0xfb95}},\n\t\t {{0x3bbf0e11, 0x214fa82b, 0x259f1341, 0x05bd1c62, 0x02275bb8, 0x013674da, 0x0ddbc520, 0x0536046a, 0x664c}}}\n\t},\n\t{\n\t\t/*  1*16^11*G: */\n\t\t{{{0x01ec6cb1, 0x0fea5e2f, 0x08583de3, 0x3b595f60, 0x3fca3cfe, 0x1ef92f9b, 0x09cdcb36, 0x2a476441, 0xda67}},\n\t\t {{0x3a68be1d, 0x3a7aa389, 0x0f740a17, 0x31eb7142, 0x1780e5de, 0x118fdfb2, 0x242bc41f, 0x2a8d5205, 0x9bac}}},\n\t\t/*  3*16^11*G: */\n\t\t{{{0x15bc8a44, 0x3bf74194, 0x3e151a19, 0x10405df2, 0x1a5fc768, 0x159692e9, 0x0eda3d38, 0x20160f3f, 0x4d01}},\n\t\t {{0x1adbc09e, 0x3c7e5324, 0x182da362, 0x250811a1, 0x16381396, 0x26ea001f, 0x0f5d367e, 0x31b0632d, 0x3a33}}},\n\t\t/*  5*16^11*G: */\n\t\t{{{0x25daeb00, 0x306ad4a1, 0x2645f76b, 0x08fac933, 0x36e9d159, 0x32da89ce, 0x0f957082, 0x0541f7d7, 0x2f66}},\n\t\t {{0x033992c0, 0x089d9e26, 0x15d308c1, 0x337b89c6, 0x00add06e, 0x254dea08, 0x2b33f6ef, 0x0484dbd4, 0xfd5c}}},\n\t\t/*  7*16^11*G: */\n\t\t{{{0x116aa6d9, 0x20aa4282, 0x3702dcf1, 0x18b22d91, 0x035a3836, 0x3c5d3686, 0x247d2254, 0x045f417f, 0xf594}},\n\t\t {{0x3f2e50cf, 0x1f41a5ba, 0x26b5b86c, 0x249de20f, 0x14bceb7a, 0x176f6ac2, 0x31b12cf6, 0x18695ba5, 0xcaa7}}},\n\t\t/*  9*16^11*G: */\n\t\t{{{0x3ac6f4c0, 0x2ab80e55, 0x04bdc4cc, 0x13a37a33, 0x16711dda, 0x070e2f9a, 0x19cdec4e, 0x135fc7d3, 0x0f2d}},\n\t\t {{0x32339b58, 0x1f9eeeb5, 0x0242656e, 0x1a8429e4, 0x01e71e8f, 0x2c9ff7ce, 0x3de4d17f, 0x27e15fa4, 0x3ec8}}},\n\t\t/* 11*16^11*G: */\n\t\t{{{0x1f428cb2, 0x215414ff, 0x2a22b55d, 0x0e08bf59, 0x18d0f123, 0x1e860565, 0x14bbd1eb, 0x33b0b8a8, 0x1d5d}},\n\t\t {{0x095b189b, 0x397b4402, 0x36044a51, 0x0fa44be1, 0x2f0b88bd, 0x1e1e0921, 0x2c8c50d0, 0x1020ec50, 0x6e5c}}},\n\t\t/* 13*16^11*G: */\n\t\t{{{0x28381273, 0x2c3aa23e, 0x293dae5f, 0x10dda581, 0x0126ced8, 0x3aa6cb31, 0x167439fd, 0x28bf4c02, 0x89d9}},\n\t\t {{0x1309773d, 0x00facfbb, 0x1127324a, 0x1875a02b, 0x0f62f58f, 0x2abc81db, 0x26f50377, 0x096d1475, 0xdfca}}},\n\t\t/* 15*16^11*G: */\n\t\t{{{0x35c71d91, 0x330cacb2, 0x2894fd21, 0x25178b8a, 0x1afece23, 0x28704c45, 0x10ae1c52, 0x06e1e0e9, 0x8319}},\n\t\t {{0x22148a61, 0x02e7b023, 0x10445ee7, 0x2847d45d, 0x3cae8a17, 0x1b784f45, 0x01b709e0, 0x1fc55ce0, 0xe0ac}}}\n\t},\n\t{\n\t\t/*  1*16^12*G: */\n\t\t{{{0x1a37b7c0, 0x1d517330, 0x311069f5, 0x02343dee, 0x322151ec, 0x00024d7b, 0x34cdda6e, 0x13ea82cc, 0x5390}},\n\t\t {{0x022771c8, 0x372c25ac, 0x14434699, 0x26666078, 0x0d3c1c13, 0x27b32b08, 0x0106d88c, 0x21f42f20, 0x5bc0}}},\n\t\t/*  3*16^12*G: */\n\t\t{{{0x08a2050e, 0x06b10bf9, 0x15f8a677, 0x0bbd55d8, 0x079b8974, 0x1da731b9, 0x0731896b, 0x093f492f, 0x6737}},\n\t\t {{0x061d3d70, 0x24326924, 0x3349cc2b, 0x1aeb3f50, 0x086b6dbe, 0x120b026a, 0x24a20203, 0x2095e25a, 0xe4cf}}},\n\t\t/*  5*16^12*G: */\n\t\t{{{0x02de63bf, 0x2fdb920e, 0x3261c66c, 0x0ebd4ca1, 0x2166a8e0, 0x26298c7d, 0x34c309e5, 0x3be91cb7, 0x4366}},\n\t\t {{0x217924cd, 0x0b1a9023, 0x2aa6d6b0, 0x0ec31496, 0x0268eaf3, 0x094df84c, 0x2d7ce2ee, 0x36426fb8, 0x2e7d}}},\n\t\t/*  7*16^12*G: */\n\t\t{{{0x06f96190, 0x04149ffc, 0x3c9525ef, 0x3c0b7a41, 0x3aa75fd1, 0x3955a599, 0x1ab1f97b, 0x14d89e64, 0x7bd7}},\n\t\t {{0x2bda00f6, 0x0f45c812, 0x20ea695a, 0x03f31707, 0x3827d6ce, 0x3591d250, 0x26309d5e, 0x3cacf6ee, 0x8336}}},\n\t\t/*  9*16^12*G: */\n\t\t{{{0x16ad41ed, 0x0ec54c55, 0x0f035243, 0x022b0d7d, 0x18dc9203, 0x0d067a24, 0x2d5c1afa, 0x249ef76a, 0x4f7e}},\n\t\t {{0x3e642d57, 0x3d0d5e19, 0x2af775bd, 0x1cc51c53, 0x28f6a62e, 0x26037d4e, 0x08b10552, 0x1d1455aa, 0xdfe7}}},\n\t\t/* 11*16^12*G: */\n\t\t{{{0x27748690, 0x3e981449, 0x0630b01c, 0x15e41376, 0x133d007d, 0x114ac7b7, 0x11ccc94b, 0x32e19f4a, 0x2355}},\n\t\t {{0x0c89582b, 0x1f11d4c5, 0x11c93914, 0x0a1a1633, 0x2a7c5858, 0x2e17b056, 0x1e1f8f55, 0x3c62969c, 0x21c2}}},\n\t\t/* 13*16^12*G: */\n\t\t{{{0x0ade7f16, 0x36ba8858, 0x0be028c6, 0x272eba4f, 0x275d24ae, 0x164aadb0, 0x1a56c013, 0x2096e6cf, 0x0b66}},\n\t\t {{0x08c56217, 0x251109a1, 0x3e7cd2bd, 0x090f037c, 0x17a97fb7, 0x29daea2d, 0x09b3fef3, 0x282e0638, 0xa1fb}}},\n\t\t/* 15*16^12*G: */\n\t\t{{{0x19060d5b, 0x241ac08a, 0x03a3a7c2, 0x1184ec47, 0x3951cb90, 0x026cbf67, 0x1022cb61, 0x010f3c2f, 0xf602}},\n\t\t {{0x1af88f13, 0x1bdbd42c, 0x3dd1a3f7, 0x2a95b4ad, 0x0f7bea37, 0x2a3d92b1, 0x0cf19881, 0x2dc1b07c, 0xf036}}}\n\t},\n\t{\n\t\t/*  1*16^13*G: */\n\t\t{{{0x3ad86047, 0x3fe567d0, 0x29b8bcae, 0x2d4e810e, 0x0a906779, 0x3329dd93, 0x183a7719, 0x3342f4d6, 0x8e7b}},\n\t\t {{0x0460372a, 0x284011fa, 0x3fd68b3e, 0x3a238b91, 0x29514579, 0x0c410832, 0x1a4b3940, 0x1dc2ca8f, 0x10b7}}},\n\t\t/*  3*16^13*G: */\n\t\t{{{0x041ead4b, 0x3fa21e68, 0x11b03c1f, 0x1d7b7eda, 0x3e76be3a, 0x11cd3beb, 0x3337ec71, 0x03032323, 0xbfc9}},\n\t\t {{0x06fedaed, 0x114b1bc2, 0x2e0ae3e7, 0x11a3bfcc, 0x042d36fb, 0x29c63754, 0x0ded24db, 0x206c7827, 0x7a94}}},\n\t\t/*  5*16^13*G: */\n\t\t{{{0x35bb3b3e, 0x1b9ef41d, 0x39f73cb2, 0x1d4d85fb, 0x2d3f5b50, 0x1664fa30, 0x3aaa4dca, 0x3c472f8f, 0x732d}},\n\t\t {{0x17366693, 0x315df87b, 0x0c58436c, 0x276b5b59, 0x253916e6, 0x38956100, 0x39977cb7, 0x240fb7a3, 0x7f41}}},\n\t\t/*  7*16^13*G: */\n\t\t{{{0x088dc3b9, 0x17d6cf06, 0x1774c99c, 0x299a493a, 0x17ef6019, 0x2a210332, 0x147b428d, 0x252e580e, 0x4ce0}},\n\t\t {{0x25c0de52, 0x3053dedb, 0x1ea06502, 0x0816c832, 0x36aca216, 0x2d360329, 0x29b3ed57, 0x03eeafc6, 0x0539}}},\n\t\t/*  9*16^13*G: */\n\t\t{{{0x0aaafe5a, 0x30dd782c, 0x109aedd4, 0x151c2ce9, 0x023fd0e2, 0x229aa56c, 0x267de96d, 0x23addbf1, 0x9a96}},\n\t\t {{0x0ed975c0, 0x39aff509, 0x1e70cc0c, 0x2d620299, 0x061d0ee7, 0x319b40f6, 0x3ba2954f, 0x3ec1e9b4, 0xabf6}}},\n\t\t/* 11*16^13*G: */\n\t\t{{{0x334c6397, 0x1d472fe7, 0x074cd093, 0x374f6d40, 0x36b22107, 0x2bbe0094, 0x161954f0, 0x3efb405c, 0xd3c6}},\n\t\t {{0x28cb3f9c, 0x07f23415, 0x05e0e00b, 0x031dc224, 0x2ab6468a, 0x20e5364b, 0x22af1945, 0x34b15797, 0x4a0d}}},\n\t\t/* 13*16^13*G: */\n\t\t{{{0x0ac3137e, 0x26e0964c, 0x1af64461, 0x2496d8a9, 0x2b3953fe, 0x3c1a9daa, 0x243b8e02, 0x38e604a4, 0x4cbd}},\n\t\t {{0x2ec02fe6, 0x0023c573, 0x08ead60c, 0x24e9eb96, 0x14c370d1, 0x24a84d2e, 0x36159500, 0x151823c4, 0x6ce5}}},\n\t\t/* 15*16^13*G: */\n\t\t{{{0x20fbf84b, 0x1e88c1b3, 0x03f0b8a4, 0x3123f2ef, 0x14cebb03, 0x3671cc30, 0x16247b8b, 0x0ccf20ac, 0x4b9d}},\n\t\t {{0x236c3c48, 0x0e7b92d2, 0x2f5b5e62, 0x19b550f8, 0x39b7eb67, 0x04f66099, 0x0c152553, 0x31fef893, 0xfd7f}}}\n\t},\n\t{\n\t\t/*  1*16^14*G: */\n\t\t{{{0x19c43862, 0x2a107856, 0x397e6690, 0x29fd3c60, 0x381bde71, 0x02061a26, 0x1ff21e6d, 0x3b4d3073, 0x385e}},\n\t\t {{0x142e5453, 0x01163f95, 0x086dc8cc, 0x0c13bb08, 0x2bf4576b, 0x077867a7, 0x223f5670, 0x3af0fa3a, 0x283b}}},\n\t\t/*  3*16^14*G: */\n\t\t{{{0x36e2d9b3, 0x12f4c1aa, 0x338d6351, 0x36e4a0c6, 0x0f845641, 0x0ba984e7, 0x305e75e1, 0x053ce5f1, 0x19a3}},\n\t\t {{0x0baaaf33, 0x154bb897, 0x004be56d, 0x00874749, 0x3528b3a5, 0x2597e21f, 0x328dd234, 0x363d76b1, 0x6cac}}},\n\t\t/*  5*16^14*G: */\n\t\t{{{0x12f00480, 0x36161fac, 0x100dcee7, 0x0d620128, 0x36721920, 0x32618d93, 0x0daa355d, 0x3b52e56a, 0x5840}},\n\t\t {{0x3e22cf9e, 0x164b578a, 0x2ae38721, 0x1d489514, 0x1dd8daba, 0x1a37aa85, 0x3f141079, 0x369ac882, 0x670c}}},\n\t\t/*  7*16^14*G: */\n\t\t{{{0x23f54c42, 0x12137ba0, 0x29a3dc8e, 0x37068f09, 0x0e532545, 0x16307d3b, 0x118fb1dc, 0x00694d1a, 0x9f57}},\n\t\t {{0x2feb6a21, 0x18387124, 0x219e5278, 0x3b9e12ac, 0x29bfdd89, 0x256dad5c, 0x19e57bfb, 0x23ee2007, 0xce7b}}},\n\t\t/*  9*16^14*G: */\n\t\t{{{0x1522461a, 0x3a504cca, 0x3c718327, 0x2cc28996, 0x3ef9a0bc, 0x2e1c0419, 0x28cfc01b, 0x045a48d6, 0x27f6}},\n\t\t {{0x07301a2d, 0x2a932be7, 0x28639446, 0x2606c836, 0x028ee8e4, 0x2315849d, 0x26ad2ea4, 0x3c6a6402, 0xe512}}},\n\t\t/* 11*16^14*G: */\n\t\t{{{0x114f36b9, 0x338b26cb, 0x3b9f390c, 0x2632aed8, 0x34a98125, 0x2fcbd0d7, 0x2f941261, 0x1e615b3b, 0x6407}},\n\t\t {{0x24b4b50a, 0x252c7ba7, 0x19ceeb28, 0x36821c12, 0x1a7b6c8c, 0x035d7f61, 0x16efaef9, 0x24a3d139, 0xda61}}},\n\t\t/* 13*16^14*G: */\n\t\t{{{0x14d6b76f, 0x3bd8f7e6, 0x0c815dbc, 0x396a7eed, 0x1dfeae7f, 0x3dc22f02, 0x1669f452, 0x1438c721, 0xa237}},\n\t\t {{0x0dcca8da, 0x0764b332, 0x1b848d14, 0x1c1f047f, 0x011113e7, 0x0be8f935, 0x3de6dac3, 0x26c529b9, 0xf733}}},\n\t\t/* 15*16^14*G: */\n\t\t{{{0x3ceee475, 0x0bba7193, 0x0ed782b1, 0x1ab20a10, 0x0aff41ab, 0x0f0087cf, 0x2378d5ed, 0x2b01e8fc, 0xbbf1}},\n\t\t {{0x07fe5067, 0x1188a802, 0x38b41d68, 0x3ae76250, 0x315fe324, 0x20f320da, 0x060e6108, 0x2e37bab5, 0xb4bf}}}\n\t},\n\t{\n\t\t/*  1*16^15*G: */\n\t\t{{{0x03fac3a7, 0x181bb61b, 0x147fbc9c, 0x377e1296, 0x3dfa180f, 0x31ce9104, 0x0f191637, 0x366e00fb, 0x06f9}},\n\t\t {{0x3a842160, 0x21a24180, 0x0281002d, 0x29374bd7, 0x05c4d47e, 0x238a8c39, 0x059ba69b, 0x31a3980c, 0x7c80}}},\n\t\t/*  3*16^15*G: */\n\t\t{{{0x121ce204, 0x13b5d7a3, 0x26763d52, 0x29c96390, 0x26f72fb2, 0x1d361672, 0x3c64fb83, 0x107458ac, 0x43ca}},\n\t\t {{0x134a8f6b, 0x1494113a, 0x2a4a468e, 0x2db1eccf, 0x1ba31f9a, 0x143e4863, 0x023fa1c6, 0x16a0b8dc, 0xdcea}}},\n\t\t/*  5*16^15*G: */\n\t\t{{{0x2be6efda, 0x13f3a4b3, 0x07280596, 0x0b53fcfe, 0x1a506d92, 0x1bdc8de1, 0x12bf5b66, 0x01bbc8a2, 0x9c3e}},\n\t\t {{0x27aefc7d, 0x3c503cca, 0x336fdf7d, 0x0ef21a1e, 0x226fd5d4, 0x02cb5133, 0x2923d8af, 0x027979d8, 0xa7b7}}},\n\t\t/*  7*16^15*G: */\n\t\t{{{0x06c88be2, 0x2449ead7, 0x06ee5e27, 0x0b1e0834, 0x30775bea, 0x1c9d6760, 0x20f033bb, 0x22a8c4f8, 0x5d6f}},\n\t\t {{0x0d7ad75d, 0x24b954fc, 0x2bf92c28, 0x2adbe3a9, 0x08bc20ed, 0x2abcceac, 0x2d4e8c71, 0x2c636355, 0xadc4}}},\n\t\t/*  9*16^15*G: */\n\t\t{{{0x12d1b844, 0x0a24d46e, 0x173e484f, 0x2700e0b0, 0x388bc5c6, 0x2c570f04, 0x20d5fc86, 0x0d70c129, 0xf57d}},\n\t\t {{0x21266837, 0x192eaef5, 0x0915c6a4, 0x01a5c80c, 0x24634c70, 0x134fd6a7, 0x2f4d9790, 0x0f67aa63, 0x707f}}},\n\t\t/* 11*16^15*G: */\n\t\t{{{0x3cc7cb09, 0x0d3401fc, 0x1d1b4352, 0x31fada28, 0x1871463b, 0x1b87fb8f, 0x194a5f59, 0x181e8e99, 0x13e7}},\n\t\t {{0x08079160, 0x2f9d6a28, 0x2b576411, 0x3ab8aed9, 0x34299d65, 0x17f7616c, 0x3b8b1e32, 0x32237a3e, 0x284d}}},\n\t\t/* 13*16^15*G: */\n\t\t{{{0x18cdee05, 0x01833849, 0x32ec3b90, 0x1d87ec85, 0x06901da8, 0x00942c6c, 0x182e6240, 0x28c895a0, 0x29be}},\n\t\t {{0x262651c8, 0x39280d66, 0x0c698e39, 0x3f0c6db2, 0x305ec7f9, 0x026cfee1, 0x29a0ea90, 0x36689a43, 0x7c40}}},\n\t\t/* 15*16^15*G: */\n\t\t{{{0x12f18ada, 0x06db1d58, 0x3dbdbcc1, 0x182f64ee, 0x3d4a59d4, 0x0dbebfcc, 0x288e7d9c, 0x1e1b48e0, 0xf521}},\n\t\t {{0x23953516, 0x375a2bf4, 0x05bf0981, 0x17bd28db, 0x11d1d6aa, 0x09840af3, 0x0db57ecc, 0x1befd80e, 0xe068}}}\n\t},\n\t{\n\t\t/*  1*16^16*G: */\n\t\t{{{0x02d0e6bd, 0x0edf839d, 0x30f5e531, 0x1d3458f6, 0x0d6ecbf7, 0x0851f041, 0x04e2582a, 0x3500490f, 0x3322}},\n\t\t {{0x2c28b2a0, 0x13ce8ba5, 0x2873af62, 0x017d8fa8, 0x1af9b728, 0x0066f137, 0x24ef5bfb, 0x01e5fa59, 0x56e7}}},\n\t\t/*  3*16^16*G: */\n\t\t{{{0x059ab499, 0x2f674fc8, 0x273c330a, 0x04ca671b, 0x3f01bc0b, 0x065acf19, 0x005ba5d2, 0x2bfcc057, 0x78ba}},\n\t\t {{0x3ee097fd, 0x20748c63, 0x11251996, 0x18cbbba3, 0x02082e91, 0x2a1383b6, 0x2c0afafc, 0x3736f6c1, 0xad4b}}},\n\t\t/*  5*16^16*G: */\n\t\t{{{0x3d06ace6, 0x124f85b3, 0x03a20ca4, 0x1c26cdbe, 0x29ab1a23, 0x2e126124, 0x2e3d4c20, 0x3c846852, 0x6f70}},\n\t\t {{0x3602d5de, 0x122fb4d2, 0x25ac5ee0, 0x0ca559af, 0x399f5075, 0x1763cd1e, 0x27b736f9, 0x228c2500, 0x791e}}},\n\t\t/*  7*16^16*G: */\n\t\t{{{0x20ee1b40, 0x323b8fb9, 0x1e96247d, 0x3b5216dc, 0x03ccd48c, 0x2527c644, 0x2a415f80, 0x276ca75a, 0xe159}},\n\t\t {{0x178f93a6, 0x0758997b, 0x032999de, 0x0d8e9d2f, 0x2fc7cfa6, 0x3e252aa8, 0x1d4a0efa, 0x1888caa0, 0x7933}}},\n\t\t/*  9*16^16*G: */\n\t\t{{{0x09c00c3e, 0x2077e8a1, 0x11208e2f, 0x03a3c0f2, 0x051859f0, 0x158b4cf5, 0x06956436, 0x0125c110, 0xbb0b}},\n\t\t {{0x11955a35, 0x266a60b4, 0x05dc90a7, 0x19c113a4, 0x31b052fe, 0x34be85ea, 0x39f63655, 0x391614eb, 0x4067}}},\n\t\t/* 11*16^16*G: */\n\t\t{{{0x05dd32e6, 0x039d6e70, 0x13e5ee7e, 0x18ed546d, 0x1a5fbfc6, 0x1276f81d, 0x1789e9b6, 0x10555065, 0xdc5a}},\n\t\t {{0x354a99b9, 0x039f6de9, 0x2e49bcf8, 0x3cbba41d, 0x3f59442f, 0x3a978806, 0x367a76dc, 0x2a298fe7, 0x4af3}}},\n\t\t/* 13*16^16*G: */\n\t\t{{{0x0544e7cb, 0x3b516eb1, 0x12960359, 0x0190896d, 0x014e99a1, 0x0d5295c4, 0x33b9dbe3, 0x065c0e61, 0x156e}},\n\t\t {{0x2d250a37, 0x354e4b02, 0x2b439cd6, 0x25b56357, 0x034be894, 0x255ca98e, 0x1907da93, 0x2367e3cc, 0x6bc0}}},\n\t\t/* 15*16^16*G: */\n\t\t{{{0x059853ca, 0x2fef0a73, 0x319bf54d, 0x3a589ae7, 0x27161348, 0x29da88a3, 0x043826bc, 0x2f33b2da, 0x4269}},\n\t\t {{0x35b8d367, 0x2a563bd4, 0x1e5a8a3d, 0x0e50297e, 0x31a409fd, 0x2132a710, 0x016b723c, 0x0706a0b0, 0xed2b}}}\n\t},\n\t{\n\t\t/*  1*16^17*G: */\n\t\t{{{0x0134ab83, 0x0875d34a, 0x36433977, 0x06cfe6bd, 0x26586874, 0x05dc3625, 0x0b7da2bd, 0x0b1f4b78, 0x8567}},\n\t\t {{0x390313a6, 0x238c253d, 0x1298f44c, 0x1fc5ff31, 0x22c2e5e7, 0x10126fe9, 0x3b2eb637, 0x06e6d6d0, 0x7c48}}},\n\t\t/*  3*16^17*G: */\n\t\t{{{0x03ba9000, 0x37c1c8ea, 0x025e8b6f, 0x21cbe71a, 0x00143dc4, 0x21d81d61, 0x1d8c1684, 0x1d3e7ffc, 0xac38}},\n\t\t {{0x2f10cf0a, 0x368f1f65, 0x366e9fa4, 0x178d435f, 0x117f9308, 0x0b77a250, 0x1c069b86, 0x3a48c228, 0xaa65}}},\n\t\t/*  5*16^17*G: */\n\t\t{{{0x2d06dbd4, 0x2981bd9b, 0x0a20d081, 0x038fe15e, 0x23e729ec, 0x0501d7a6, 0x070139ad, 0x1739ea9a, 0x570d}},\n\t\t {{0x3d1ed495, 0x2996fb3a, 0x2460bed5, 0x20e8db71, 0x101bbbb6, 0x19b99c47, 0x202f605b, 0x14d25083, 0xa6ae}}},\n\t\t/*  7*16^17*G: */\n\t\t{{{0x092d230e, 0x0d307e48, 0x29339284, 0x3b8ca834, 0x366ef5da, 0x308a7b80, 0x28bb6f87, 0x3e1c0a09, 0x75b5}},\n\t\t {{0x151570b8, 0x0df2f7ef, 0x111f8fb0, 0x19e92c01, 0x1dfa8e02, 0x1e1d1553, 0x3852363d, 0x338878e9, 0x527c}}},\n\t\t/*  9*16^17*G: */\n\t\t{{{0x034fcc0e, 0x1edafdab, 0x3e3884c4, 0x1fc4290a, 0x1259c892, 0x16e0389f, 0x1dec2b0a, 0x23beb87b, 0x44fc}},\n\t\t {{0x319c420a, 0x33fc0c79, 0x0d0489d9, 0x03a5292f, 0x33d3d772, 0x099f9e20, 0x31367e49, 0x37a52ea6, 0xd2c7}}},\n\t\t/* 11*16^17*G: */\n\t\t{{{0x0bb69991, 0x169207f2, 0x3307175d, 0x3ecfe8b0, 0x02f535ff, 0x28598838, 0x27bc6866, 0x2e91eeb3, 0xdea2}},\n\t\t {{0x316fe2df, 0x019d0aa7, 0x21ed9bc7, 0x27736cd8, 0x37b9e722, 0x32ffb213, 0x028e4ac5, 0x2ff5b643, 0xae28}}},\n\t\t/* 13*16^17*G: */\n\t\t{{{0x114fc9cc, 0x30903409, 0x1a461658, 0x3402af0a, 0x38a83626, 0x073db312, 0x168d6efc, 0x3f2629b8, 0x3968}},\n\t\t {{0x1fad37dd, 0x064e5225, 0x388f3340, 0x05195dbf, 0x2d32c91a, 0x1e60b46a, 0x35928123, 0x2ef436d2, 0x789c}}},\n\t\t/* 15*16^17*G: */\n\t\t{{{0x2e0c85f1, 0x2bb08646, 0x03a3a250, 0x294b94d8, 0x3945d5a6, 0x0977c255, 0x06a2926b, 0x2441a638, 0x6896}},\n\t\t {{0x2dc1de21, 0x31d208cc, 0x0d503922, 0x10306768, 0x05d72d1f, 0x0c170761, 0x0979256f, 0x0fed2ce3, 0xaefd}}}\n\t},\n\t{\n\t\t/*  1*16^18*G: */\n\t\t{{{0x20c82a0a, 0x3f6566bd, 0x3668832f, 0x2489b183, 0x1413b10f, 0x1b27c646, 0x188a46b0, 0x2fe026c6, 0x0948}},\n\t\t {{0x18c8e589, 0x132dfe23, 0x17cd2bed, 0x137fc232, 0x03418c6d, 0x2dd31747, 0x36646dc6, 0x18a15b72, 0x53a5}}},\n\t\t/*  3*16^18*G: */\n\t\t{{{0x38c8ac7f, 0x0a0bf97e, 0x1e2aa527, 0x0490bb99, 0x16f84964, 0x0ce5b481, 0x22bbcb5c, 0x2cbef8e0, 0x9945}},\n\t\t {{0x29aea3b0, 0x1b650e85, 0x2dacdfa9, 0x0bde88fb, 0x28eff528, 0x36d13fec, 0x3282d607, 0x3b6092c3, 0x3eef}}},\n\t\t/*  5*16^18*G: */\n\t\t{{{0x169e353a, 0x3475e78e, 0x2bbe1f6e, 0x28110214, 0x07d5fe10, 0x3e0889c4, 0x070e6235, 0x131ac816, 0x2a31}},\n\t\t {{0x25746067, 0x09649b87, 0x32658bfc, 0x22952ab6, 0x2a1ba013, 0x18f91dae, 0x227ac1a4, 0x2b02fcd6, 0x15a4}}},\n\t\t/*  7*16^18*G: */\n\t\t{{{0x29b84966, 0x278bd27b, 0x17f3ff98, 0x13d041b7, 0x2b6c911b, 0x2dbebce9, 0x3fc2d498, 0x29402dc0, 0x5959}},\n\t\t {{0x07473a6a, 0x02998c86, 0x0fe24264, 0x00373023, 0x082a7091, 0x0c4a0837, 0x0a897f94, 0x399d07d7, 0x0370}}},\n\t\t/*  9*16^18*G: */\n\t\t{{{0x2bc6b173, 0x2c326e48, 0x2ed3feb3, 0x36188f1f, 0x1b5f9d7d, 0x183118c1, 0x22fe8e11, 0x0c4e4dc8, 0x9eeb}},\n\t\t {{0x1723a71d, 0x14e58836, 0x0e70c4b9, 0x29c6afb4, 0x3a1ae30e, 0x2aaff6ee, 0x2d58d952, 0x3c780443, 0xe121}}},\n\t\t/* 11*16^18*G: */\n\t\t{{{0x3ec805f3, 0x1dc910fd, 0x1d995915, 0x3903dd42, 0x2e97887d, 0x2ec8e201, 0x318f516e, 0x13f931fd, 0x39cc}},\n\t\t {{0x3a3c48d3, 0x06468304, 0x3c912e4d, 0x2e55cdcf, 0x02de7dbb, 0x399a4f3d, 0x2f8f3151, 0x11cb1691, 0xecb1}}},\n\t\t/* 13*16^18*G: */\n\t\t{{{0x0e22580e, 0x0f58bed7, 0x2d6f8879, 0x04ca25b4, 0x1bd4d2c7, 0x0bff7993, 0x0dc69689, 0x201d19bb, 0xf94c}},\n\t\t {{0x3127db82, 0x07948fd9, 0x2371d4e8, 0x21fb114c, 0x1a81f698, 0x12ffdaad, 0x1225a919, 0x1ff719e1, 0x5e9c}}},\n\t\t/* 15*16^18*G: */\n\t\t{{{0x10c4f21f, 0x2f902eb4, 0x103da7a6, 0x092a5653, 0x1999d250, 0x0081a36c, 0x1d162fcc, 0x2e1b1ab5, 0x8ccc}},\n\t\t {{0x329dfea0, 0x1fc49ba9, 0x264be28f, 0x24b72b20, 0x0758a54b, 0x2fbd5272, 0x11c43699, 0x2596189d, 0x57f8}}}\n\t},\n\t{\n\t\t/*  1*16^19*G: */\n\t\t{{{0x338fd8e8, 0x33b36067, 0x069752ac, 0x2c39137f, 0x2873a8f1, 0x19f383c0, 0x001c34f0, 0x339fd186, 0x6260}},\n\t\t {{0x32b4ae17, 0x06a13a56, 0x051c198c, 0x34a488e0, 0x2a1ef7ec, 0x024125dd, 0x1b571a7f, 0x2a0adbe9, 0xbc2d}}},\n\t\t/*  3*16^19*G: */\n\t\t{{{0x01136602, 0x2c2e9195, 0x19e3a5bb, 0x311bd203, 0x333b3d38, 0x1624dfc8, 0x2dfc33d0, 0x09ca0120, 0x87d1}},\n\t\t {{0x18af6aac, 0x3da0f107, 0x3d3bf7c4, 0x2a211d1b, 0x27745387, 0x289db3fd, 0x203de926, 0x0921c296, 0x71ce}}},\n\t\t/*  5*16^19*G: */\n\t\t{{{0x08c5a916, 0x2c8175cd, 0x35610f25, 0x17110354, 0x354aa13f, 0x2b318f6a, 0x1e9746b0, 0x1f4ff898, 0xfd5d}},\n\t\t {{0x3adb8bda, 0x052cdec1, 0x1cf6faab, 0x35ce052f, 0x07b52fe5, 0x10f299e7, 0x15b07d2b, 0x0fb43bad, 0x0dd8}}},\n\t\t/*  7*16^19*G: */\n\t\t{{{0x35f7529c, 0x17664258, 0x1bd51dd4, 0x1d96e62d, 0x34438138, 0x114f0cb4, 0x026122ba, 0x35042607, 0xde0d}},\n\t\t {{0x24cd88fe, 0x0f08300b, 0x09b77406, 0x224931a2, 0x3a357017, 0x042608b5, 0x2145f9b2, 0x1ba74428, 0xd70a}}},\n\t\t/*  9*16^19*G: */\n\t\t{{{0x38f76d11, 0x320bd234, 0x38515573, 0x044003ef, 0x0292a215, 0x16fbf0e7, 0x0f44e69c, 0x0822b693, 0xb26c}},\n\t\t {{0x23b7356b, 0x307002c7, 0x182624bd, 0x000c1967, 0x0d643305, 0x13a1f643, 0x1d33cf0c, 0x3e208252, 0x1f1c}}},\n\t\t/* 11*16^19*G: */\n\t\t{{{0x269e22db, 0x2538ec19, 0x39c8933f, 0x264ffd67, 0x0c294eac, 0x0ef4a406, 0x3f523a7e, 0x052e3f1f, 0xfceb}},\n\t\t {{0x1c2260a1, 0x3d5cb6c9, 0x24ebe4cb, 0x15439e4e, 0x1f0924ad, 0x22969d49, 0x2b8d1fcd, 0x1ace9035, 0x64aa}}},\n\t\t/* 13*16^19*G: */\n\t\t{{{0x238a2755, 0x3c2105e6, 0x149c5506, 0x1c869c59, 0x107faa53, 0x05d5dd2d, 0x15cac55c, 0x26988f33, 0x4e90}},\n\t\t {{0x23cca3de, 0x3de927d8, 0x229800ca, 0x3354e534, 0x3559dbb6, 0x091b7541, 0x235aecef, 0x36a1e333, 0xae56}}},\n\t\t/* 15*16^19*G: */\n\t\t{{{0x183ba64d, 0x20962566, 0x0c595a3a, 0x3983dde2, 0x0e40e2bd, 0x028517ae, 0x04c03bfb, 0x115708b8, 0xc367}},\n\t\t {{0x2a2181fd, 0x053323e5, 0x1778f146, 0x189aab28, 0x1964c742, 0x3839ba13, 0x36033080, 0x02b41a72, 0x3a52}}}\n\t},\n\t{\n\t\t/*  1*16^20*G: */\n\t\t{{{0x2037fa2d, 0x254f3234, 0x1bfdc432, 0x0fb23d5d, 0x3f410304, 0x0d21052e, 0x1d8d43d8, 0x1f782bf0, 0xe503}},\n\t\t {{0x1d755bda, 0x03977210, 0x0481f10e, 0x17d6c0fb, 0x190bddbd, 0x263427ee, 0x0d3b5f9f, 0x14d2eaa5, 0x4571}}},\n\t\t/*  3*16^20*G: */\n\t\t{{{0x177e7775, 0x222a29b8, 0x0ed95f63, 0x385564e2, 0x1291aeb5, 0x150eeb3d, 0x233cee58, 0x1a8ebfe5, 0x9d89}},\n\t\t {{0x3a056691, 0x3f3db4ea, 0x299253be, 0x26735fb8, 0x10927de8, 0x2593b5c9, 0x1bf0b94e, 0x2a790fd2, 0xdd91}}},\n\t\t/*  5*16^20*G: */\n\t\t{{{0x3c2a3293, 0x3f781378, 0x103476c5, 0x222e1bba, 0x02f4cd56, 0x2c295cca, 0x23792d0e, 0x2e3b9c45, 0x8327}},\n\t\t {{0x0e0df9bd, 0x2f215386, 0x2326a416, 0x2bf6ad3b, 0x39708496, 0x2cfa9989, 0x0a98e18b, 0x1f899bb8, 0x0499}}},\n\t\t/*  7*16^20*G: */\n\t\t{{{0x0562c042, 0x1086c9b1, 0x38dfb1a2, 0x0b48c8d2, 0x1a8ed609, 0x1998763e, 0x1b16897d, 0x0aaa8a9b, 0x5ae4}},\n\t\t {{0x0f79269c, 0x2417337e, 0x07cd8dbf, 0x3836e544, 0x389d4a94, 0x30777180, 0x3051eab5, 0x0e9f017f, 0x99d9}}},\n\t\t/*  9*16^20*G: */\n\t\t{{{0x1e85af61, 0x0d2204a1, 0x14ae766b, 0x23b5c8b7, 0x021b0f4e, 0x3ada3fdb, 0x1c8eb59a, 0x0eb909a8, 0x92c2}},\n\t\t {{0x036a2b09, 0x39c8d9a7, 0x2286fed4, 0x08eb60ad, 0x38d5792d, 0x085f571c, 0x11bb409f, 0x3e23c055, 0x414c}}},\n\t\t/* 11*16^20*G: */\n\t\t{{{0x07b5eba8, 0x38abc6cb, 0x118ea36c, 0x2afb71fe, 0x38df422d, 0x03d05dab, 0x3df1088d, 0x18231dab, 0xfee5}},\n\t\t {{0x0d0b9b5c, 0x3d4574da, 0x39054793, 0x203fd0af, 0x07c14ee3, 0x100be64a, 0x258afb11, 0x16644d3f, 0x3807}}},\n\t\t/* 13*16^20*G: */\n\t\t{{{0x3c63caf4, 0x078ee92c, 0x0f53d528, 0x23fceaca, 0x2a6afca2, 0x044ed318, 0x267e620a, 0x113ae4b9, 0x42e5}},\n\t\t {{0x169c29c8, 0x21ebb026, 0x3efc5f11, 0x29439eda, 0x015e7873, 0x3c88305d, 0x0c671f71, 0x15383e47, 0x9ff8}}},\n\t\t/* 15*16^20*G: */\n\t\t{{{0x1e0f09a1, 0x028af661, 0x14032838, 0x28427c6e, 0x300efef0, 0x25bb4a91, 0x32ce3839, 0x20ed9954, 0x7aed}},\n\t\t {{0x05857d73, 0x1176337a, 0x33f4a540, 0x22cbcc03, 0x032d8ed8, 0x2bf42ac4, 0x1ef7c7dd, 0x1517e68c, 0xf5b8}}}\n\t},\n\t{\n\t\t/*  1*16^21*G: */\n\t\t{{{0x24fce725, 0x1619a82b, 0x2a6c5b72, 0x3a36f471, 0x1771b4e7, 0x2a417a3c, 0x207adf5e, 0x1cac3d28, 0xe063}},\n\t\t {{0x0eee31dd, 0x09c0d3e5, 0x3104870b, 0x12129de1, 0x1a488cd7, 0x09eecab5, 0x18cfe12a, 0x225d2f38, 0x7a90}}},\n\t\t/*  3*16^21*G: */\n\t\t{{{0x1a328d6a, 0x2eaa0623, 0x1adc18bd, 0x135dcea5, 0x308fa7b2, 0x1a264616, 0x34e00a34, 0x3016e988, 0xc663}},\n\t\t {{0x3ec9b8c0, 0x0ec2edaa, 0x12bf9cc2, 0x21547a94, 0x171317dd, 0x2bf73c9d, 0x21c38d39, 0x3a6357dc, 0x3331}}},\n\t\t/*  5*16^21*G: */\n\t\t{{{0x3996de2f, 0x32472120, 0x0b25114b, 0x33b7cbb8, 0x0fe4e977, 0x2cc37ba8, 0x06a459ce, 0x09a0b7ee, 0xd3fc}},\n\t\t {{0x14526f8c, 0x31248907, 0x37abf168, 0x166d2637, 0x3781da4e, 0x2d1d5353, 0x30a18f68, 0x37e66917, 0xc4f0}}},\n\t\t/*  7*16^21*G: */\n\t\t{{{0x03e697ea, 0x31b12344, 0x05f83e85, 0x399e3ee6, 0x3fabd19c, 0x287fb268, 0x2c0237dc, 0x12d0ffac, 0xc17a}},\n\t\t {{0x1edc6c87, 0x3b8ee1f7, 0x39f02ab0, 0x38686d5f, 0x201fae96, 0x05e3dc65, 0x35954cae, 0x170b556a, 0x3935}}},\n\t\t/*  9*16^21*G: */\n\t\t{{{0x3163da1b, 0x0b4b0c08, 0x393a3118, 0x03b7b983, 0x011fde9a, 0x24d275ff, 0x390b468c, 0x22df2899, 0x8f61}},\n\t\t {{0x03bdd76e, 0x1fcc4844, 0x249b6e7c, 0x14319a8c, 0x2c5a4264, 0x2f69d35e, 0x3eb6eb5f, 0x0fc97c22, 0x7823}}},\n\t\t/* 11*16^21*G: */\n\t\t{{{0x0ec8ae90, 0x3a1643f8, 0x0bbc5dee, 0x2c9ae4ba, 0x03f1b8cf, 0x356e36b2, 0x21e6eb86, 0x303c56de, 0x9798}},\n\t\t {{0x252844d3, 0x2a6b0bab, 0x03188e27, 0x392596f4, 0x1c73bee2, 0x3b25253e, 0x02ed3dd2, 0x38aa9d69, 0xba40}}},\n\t\t/* 13*16^21*G: */\n\t\t{{{0x11d66b7f, 0x16865e3c, 0x187dc810, 0x29a49414, 0x1284757a, 0x3c6e42e2, 0x22d6747c, 0x1bb8fed6, 0xfdfa}},\n\t\t {{0x38e5178b, 0x2aa3e019, 0x3d78de9d, 0x11be7744, 0x1a18c4d8, 0x0307268f, 0x198db93c, 0x3cc78892, 0x4d9c}}},\n\t\t/* 15*16^21*G: */\n\t\t{{{0x1265bcf0, 0x201d5e12, 0x11c7d30b, 0x338ade10, 0x0f220e69, 0x3aa69187, 0x29e43add, 0x338e3788, 0xfd58}},\n\t\t {{0x2b996292, 0x0cf9ea73, 0x0f1cd1df, 0x0986ff8a, 0x05e4fb87, 0x20aae692, 0x3215bd53, 0x29794dd8, 0xffe0}}}\n\t},\n\t{\n\t\t/*  1*16^22*G: */\n\t\t{{{0x10559754, 0x02b5a423, 0x2a3f5854, 0x2c42f778, 0x0ce02204, 0x02efe770, 0x1d45358d, 0x1e9c5735, 0x213c}},\n\t\t {{0x34b458f2, 0x3fcb09d4, 0x36a7eedd, 0x12143d7c, 0x1ba190bb, 0x0eb41891, 0x06250701, 0x2b42d6b9, 0x4b6d}}},\n\t\t/*  3*16^22*G: */\n\t\t{{{0x1e05dccc, 0x0cb60046, 0x019a93e5, 0x0fe8fb53, 0x13d172ae, 0x1b825ae5, 0x1a030954, 0x3db85d4f, 0xb8ce}},\n\t\t {{0x0c6d5750, 0x0052833f, 0x26b68133, 0x1d5ff0da, 0x12bd99df, 0x3529d393, 0x09bbf6a4, 0x229829b3, 0x302b}}},\n\t\t/*  5*16^22*G: */\n\t\t{{{0x373bb31a, 0x16f7fb84, 0x3db97b48, 0x07dedad7, 0x3b5f4970, 0x282f78ba, 0x07385e02, 0x0cf9de6d, 0x03fb}},\n\t\t {{0x3d215c9e, 0x0d32f9a5, 0x07640d4e, 0x169f1db1, 0x3b572bc6, 0x30586aae, 0x2fe281e0, 0x36549523, 0xf36a}}},\n\t\t/*  7*16^22*G: */\n\t\t{{{0x1d9a4ab4, 0x16d457af, 0x15bb7c0a, 0x1f0db061, 0x0f7a3671, 0x05bded34, 0x03e1161f, 0x1f34427b, 0x4b17}},\n\t\t {{0x235ab6f7, 0x2ab77f91, 0x1741f558, 0x0df8957c, 0x226b486e, 0x23d9ca4d, 0x2fa65fda, 0x19ba6978, 0x3ec9}}},\n\t\t/*  9*16^22*G: */\n\t\t{{{0x301c23a4, 0x3d1beca6, 0x3a49cf56, 0x0a905611, 0x39cd75c2, 0x00e0a6e6, 0x27a06c2a, 0x00d481a8, 0x5e87}},\n\t\t {{0x10d986f9, 0x085e65ac, 0x24ccfda1, 0x05c761d2, 0x2c6e2da2, 0x1d5746b8, 0x09221e71, 0x1913bee7, 0x5b96}}},\n\t\t/* 11*16^22*G: */\n\t\t{{{0x007b0c66, 0x3cfcd748, 0x16c86fb1, 0x29ffb919, 0x2ceb7434, 0x08913d82, 0x1680a447, 0x30c064c3, 0xe545}},\n\t\t {{0x31f2d470, 0x21fd5f49, 0x35a239dd, 0x3960a386, 0x19bcbf97, 0x31bf68e5, 0x2955e7e5, 0x0d03a318, 0xe06a}}},\n\t\t/* 13*16^22*G: */\n\t\t{{{0x03648bba, 0x2960642e, 0x1c3c7444, 0x283c2c1a, 0x01b39882, 0x0fb8897c, 0x0f580a13, 0x10855e95, 0xb2a4}},\n\t\t {{0x00fb6452, 0x11bead28, 0x09c17bb2, 0x36154547, 0x3d7e31c0, 0x3ef25e3e, 0x366619e9, 0x17f0ada4, 0xfe4f}}},\n\t\t/* 15*16^22*G: */\n\t\t{{{0x2bab27d0, 0x3db748bb, 0x045103fc, 0x02d07e8b, 0x197007f7, 0x25c06463, 0x138651ba, 0x2383cf51, 0x1b90}},\n\t\t {{0x00d3d110, 0x07a19d79, 0x07e51b57, 0x2ef2a4d6, 0x3c4b9ab5, 0x15f24605, 0x26b5e6f3, 0x1897bb11, 0x9b6d}}}\n\t},\n\t{\n\t\t/*  1*16^23*G: */\n\t\t{{{0x08fbd53c, 0x0330e8ec, 0x1c62cddf, 0x20e31c2b, 0x019a87e2, 0x2e4d4a95, 0x0b34e8db, 0x09ca9ebd, 0x4e7c}},\n\t\t {{0x17dcaae6, 0x02ce5060, 0x3f7dd33e, 0x02e5852f, 0x2f681b53, 0x3f427db7, 0x10b18e16, 0x271d9b27, 0x1774}}},\n\t\t/*  3*16^23*G: */\n\t\t{{{0x2521b3ff, 0x38a61193, 0x1aa750ce, 0x0f01c5fa, 0x2e24a523, 0x1134afa6, 0x1455c75e, 0x138c0432, 0x0248}},\n\t\t {{0x0269da7e, 0x306b92e4, 0x23ac8bbc, 0x1c01b7a4, 0x2d0eebad, 0x30acf0ac, 0x3e30d07e, 0x34282a88, 0x9619}}},\n\t\t/*  5*16^23*G: */\n\t\t{{{0x004ba7b9, 0x25ade7ea, 0x0741751f, 0x35a91c0c, 0x2c954e20, 0x26dc359c, 0x2ce57ef7, 0x3149b3ed, 0x16c1}},\n\t\t {{0x1c5bd741, 0x1d6f8e94, 0x1c9a9cc4, 0x1d57006f, 0x0a94deec, 0x189d1672, 0x31439062, 0x1fdf0d00, 0xdb15}}},\n\t\t/*  7*16^23*G: */\n\t\t{{{0x236683fa, 0x20d921ea, 0x0ec0825e, 0x2086d4e0, 0x127b6695, 0x22739dd1, 0x131af87a, 0x0f35d4fe, 0x0397}},\n\t\t {{0x3f4a577f, 0x3d7ecadd, 0x3e981ded, 0x1e213863, 0x35a26cd7, 0x384ad8ca, 0x0a3a3643, 0x168b30c3, 0x38cf}}},\n\t\t/*  9*16^23*G: */\n\t\t{{{0x00bf6f06, 0x202ce667, 0x1043b571, 0x0f04cc89, 0x20576571, 0x3013d2c0, 0x0f1511c2, 0x26ee9cbb, 0xba6a}},\n\t\t {{0x381db551, 0x0cafbdc1, 0x0697aafe, 0x17453deb, 0x18bd8e9e, 0x082fcb95, 0x211b0320, 0x078e2cd2, 0x1377}}},\n\t\t/* 11*16^23*G: */\n\t\t{{{0x31231a43, 0x347be7c1, 0x1ad43b9f, 0x35453599, 0x1e442f44, 0x3b654193, 0x04dd2d8a, 0x2f3309f3, 0x35c5}},\n\t\t {{0x1620c8f6, 0x36dcb914, 0x23cf0ae7, 0x3de93301, 0x3a589d4c, 0x396082db, 0x346ce734, 0x1d5c8ee5, 0x0e36}}},\n\t\t/* 13*16^23*G: */\n\t\t{{{0x3dd40609, 0x3d02f15b, 0x181cd76b, 0x10642603, 0x08356ac7, 0x0bc4bf16, 0x186bca12, 0x27091715, 0xfd47}},\n\t\t {{0x2a64ca53, 0x378bc4d9, 0x21ca4739, 0x04ebb5c9, 0x1841fd91, 0x2b5e90f2, 0x0afeff2c, 0x33ed49a5, 0x3069}}},\n\t\t/* 15*16^23*G: */\n\t\t{{{0x2b799a7f, 0x36dc0bd4, 0x3b8e8424, 0x062db354, 0x2c7d544f, 0x363ae6bc, 0x0d864bde, 0x000a8eb3, 0x6c40}},\n\t\t {{0x13c81e32, 0x2d7320b3, 0x20483f68, 0x1eaf5320, 0x1ddcbdc0, 0x2e0da838, 0x235be690, 0x37054c2d, 0x95c2}}}\n\t},\n\t{\n\t\t/*  1*16^24*G: */\n\t\t{{{0x00fb27b6, 0x0909f8a1, 0x24305763, 0x1b8f6caf, 0x286aa5c7, 0x08e2b585, 0x38b1b10f, 0x138f6f9d, 0xfea7}},\n\t\t {{0x323cb96f, 0x0074f6df, 0x33f7b777, 0x1ad65ae5, 0x36af9312, 0x19d37b32, 0x313297cf, 0x1a36e6c2, 0x6e05}}},\n\t\t/*  3*16^24*G: */\n\t\t{{{0x3e889756, 0x37606ba6, 0x3004bb25, 0x1ed9265e, 0x1899f3f2, 0x3365ec9c, 0x1fea8226, 0x22f0cc84, 0x762e}},\n\t\t {{0x3ca6b774, 0x17896781, 0x084fa5e2, 0x1cb6cc52, 0x02e34719, 0x3313c526, 0x3e97c3c7, 0x250982bc, 0xc028}}},\n\t\t/*  5*16^24*G: */\n\t\t{{{0x0975d2ea, 0x1bdd7a5c, 0x014e8ea2, 0x14ab3e84, 0x08f4a91e, 0x26f6ec8c, 0x095348e1, 0x1f51f7d8, 0xdf07}},\n\t\t {{0x31936f95, 0x28f0b678, 0x3bdd277a, 0x07b16e13, 0x22527c8a, 0x21097262, 0x37f4424c, 0x1ea2003b, 0xf861}}},\n\t\t/*  7*16^24*G: */\n\t\t{{{0x3c4c92d7, 0x2e1247ee, 0x14391b45, 0x36d35bb9, 0x0b142935, 0x1f7aa0cd, 0x3da032e1, 0x1f5d62f4, 0x9f3e}},\n\t\t {{0x314906dd, 0x32eeff3e, 0x294e1186, 0x0a88c0f5, 0x2b150245, 0x18ac872e, 0x1466b588, 0x2107a9df, 0xecd2}}},\n\t\t/*  9*16^24*G: */\n\t\t{{{0x32a8c483, 0x2b835cca, 0x1040ac35, 0x12c32231, 0x39528117, 0x230f48bb, 0x0cf9edc3, 0x1e575ed7, 0xa0cc}},\n\t\t {{0x12cc6ba9, 0x0259d156, 0x36936055, 0x0d23c6f7, 0x31df786b, 0x1d3f25c8, 0x3873ee23, 0x0048be2c, 0xabc3}}},\n\t\t/* 11*16^24*G: */\n\t\t{{{0x05dd3aee, 0x1c3c6daf, 0x396d2f21, 0x054ea2a3, 0x2976ca13, 0x08aa6b1a, 0x3c7cce0e, 0x14294554, 0x6d1c}},\n\t\t {{0x3df597f7, 0x3b8d5393, 0x0ed53adf, 0x078c42aa, 0x07d47485, 0x09c8008a, 0x3dfdc977, 0x052381aa, 0xafff}}},\n\t\t/* 13*16^24*G: */\n\t\t{{{0x24a6d0bb, 0x1e32a6df, 0x1a1afdc6, 0x274c48bd, 0x26418f65, 0x069b62a2, 0x3f9f3f31, 0x075862e5, 0x5e5f}},\n\t\t {{0x1033eaf9, 0x1a0e11e4, 0x06f653a1, 0x1557cb94, 0x2721da72, 0x3daf3413, 0x3e6f7358, 0x140ac1a9, 0xd7b1}}},\n\t\t/* 15*16^24*G: */\n\t\t{{{0x0f005e3f, 0x36a6d791, 0x2c39bd2d, 0x3da38c6f, 0x01a1495a, 0x0f2e6b38, 0x2427fffd, 0x229acf05, 0xf813}},\n\t\t {{0x2f357eb7, 0x0b5f8080, 0x14be2134, 0x3b106f55, 0x25cb51f4, 0x005795ea, 0x0ebd9f9d, 0x23cefbed, 0xca75}}}\n\t},\n\t{\n\t\t/*  1*16^25*G: */\n\t\t{{{0x17bdde39, 0x0b00a910, 0x36043295, 0x11385e6d, 0x1968d315, 0x095c3566, 0x3cf0e10a, 0x1044fd9d, 0x76e6}},\n\t\t {{0x1901ac01, 0x12c5d4b4, 0x16d2032b, 0x0a8cf4ad, 0x01f0d35e, 0x019b5c1a, 0x295cf577, 0x37e37b93, 0xc90d}}},\n\t\t/*  3*16^25*G: */\n\t\t{{{0x0078ee8d, 0x3c142473, 0x06919442, 0x2fc83394, 0x1b4ff64e, 0x3dc98eaa, 0x1a9be25f, 0x15eb6167, 0xd08e}},\n\t\t {{0x2da63e86, 0x265fd370, 0x022ed9de, 0x0fbdf3e5, 0x3e6df412, 0x05cbb9d5, 0x088d72d6, 0x25e612ad, 0x852e}}},\n\t\t/*  5*16^25*G: */\n\t\t{{{0x029129ec, 0x164519c1, 0x24825481, 0x2b8eb3c7, 0x131d080c, 0x22fa03b3, 0x04d275f5, 0x30217935, 0x7da6}},\n\t\t {{0x2cd9ff0e, 0x2d42bb8a, 0x0ca586ae, 0x12302195, 0x1627bf04, 0x34081d24, 0x01857511, 0x051aee7d, 0xf498}}},\n\t\t/*  7*16^25*G: */\n\t\t{{{0x11654f22, 0x3e0f5255, 0x31aaee94, 0x3dfce508, 0x29d94fb2, 0x3a4006f9, 0x1be6e21b, 0x2433fd70, 0x90d0}},\n\t\t {{0x201a43e1, 0x3d77815d, 0x1a3f8740, 0x358d594f, 0x3f70336d, 0x3c08781a, 0x0f61a953, 0x26874aeb, 0xcd56}}},\n\t\t/*  9*16^25*G: */\n\t\t{{{0x076b19fa, 0x2dbbd947, 0x28819d71, 0x35b81b41, 0x21292ed9, 0x08b0c420, 0x1d1ecc73, 0x26161f3c, 0xda47}},\n\t\t {{0x326f5af7, 0x2a89bbac, 0x153fc206, 0x1ef44fa5, 0x16569ea6, 0x0da41df8, 0x0af01d17, 0x35de26f3, 0xebb1}}},\n\t\t/* 11*16^25*G: */\n\t\t{{{0x39135dbd, 0x364bed96, 0x1d8631ec, 0x3021ebce, 0x29897cf0, 0x1eabd60b, 0x1ee6ad81, 0x1d412a37, 0xe3e4}},\n\t\t {{0x0748045d, 0x241abcf9, 0x2c95da96, 0x2880bfd7, 0x383ffea5, 0x2320654a, 0x3c6c40b9, 0x16fe0272, 0x930a}}},\n\t\t/* 13*16^25*G: */\n\t\t{{{0x0dee455f, 0x2fc2e797, 0x0ce4075c, 0x19fff9ba, 0x0bdb4aff, 0x114ce3e0, 0x0a9b0a47, 0x195bfa1c, 0x7e8c}},\n\t\t {{0x171b9cba, 0x1cf7a660, 0x2f466271, 0x28b459d1, 0x03a53b4a, 0x3dd83d20, 0x0740f2a3, 0x318cb28c, 0xbddd}}},\n\t\t/* 15*16^25*G: */\n\t\t{{{0x2698b59e, 0x1de5ae6d, 0x13447a43, 0x0cd64962, 0x23c7260a, 0x2c0d6acf, 0x15eb15be, 0x107e246a, 0x3df8}},\n\t\t {{0x2b92baf5, 0x33e399e5, 0x14949f8b, 0x3f219ec8, 0x1cf3867b, 0x0aeba3c4, 0x090c1da0, 0x39b7e62c, 0xb38f}}}\n\t},\n\t{\n\t\t/*  1*16^26*G: */\n\t\t{{{0x2bcbb891, 0x2ac54090, 0x326cbee3, 0x1f3190f7, 0x3f8f9a8f, 0x206ea9d0, 0x2abe1e82, 0x315ac0ec, 0xc738}},\n\t\t {{0x299a84c3, 0x1f9cd765, 0x080cfe91, 0x0c53bbde, 0x3fbbbb82, 0x063cbab2, 0x2d2537f7, 0x2d5e2546, 0x893f}}},\n\t\t/*  3*16^26*G: */\n\t\t{{{0x0761d58d, 0x12eabcce, 0x0d60e2f3, 0x1326f902, 0x20df7aca, 0x09028d5c, 0x3614610a, 0x1849e08f, 0xb8c4}},\n\t\t {{0x1d1051a4, 0x0e3a82ea, 0x2107c5b6, 0x1d411e17, 0x33c5053f, 0x1163da5f, 0x0e37d14a, 0x365b145c, 0x8f9e}}},\n\t\t/*  5*16^26*G: */\n\t\t{{{0x050b0040, 0x36c2cc10, 0x0134adc2, 0x3d1f6e7c, 0x1a3671f3, 0x03264ffa, 0x271f7a35, 0x1ba7dc40, 0x08d5}},\n\t\t {{0x1b3fd0a1, 0x163899e9, 0x21782beb, 0x35f11c83, 0x39b285f6, 0x34542a35, 0x29aa21ff, 0x216baf42, 0xa121}}},\n\t\t/*  7*16^26*G: */\n\t\t{{{0x13573b7f, 0x15958f7c, 0x30b6270f, 0x268717b4, 0x265a3788, 0x083e5def, 0x3ce6341e, 0x3c8cb50b, 0xdc13}},\n\t\t {{0x0c1f2ba6, 0x0ab348a1, 0x3404b1c4, 0x11551c05, 0x290a7670, 0x10436a12, 0x2340c3c7, 0x2ea010a7, 0xc909}}},\n\t\t/*  9*16^26*G: */\n\t\t{{{0x07ae9ceb, 0x00bd642e, 0x0ef2d14b, 0x1b087a9c, 0x2119a822, 0x0655976c, 0x37f073af, 0x0b798077, 0x25c0}},\n\t\t {{0x0bc6e275, 0x1c24344d, 0x26587264, 0x319077c2, 0x2d11d537, 0x2138373e, 0x2383c0c8, 0x3ab4b204, 0x8a9f}}},\n\t\t/* 11*16^26*G: */\n\t\t{{{0x2c5a3c34, 0x3e0263db, 0x15949fe1, 0x33a0b00a, 0x2e3e58ae, 0x2e7d329e, 0x0e49ce8a, 0x2746cb3e, 0xfedd}},\n\t\t {{0x213d7714, 0x0ad52fd3, 0x1bf82976, 0x2bad51a6, 0x0f4b00ad, 0x3a14c4b2, 0x3b8e0b0b, 0x0930c614, 0xa52e}}},\n\t\t/* 13*16^26*G: */\n\t\t{{{0x2ab6a396, 0x2d395346, 0x11360769, 0x0086e468, 0x0488b373, 0x38b5fd7a, 0x2a48c2de, 0x0ca1af1b, 0x3e0e}},\n\t\t {{0x1980e27e, 0x3acc7923, 0x3468f6a2, 0x2c04107c, 0x053fc66a, 0x07f877ad, 0x337964f3, 0x205cbe8e, 0xca44}}},\n\t\t/* 15*16^26*G: */\n\t\t{{{0x341023ec, 0x2bcd6188, 0x3ecf570a, 0x11763ddb, 0x02b9af56, 0x0b808026, 0x32d28498, 0x2e4c2030, 0x344a}},\n\t\t {{0x1e1eeb87, 0x13e260a4, 0x03995d70, 0x13a5dabf, 0x114c5ffc, 0x23cb47a9, 0x0462a73f, 0x0ac10ac9, 0x6e1c}}}\n\t},\n\t{\n\t\t/*  1*16^27*G: */\n\t\t{{{0x08f6c14b, 0x1cba7d96, 0x29250143, 0x35cb97ce, 0x172877d1, 0x131d8df2, 0x25b81e26, 0x1899522d, 0xd895}},\n\t\t {{0x1d7d991f, 0x24d8fb5d, 0x3b067e17, 0x10a358ca, 0x0340eb03, 0x3b182063, 0x07eae728, 0x2a8e3caf, 0xfebf}}},\n\t\t/*  3*16^27*G: */\n\t\t{{{0x2127b756, 0x02ea1ffd, 0x3a097048, 0x10a2f92a, 0x20b41603, 0x0d8b6941, 0x1f12672d, 0x1e0bdc5b, 0x6d8c}},\n\t\t {{0x3f172571, 0x1547dd2a, 0x17cdcca6, 0x0ea9b68b, 0x134daf4e, 0x26a0b4db, 0x1b911145, 0x37c225bf, 0x99ae}}},\n\t\t/*  5*16^27*G: */\n\t\t{{{0x358cf17a, 0x37b869cd, 0x18823524, 0x3e1772e9, 0x0097f8f1, 0x166bbc6d, 0x37aca8d0, 0x2fb7656f, 0xebca}},\n\t\t {{0x1caa0ccd, 0x11b3717d, 0x0ace95c4, 0x3eb484b4, 0x032e6b10, 0x00286d9f, 0x2b9cb02c, 0x3383e3c8, 0x47d3}}},\n\t\t/*  7*16^27*G: */\n\t\t{{{0x2c855c5b, 0x33bb9456, 0x17c8afbb, 0x21588680, 0x17fc2811, 0x0c68da78, 0x0ce24453, 0x134b92f5, 0xe8df}},\n\t\t {{0x2e465650, 0x27579cb0, 0x21e4d7d5, 0x18ed57c7, 0x2f32c596, 0x136d3d67, 0x39b26444, 0x3f5c311f, 0x6c57}}},\n\t\t/*  9*16^27*G: */\n\t\t{{{0x12e7e454, 0x023d6f69, 0x30e6150d, 0x0cbbfbc3, 0x181662fe, 0x121808ea, 0x0a832912, 0x34f5c63b, 0x4068}},\n\t\t {{0x18ef191e, 0x1e6b3797, 0x3c373327, 0x23487b44, 0x1d38d198, 0x305165f6, 0x247aab9e, 0x14edc952, 0x8cd8}}},\n\t\t/* 11*16^27*G: */\n\t\t{{{0x06c5d939, 0x215eb7e1, 0x3a933de0, 0x1d68a1de, 0x0a027ea4, 0x2fccb983, 0x025e0b55, 0x03b36c76, 0x1255}},\n\t\t {{0x19e757c9, 0x0a9d3f15, 0x0d8d4319, 0x22dd07fb, 0x324a7283, 0x2390f05d, 0x2d7a7544, 0x20cd3e1c, 0x7b8f}}},\n\t\t/* 13*16^27*G: */\n\t\t{{{0x16c8a56f, 0x2342ab19, 0x0f374213, 0x024f150d, 0x3ad08f85, 0x2eded4eb, 0x185d4c69, 0x19c6b0ed, 0x944d}},\n\t\t {{0x1a7be289, 0x27d37197, 0x106517eb, 0x35305d37, 0x3ac61967, 0x10e4d84c, 0x01fff4c1, 0x1965ded4, 0xa710}}},\n\t\t/* 15*16^27*G: */\n\t\t{{{0x2e08f15a, 0x3bae2862, 0x012900ba, 0x1a795b72, 0x13c305fd, 0x2c0d956b, 0x19a0cfe6, 0x13a47342, 0x86a5}},\n\t\t {{0x01388308, 0x1493479f, 0x335254d3, 0x04a74496, 0x35686777, 0x0aa341b5, 0x384603a7, 0x18520de9, 0xcfee}}}\n\t},\n\t{\n\t\t/*  1*16^28*G: */\n\t\t{{{0x0f676e03, 0x24542959, 0x3e84edd4, 0x3ff1cda4, 0x1e8761ce, 0x3d90cd5c, 0x17518eb0, 0x2500caa5, 0xb8da}},\n\t\t {{0x0efdf6e7, 0x1223939d, 0x1ff3b511, 0x33161365, 0x2808b092, 0x267325d8, 0x1a1e4d7c, 0x37e91201, 0x2804}}},\n\t\t/*  3*16^28*G: */\n\t\t{{{0x06e1346b, 0x28661277, 0x05af1c5e, 0x2f9ec40e, 0x1152c05a, 0x31d87c53, 0x2d10be54, 0x1a3fc260, 0x0690}},\n\t\t {{0x17226c13, 0x2ed62953, 0x0c6026e7, 0x3da24e65, 0x06442aa4, 0x176caf42, 0x3de26da8, 0x38f8242f, 0xb863}}},\n\t\t/*  5*16^28*G: */\n\t\t{{{0x1ca1f6a1, 0x039a47f3, 0x08cff1a3, 0x232f450d, 0x286ce106, 0x1b7172c7, 0x19761528, 0x0d24f2c9, 0x898c}},\n\t\t {{0x164f647c, 0x12b7083c, 0x32bd79ca, 0x29f3e5e7, 0x2c6e93b2, 0x1150914a, 0x2a5549d8, 0x1661aad5, 0x75f7}}},\n\t\t/*  7*16^28*G: */\n\t\t{{{0x3d1e3998, 0x29a780f0, 0x3a04328a, 0x15b22e45, 0x2a274e5e, 0x0a675c08, 0x18bf01a5, 0x38bfb4a4, 0xb213}},\n\t\t {{0x325fb81e, 0x30b2f718, 0x3ded175e, 0x0d0596fa, 0x243bc3d5, 0x187afe0e, 0x13c12c3d, 0x23b083cb, 0x229f}}},\n\t\t/*  9*16^28*G: */\n\t\t{{{0x225be234, 0x02f87fb2, 0x1df35070, 0x20f8f9c3, 0x206e060e, 0x342e9a45, 0x3f93e5d1, 0x0eb605b1, 0x4b3b}},\n\t\t {{0x120e8362, 0x18edf80e, 0x3211b840, 0x39ff64b3, 0x0cc04c41, 0x17a5b7f6, 0x2bc9c787, 0x008ee176, 0x5eec}}},\n\t\t/* 11*16^28*G: */\n\t\t{{{0x2289f55e, 0x2598d29f, 0x2c76707b, 0x1dac3c38, 0x0965be29, 0x0946c09e, 0x04f96020, 0x222db76c, 0x9f7b}},\n\t\t {{0x3e1e4bde, 0x0f34ed97, 0x310a2b1b, 0x394db83a, 0x0fc71fc0, 0x051ad0a6, 0x010f7be3, 0x3de131c1, 0x32f9}}},\n\t\t/* 13*16^28*G: */\n\t\t{{{0x1dfe1d2b, 0x19527230, 0x16878e51, 0x24fd4279, 0x3b73a4c4, 0x332b7f4f, 0x048e3e76, 0x10fa72dd, 0xd58a}},\n\t\t {{0x0cd50922, 0x33c9e56e, 0x0bd6fbff, 0x366e8857, 0x28276b54, 0x1ca44ca0, 0x083cf10a, 0x219ae816, 0xfc17}}},\n\t\t/* 15*16^28*G: */\n\t\t{{{0x249c795e, 0x090546f8, 0x1ce805e1, 0x1101aaa6, 0x27ea4eed, 0x365a70f0, 0x18310cd6, 0x1c4e5c44, 0x21d2}},\n\t\t {{0x19208ece, 0x0004bb0e, 0x2dfb761b, 0x1c651292, 0x2bb4c3d6, 0x0d6e1548, 0x1acea177, 0x3e6d2c1d, 0x94c5}}}\n\t},\n\t{\n\t\t/*  1*16^29*G: */\n\t\t{{{0x23c0df5d, 0x06845de3, 0x156a792f, 0x067bfed4, 0x1d7fab20, 0x2b6ae51d, 0x3b33a7d8, 0x3a851107, 0xe80f}},\n\t\t {{0x2ac9ec78, 0x32d0a46d, 0x3322ea9f, 0x0557a02b, 0x0a94472d, 0x25da328f, 0x200771e8, 0x379fd8e3, 0xeed1}}},\n\t\t/*  3*16^29*G: */\n\t\t{{{0x17592d55, 0x300d67b3, 0x0e350192, 0x356e51d0, 0x3ce3b106, 0x3fbda58c, 0x1052608a, 0x31b6f128, 0x5d2e}},\n\t\t {{0x2f5183a7, 0x19b9743a, 0x11151742, 0x0a9ef36b, 0x0cd6950e, 0x1c43e89a, 0x245eb58f, 0x337e271b, 0x0a92}}},\n\t\t/*  5*16^29*G: */\n\t\t{{{0x3e8f9f5c, 0x247d2d27, 0x1880a519, 0x187c7856, 0x1f404d73, 0x32b8d085, 0x3f742fe2, 0x0770ec46, 0xac37}},\n\t\t {{0x325a503c, 0x1ea0ffcc, 0x2751e1d1, 0x254d163b, 0x14e73522, 0x04079cc9, 0x1a477ff2, 0x05b061c2, 0xc516}}},\n\t\t/*  7*16^29*G: */\n\t\t{{{0x19e33446, 0x12872354, 0x2af385df, 0x224ef114, 0x22a17a40, 0x2302f408, 0x1840c934, 0x000e853c, 0x8942}},\n\t\t {{0x26387689, 0x034e2803, 0x1e74f984, 0x3f5dcd9e, 0x3de4e06b, 0x2cb5b43b, 0x1077a4d8, 0x00e56569, 0xa9fd}}},\n\t\t/*  9*16^29*G: */\n\t\t{{{0x3913cb26, 0x35ca3256, 0x13bd6d03, 0x3ad06700, 0x105c9899, 0x36913fd5, 0x342a8a2c, 0x099acc28, 0x2770}},\n\t\t {{0x3348a7a2, 0x3f9c5ccf, 0x0815bebb, 0x103246f3, 0x32b324e9, 0x0b49341f, 0x0db1a555, 0x2f179e6c, 0xf649}}},\n\t\t/* 11*16^29*G: */\n\t\t{{{0x195e8247, 0x02aa8085, 0x286cd1af, 0x2ff71155, 0x38ba9097, 0x179b8073, 0x3ed2178e, 0x3434e0f2, 0x75e4}},\n\t\t {{0x19982d22, 0x288ff675, 0x29ad893c, 0x36ad6dba, 0x3726d47d, 0x3e5c3b1e, 0x10990741, 0x10a85d50, 0x1fce}}},\n\t\t/* 13*16^29*G: */\n\t\t{{{0x26333323, 0x11e7d136, 0x0f4abf47, 0x2eef071a, 0x04da849c, 0x08358166, 0x1bbf03f0, 0x2d8e0cd8, 0x3ed1}},\n\t\t {{0x35d61ba3, 0x2c4ff122, 0x378f7294, 0x2dca2842, 0x0f929ea9, 0x1f2625a2, 0x34ee75d9, 0x0b6922d6, 0xd84f}}},\n\t\t/* 15*16^29*G: */\n\t\t{{{0x333980bf, 0x09415f52, 0x0dd00baf, 0x28dc0b94, 0x08dd4368, 0x1bf5dc8d, 0x18181b84, 0x34bc1a9d, 0x70fd}},\n\t\t {{0x20b75785, 0x0bbaa33a, 0x1d74a561, 0x040d60e1, 0x2e596b0a, 0x29043447, 0x18696957, 0x32b03435, 0x5edf}}}\n\t},\n\t{\n\t\t/*  1*16^30*G: */\n\t\t{{{0x04e16070, 0x3701eef3, 0x2fd6915d, 0x286080c7, 0x167543f2, 0x29239475, 0x1704313b, 0x1a5ef7f3, 0xa301}},\n\t\t {{0x1e177ea1, 0x30346810, 0x0a11a130, 0x0d76fdf0, 0x140f9b17, 0x2027e897, 0x3e4f5081, 0x3e473ed9, 0x7370}}},\n\t\t/*  3*16^30*G: */\n\t\t{{{0x138011fc, 0x1c049c00, 0x17285626, 0x165a99eb, 0x200a4d83, 0x2c4cc208, 0x1eb11156, 0x04e8c205, 0x6e83}},\n\t\t {{0x3f15ab7d, 0x2b2da7e8, 0x1c51f9a6, 0x2be456ba, 0x1ac30426, 0x04b6c807, 0x0f204c1a, 0x2062f709, 0xc147}}},\n\t\t/*  5*16^30*G: */\n\t\t{{{0x100e6ba7, 0x0e9d26e3, 0x0916f7f5, 0x0dbb16d1, 0x19e1b43d, 0x0780e293, 0x0851f2bd, 0x2a4265e1, 0xf952}},\n\t\t {{0x0175e4c1, 0x36ebbb94, 0x062a2b98, 0x15c59ed3, 0x3fa0f655, 0x0dda8b89, 0x3cebf861, 0x0e96c22a, 0xd8a9}}},\n\t\t/*  7*16^30*G: */\n\t\t{{{0x03aa0e93, 0x2401968a, 0x2fb1f626, 0x0b8e50eb, 0x1e893a8f, 0x00c68676, 0x3fee7504, 0x1b578c74, 0x9401}},\n\t\t {{0x07addac2, 0x23bb49a2, 0x257b07a3, 0x210dceea, 0x2e6fd7f4, 0x1574d53b, 0x14d96403, 0x0cbb9711, 0x6750}}},\n\t\t/*  9*16^30*G: */\n\t\t{{{0x0266b17b, 0x03d218b8, 0x262bb32b, 0x0d5a2880, 0x1f09c202, 0x25e211aa, 0x3b2891bb, 0x345d3567, 0xef22}},\n\t\t {{0x39dac83e, 0x0a9b810d, 0x1c341b73, 0x39c9dbdc, 0x34a1073e, 0x27330eb8, 0x24c7568f, 0x21325eac, 0xbc57}}},\n\t\t/* 11*16^30*G: */\n\t\t{{{0x12d382a0, 0x0c4c056a, 0x2ecd9ae2, 0x2372ef38, 0x2df927f2, 0x2b31e02c, 0x3892d39c, 0x3bf3933a, 0xb5f7}},\n\t\t {{0x25b4b532, 0x28bc2aee, 0x1acf8c5b, 0x3ec25b4a, 0x0bddd371, 0x255f1b83, 0x3f2353c0, 0x1516d470, 0x6843}}},\n\t\t/* 13*16^30*G: */\n\t\t{{{0x012cffa5, 0x39a49191, 0x28cc5c47, 0x3b508219, 0x14624389, 0x1d5363ef, 0x31076408, 0x30f4acb9, 0x1cdd}},\n\t\t {{0x1521954e, 0x379b6273, 0x336b528a, 0x0726109a, 0x02b08ac4, 0x2c49afe5, 0x1f8a63fd, 0x1a832cbc, 0x1e47}}},\n\t\t/* 15*16^30*G: */\n\t\t{{{0x34a9f22f, 0x0d7f90e4, 0x17a8e2ad, 0x02067148, 0x0835b0cc, 0x3e2e2e52, 0x0e939f21, 0x2cd67c97, 0x2acc}},\n\t\t {{0x375c4927, 0x2dd772ce, 0x1ba550b7, 0x12f5efb1, 0x30edf115, 0x04e8dfb7, 0x2d2e5192, 0x293a5622, 0xd518}}}\n\t},\n\t{\n\t\t/*  1*16^31*G: */\n\t\t{{{0x3fb04ed4, 0x2deb18f8, 0x1307fffa, 0x330cc2c4, 0x278de208, 0x3e741449, 0x2b936463, 0x216ce275, 0x90ad}},\n\t\t {{0x0b6ef150, 0x24753523, 0x182894d9, 0x2bbeaf85, 0x3222b839, 0x372f6509, 0x38261aff, 0x1e8d8828, 0x0e50}}},\n\t\t/*  3*16^31*G: */\n\t\t{{{0x30b7b678, 0x09d76cce, 0x0f638166, 0x0f10c46f, 0x2b6c76f1, 0x21af2909, 0x0231ba19, 0x125ccd39, 0x186e}},\n\t\t {{0x38d91fc1, 0x1e81dbcb, 0x09535dca, 0x01dc8951, 0x37e67e11, 0x3f209702, 0x3bd84aa7, 0x18392601, 0xc0d4}}},\n\t\t/*  5*16^31*G: */\n\t\t{{{0x33421fb8, 0x3c1b972e, 0x35a55d0c, 0x125c7cbb, 0x37241298, 0x01acd30e, 0x1bf62e7e, 0x2360d3db, 0x061c}},\n\t\t {{0x0e3ccd80, 0x257bd9a1, 0x26fcdd29, 0x19c4d2ce, 0x05eb5c80, 0x0e496438, 0x3b4b7ba9, 0x1ab66400, 0x6dfc}}},\n\t\t/*  7*16^31*G: */\n\t\t{{{0x2f6b35a4, 0x0492f862, 0x327fb487, 0x27cde9aa, 0x3a68ad88, 0x18c901cc, 0x2e513b73, 0x2d8e8823, 0xf6a6}},\n\t\t {{0x01f422a6, 0x2badbfb2, 0x1ee1862c, 0x355d5b9d, 0x20186f19, 0x34dc13d5, 0x1138b1ca, 0x322a000b, 0x3df7}}},\n\t\t/*  9*16^31*G: */\n\t\t{{{0x26954c11, 0x25a08fa2, 0x160d018b, 0x2a290f05, 0x0778ff7f, 0x346c3c54, 0x2c376220, 0x3f0a30a1, 0x87a2}},\n\t\t {{0x272a8b45, 0x15b8ccb8, 0x278124b7, 0x1224cfca, 0x127532cc, 0x06523683, 0x2ecef97b, 0x1462d16a, 0x33ad}}},\n\t\t/* 11*16^31*G: */\n\t\t{{{0x22706ab6, 0x391d1cab, 0x2e53c0da, 0x02cd0774, 0x384cfe3c, 0x15bbf2f0, 0x081a6845, 0x0b811b9e, 0xe147}},\n\t\t {{0x1d58de05, 0x1ba1a85a, 0x13cd2753, 0x16275551, 0x0621f8aa, 0x1a465e32, 0x18fc683f, 0x24aa91f1, 0x82cd}}},\n\t\t/* 13*16^31*G: */\n\t\t{{{0x07a84fb6, 0x2feb9508, 0x3a15021e, 0x08da1d43, 0x08b9ebc4, 0x2d358079, 0x0aef5de8, 0x24b2013e, 0x1caf}},\n\t\t {{0x27149109, 0x1ac60640, 0x22ce6761, 0x07305a5a, 0x101622ec, 0x2993e3fc, 0x2e53a481, 0x2e16b25d, 0xbc24}}},\n\t\t/* 15*16^31*G: */\n\t\t{{{0x0a955911, 0x1da33f85, 0x0ded52db, 0x1f85a898, 0x17839710, 0x27bfa6cf, 0x1650d258, 0x3f5a6bc2, 0x705b}},\n\t\t {{0x3fd200e4, 0x2edf1a4f, 0x242e72d8, 0x1fced48a, 0x0051fa29, 0x18f607d5, 0x3f990a7e, 0x2904c2dc, 0xe14a}}}\n\t},\n\t{\n\t\t/*  1*16^32*G: */\n\t\t{{{0x1ec4c0da, 0x2ded1132, 0x23ea3351, 0x23159e1c, 0x1f162ee8, 0x2706b660, 0x35f33923, 0x2e74bd8e, 0x8f68}},\n\t\t {{0x101fff82, 0x08f2fde5, 0x1510bfdf, 0x3a8b3fa5, 0x3e215dbb, 0x36430ada, 0x23986de1, 0x27cb6e81, 0x662a}}},\n\t\t/*  3*16^32*G: */\n\t\t{{{0x123809fa, 0x238ae3b7, 0x1d954be1, 0x21172cd4, 0x051f08fd, 0x24cd8fc9, 0x09f228ba, 0x076f8b94, 0x3838}},\n\t\t {{0x331fed52, 0x35c1d460, 0x2d8f24db, 0x207f32cc, 0x0eb1cc36, 0x10169548, 0x117dcb09, 0x0b4283ee, 0xe4a3}}},\n\t\t/*  5*16^32*G: */\n\t\t{{{0x17c2a310, 0x3a909922, 0x01226303, 0x21aba950, 0x0699a1f1, 0x086e0aa9, 0x32ae6f69, 0x09c9390d, 0x4926}},\n\t\t {{0x1e27ded0, 0x3106da05, 0x35ff8ce0, 0x058d84a9, 0x14303b6d, 0x33e95a5c, 0x3abf95a2, 0x39dcef29, 0x1337}}},\n\t\t/*  7*16^32*G: */\n\t\t{{{0x0ebd2d31, 0x0e12c1e7, 0x306db8d1, 0x330695bf, 0x37e2f84d, 0x094ecf91, 0x00c90d5e, 0x15a30689, 0xe306}},\n\t\t {{0x12546e44, 0x24ad020e, 0x23738266, 0x2f2010af, 0x3d0db6ff, 0x3cac41fd, 0x34260888, 0x1bf8de24, 0x0eac}}},\n\t\t/*  9*16^32*G: */\n\t\t{{{0x363136b0, 0x14c30e78, 0x2b41dd9c, 0x3afe366a, 0x3bd63374, 0x2c39d88f, 0x0cefc271, 0x0403890a, 0x3b9e}},\n\t\t {{0x2cdbbc8a, 0x14fb05bd, 0x2d31f819, 0x2b8a28ce, 0x075b26a2, 0x14cfae3d, 0x2bb71df1, 0x26054b45, 0xfafb}}},\n\t\t/* 11*16^32*G: */\n\t\t{{{0x2f485d3f, 0x1823c11c, 0x107beee9, 0x3281da20, 0x1edef717, 0x1b2a03d7, 0x2c9a92b7, 0x2b525c4a, 0xbb0a}},\n\t\t {{0x3ca2f975, 0x1e4e4940, 0x1670bffe, 0x1696be8c, 0x17da3489, 0x34807dca, 0x354798ec, 0x2714f160, 0xea69}}},\n\t\t/* 13*16^32*G: */\n\t\t{{{0x36718dc9, 0x2bbb4ce8, 0x01123de4, 0x3962d36c, 0x3e0113e1, 0x23ac65eb, 0x2fcc0d4e, 0x02b2393b, 0x7909}},\n\t\t {{0x1cfae7c5, 0x18cc8ac4, 0x3a9008b9, 0x0dabedc2, 0x1aaa56dd, 0x205b2f36, 0x05b8f13d, 0x1c8ae464, 0xeaab}}},\n\t\t/* 15*16^32*G: */\n\t\t{{{0x3f60c7d1, 0x09a5a531, 0x1775ad2a, 0x35c779f3, 0x09ba668d, 0x0f6ef395, 0x17b551c0, 0x206b7a7e, 0xe77c}},\n\t\t {{0x02d72449, 0x3b1607ca, 0x02986d34, 0x051c3dc7, 0x28154363, 0x30ecc8fa, 0x01321c5f, 0x051e3bbe, 0x3acf}}}\n\t},\n\t{\n\t\t/*  1*16^33*G: */\n\t\t{{{0x13231e11, 0x1a1bf541, 0x3681e3e6, 0x123a1940, 0x0c36091f, 0x267fe466, 0x385d65ff, 0x3ec05dab, 0xe4f3}},\n\t\t {{0x2feb73bc, 0x08b0e15d, 0x151d1c98, 0x31f9d3b2, 0x02b7286c, 0x069b43a8, 0x34f1c166, 0x18ceb43b, 0x1e63}}},\n\t\t/*  3*16^33*G: */\n\t\t{{{0x2bf05bd6, 0x0e67c139, 0x12a99465, 0x3d5b80c8, 0x070deca2, 0x0bd47fad, 0x04fe9083, 0x0c906fb9, 0x900c}},\n\t\t {{0x300d358b, 0x394ab4ef, 0x04efb15d, 0x2614d60f, 0x0b2439d6, 0x31c8115c, 0x1f0f5f95, 0x3e7a3a2c, 0x6c31}}},\n\t\t/*  5*16^33*G: */\n\t\t{{{0x1f105c50, 0x29f0a332, 0x31385257, 0x3837bbde, 0x0233cd82, 0x2330d00f, 0x190aad62, 0x00d8aac1, 0x5a8d}},\n\t\t {{0x38a4cde9, 0x326c8060, 0x2d013c35, 0x017da299, 0x03ff74a6, 0x29adc905, 0x0e536936, 0x3aac44f5, 0xc059}}},\n\t\t/*  7*16^33*G: */\n\t\t{{{0x32d64feb, 0x11f862e6, 0x292292c6, 0x1cbe2964, 0x0ba4e837, 0x3ce95ddb, 0x2f60a48e, 0x1340c48c, 0xd93f}},\n\t\t {{0x34698359, 0x2c3ef564, 0x2c90da37, 0x3810c2fb, 0x1c8c4d93, 0x1cc47153, 0x32733a23, 0x15575172, 0x7925}}},\n\t\t/*  9*16^33*G: */\n\t\t{{{0x039fbc84, 0x08881335, 0x057a0167, 0x1c18a458, 0x2ac65b7e, 0x138af198, 0x328441b1, 0x1a71b8db, 0x2f07}},\n\t\t {{0x1c201bec, 0x3ee40b78, 0x04dd5d73, 0x29e6da93, 0x0e2149cc, 0x37c01e64, 0x3bdddfa5, 0x3cdc935c, 0xb434}}},\n\t\t/* 11*16^33*G: */\n\t\t{{{0x06a758ea, 0x14dfab32, 0x27f19c4d, 0x0620c624, 0x016e3991, 0x1a256855, 0x20309958, 0x19e01567, 0xfe7e}},\n\t\t {{0x1b7ab649, 0x13c8b657, 0x03120d1e, 0x2005c1d1, 0x09251f3b, 0x02385a61, 0x1dcb988c, 0x1a59e8a0, 0x38aa}}},\n\t\t/* 13*16^33*G: */\n\t\t{{{0x0cfffefa, 0x39c5589a, 0x0651afad, 0x060113dc, 0x03af8510, 0x3dbe4543, 0x03127d6d, 0x3d729d4e, 0x91ba}},\n\t\t {{0x1f7f6faf, 0x1f4dbcd3, 0x2fd303dc, 0x2fbcc439, 0x1d3d92f4, 0x25a7c49f, 0x3bcebe5d, 0x33c464d1, 0x04e5}}},\n\t\t/* 15*16^33*G: */\n\t\t{{{0x0d33c546, 0x3f0245fa, 0x05edaf32, 0x15d7ecca, 0x35ddd782, 0x314dcf83, 0x378a7cb2, 0x104872cf, 0x4458}},\n\t\t {{0x000b4fd4, 0x029b461c, 0x32ca7366, 0x0bc28f3e, 0x1ada2085, 0x097ab8e4, 0x0753a772, 0x24ddfcfe, 0x308d}}}\n\t},\n\t{\n\t\t/*  1*16^34*G: */\n\t\t{{{0x20eae29e, 0x1bedbab8, 0x14e1d071, 0x00d3cbc3, 0x1a4266c7, 0x1854de91, 0x3f331eb9, 0x3ea6c63a, 0x8c00}},\n\t\t {{0x2702414b, 0x1f4a9319, 0x1e36c54e, 0x3eb6bea0, 0x36c974c2, 0x30d0e8dc, 0x121a1a9d, 0x1c99ffa9, 0xefa4}}},\n\t\t/*  3*16^34*G: */\n\t\t{{{0x2bfd913d, 0x0fe5580f, 0x254c9eac, 0x29a039bb, 0x2a8d2050, 0x01e82130, 0x3ddf874d, 0x0aa9fa41, 0x3636}},\n\t\t {{0x052e243d, 0x113e6bab, 0x2b2faafc, 0x0c2ec435, 0x1a2a82d8, 0x18910dc3, 0x0afd5341, 0x1e19db2e, 0x48f2}}},\n\t\t/*  5*16^34*G: */\n\t\t{{{0x2d132896, 0x32aeafe6, 0x3bc6c967, 0x2c78eead, 0x19200dfc, 0x16b658b7, 0x21e02f29, 0x25db7cca, 0x4487}},\n\t\t {{0x2f685248, 0x23006c4a, 0x276aa7a4, 0x2d035698, 0x161a3306, 0x26a41dd1, 0x1afe1efc, 0x16183445, 0x27bd}}},\n\t\t/*  7*16^34*G: */\n\t\t{{{0x3fa2670c, 0x02055bda, 0x06273e6e, 0x003e0ae8, 0x35032474, 0x2a72aa0c, 0x383788b6, 0x0eb0a2f2, 0x4a4d}},\n\t\t {{0x16c1764d, 0x022e7ff7, 0x329beed8, 0x0c16532f, 0x302b9d49, 0x1dc4777b, 0x05a4f17e, 0x2e470061, 0x70ab}}},\n\t\t/*  9*16^34*G: */\n\t\t{{{0x0cb24aa7, 0x365abf89, 0x1345c530, 0x0c42318e, 0x38fe1890, 0x39bf627f, 0x11802c3a, 0x0b4642ba, 0x5f7b}},\n\t\t {{0x0a693d7d, 0x35e01d0d, 0x3c81d0c6, 0x237adc24, 0x267c47ce, 0x0fe028f3, 0x1f2b330a, 0x0d80313f, 0x0770}}},\n\t\t/* 11*16^34*G: */\n\t\t{{{0x2f7fb8bd, 0x0646f17c, 0x3e4090a4, 0x31192857, 0x0886d87b, 0x30939b65, 0x190d02ae, 0x1d144ce7, 0x5139}},\n\t\t {{0x03908c0f, 0x0252b0b6, 0x3f98d5a8, 0x3f0cb4f8, 0x015c47fa, 0x23fbf6ba, 0x03bf34b8, 0x050f91d9, 0xfcd7}}},\n\t\t/* 13*16^34*G: */\n\t\t{{{0x2e36ca73, 0x0add2457, 0x3bbf3ede, 0x321934da, 0x014887ea, 0x0a444afc, 0x3dfb8aa4, 0x05b58afe, 0xcf83}},\n\t\t {{0x2ec25534, 0x2d248650, 0x08d710f5, 0x25856636, 0x1cca681c, 0x11142243, 0x19d73e38, 0x2d637ad7, 0x09fe}}},\n\t\t/* 15*16^34*G: */\n\t\t{{{0x3752f97d, 0x3224df5a, 0x33476613, 0x0bbef1d7, 0x0fa6165a, 0x274a19a3, 0x3b49de53, 0x37a69312, 0x8610}},\n\t\t {{0x1f1b1af2, 0x015f7350, 0x05543e08, 0x2ad367d5, 0x33f99e57, 0x33666c94, 0x30bbc937, 0x25e80ad8, 0xd319}}}\n\t},\n\t{\n\t\t/*  1*16^35*G: */\n\t\t{{{0x20cb3e41, 0x25ff77f1, 0x08b92c09, 0x0f4213cc, 0x298ed314, 0x033b02a7, 0x0829f3e1, 0x1b39a775, 0xe7a2}},\n\t\t {{0x0f2cfd51, 0x3a2a5087, 0x20e83e20, 0x29acb010, 0x2fbb18d0, 0x2c01a86a, 0x3984b471, 0x238c03e9, 0x2a75}}},\n\t\t/*  3*16^35*G: */\n\t\t{{{0x3aee42db, 0x03e7f4af, 0x330714a7, 0x2eef16d1, 0x2cbfc1d9, 0x2dbb6e47, 0x19150fc7, 0x09f9f66d, 0xcc34}},\n\t\t {{0x15d87bdb, 0x188a7004, 0x272422dc, 0x3972eb63, 0x21520010, 0x38ff4fec, 0x1c6a1885, 0x26106948, 0xea24}}},\n\t\t/*  5*16^35*G: */\n\t\t{{{0x3ed4a086, 0x3d0d9b19, 0x29c410ef, 0x35d70563, 0x0b5cf4b1, 0x0f1617ef, 0x0445dec8, 0x016eb366, 0x948f}},\n\t\t {{0x1e2bca4b, 0x0a86003e, 0x03fa2d1a, 0x08ca29c7, 0x1139411c, 0x11429980, 0x22a3382f, 0x2a27fed6, 0x864c}}},\n\t\t/*  7*16^35*G: */\n\t\t{{{0x37542c21, 0x032fa9b2, 0x2a64c15c, 0x067d34a3, 0x1d6d43ae, 0x1bf11514, 0x19ac9065, 0x0658a4a4, 0x2584}},\n\t\t {{0x272bfabf, 0x2faf8c65, 0x0c2ad7b3, 0x38e861b9, 0x3513d5f3, 0x176a9331, 0x3244801e, 0x16c7c736, 0xfcb3}}},\n\t\t/*  9*16^35*G: */\n\t\t{{{0x0c1ecbf8, 0x0f1187d0, 0x2eed7ca4, 0x227c37a6, 0x28421f64, 0x25d53307, 0x3c52522a, 0x337104dc, 0x7e12}},\n\t\t {{0x30bed615, 0x3516e336, 0x3e1d9f59, 0x1a7d8763, 0x0d1259c9, 0x3e536af9, 0x1c837143, 0x13e22223, 0x7128}}},\n\t\t/* 11*16^35*G: */\n\t\t{{{0x14557d86, 0x1f999470, 0x2667ff41, 0x3fbb11e3, 0x05a6cf1c, 0x2e4729e8, 0x342a6772, 0x30bfca8d, 0x4b8e}},\n\t\t {{0x35167eb9, 0x3766c646, 0x3c3f692b, 0x357cbbc3, 0x27ac5f28, 0x101cb794, 0x157ab14a, 0x30ffc130, 0xfde6}}},\n\t\t/* 13*16^35*G: */\n\t\t{{{0x0780763c, 0x0ae0b4ed, 0x265691d5, 0x229b57a4, 0x3ac07e5f, 0x10db71a5, 0x23a42532, 0x3041cce5, 0xfcd5}},\n\t\t {{0x38e851cb, 0x1539d080, 0x16463a4b, 0x066c8b9c, 0x32e38cb1, 0x0836cd7d, 0x22c463b7, 0x2af8b954, 0x18dd}}},\n\t\t/* 15*16^35*G: */\n\t\t{{{0x1d8ef686, 0x338ef8c1, 0x2272e66b, 0x23923d00, 0x266e53f6, 0x22976be0, 0x3cbe5223, 0x0b3b9610, 0x900f}},\n\t\t {{0x2121a8cf, 0x1ce9259f, 0x09156d50, 0x1b37fd0f, 0x09d11059, 0x31546c4d, 0x0425ad61, 0x30557b18, 0x732a}}}\n\t},\n\t{\n\t\t/*  1*16^36*G: */\n\t\t{{{0x1e6b80ef, 0x33ca7acf, 0x179424f3, 0x32f2e59f, 0x3cbdc571, 0x1503088e, 0x22ec8d23, 0x2783b8d9, 0xb645}},\n\t\t {{0x1a71ba45, 0x0c2fc2d8, 0x0e35b2ff, 0x2ceb9b52, 0x261db3c4, 0x2b7c5b95, 0x3e06de1d, 0x21db41bc, 0x067c}}},\n\t\t/*  3*16^36*G: */\n\t\t{{{0x319888e9, 0x0e73c9e4, 0x2448a8b4, 0x04ae9afc, 0x2681673d, 0x1834c0a5, 0x3a6e2dde, 0x3a9dceb0, 0x1f90}},\n\t\t {{0x2f113b79, 0x1bf7f25f, 0x19522e65, 0x0dd47fb9, 0x2b96a821, 0x054f49c7, 0x2a10e958, 0x0d9f0576, 0x89be}}},\n\t\t/*  5*16^36*G: */\n\t\t{{{0x3562222c, 0x217bedbc, 0x1e6f2c60, 0x00d11e64, 0x0b52bade, 0x00aeb4cd, 0x3e0ad6e7, 0x39537b7f, 0x13a4}},\n\t\t {{0x28200145, 0x32c59a32, 0x1c904c08, 0x3e715deb, 0x209a52d4, 0x2b0be075, 0x2e813b2c, 0x1f539605, 0xc9d6}}},\n\t\t/*  7*16^36*G: */\n\t\t{{{0x343b46bb, 0x0df93703, 0x2c925254, 0x3b4e98fe, 0x055dbd12, 0x01f01761, 0x0aadd1d4, 0x07afc8cf, 0x6199}},\n\t\t {{0x0c20a848, 0x123d6407, 0x12ecd8ef, 0x2a1ca729, 0x3badf11c, 0x3ce1c59b, 0x1e492952, 0x38c23cff, 0x01c5}}},\n\t\t/*  9*16^36*G: */\n\t\t{{{0x121add3b, 0x396f8f77, 0x1727d8f7, 0x26a513d1, 0x1626118b, 0x0e736c34, 0x3d387490, 0x2ba92de1, 0xea27}},\n\t\t {{0x368ce7dd, 0x2d78a476, 0x24e1be71, 0x2c84b5a3, 0x1c2f6278, 0x0f3ac8c9, 0x217de572, 0x3c79b90a, 0xc70f}}},\n\t\t/* 11*16^36*G: */\n\t\t{{{0x211ff757, 0x3a2be2ed, 0x04c226e6, 0x133a5d07, 0x22b6da9b, 0x0043e2db, 0x3fd54ba9, 0x144d5adf, 0x5946}},\n\t\t {{0x094d031a, 0x2299bb2a, 0x3bffe3b2, 0x06ef1edf, 0x0406f996, 0x00e34057, 0x32750042, 0x0d833977, 0x3611}}},\n\t\t/* 13*16^36*G: */\n\t\t{{{0x236160b5, 0x1d89628d, 0x0e7ebc06, 0x314fc91c, 0x091ec0cc, 0x0ebde5c0, 0x33290e84, 0x1b8e457d, 0x16b2}},\n\t\t {{0x18a1dc0e, 0x11897efd, 0x0ba3ef81, 0x0d8eab1c, 0x3654d4e1, 0x190d4918, 0x2ef8bb63, 0x159698c0, 0x060f}}},\n\t\t/* 15*16^36*G: */\n\t\t{{{0x37b32db8, 0x25934a24, 0x247791f3, 0x07b5d27d, 0x2cea85c9, 0x2850f210, 0x19f931be, 0x14a57115, 0x024b}},\n\t\t {{0x2a64f760, 0x25153eaa, 0x05b81a95, 0x2ada0448, 0x1e5be862, 0x38a08731, 0x3309c7b6, 0x3be3d6ff, 0x609f}}}\n\t},\n\t{\n\t\t/*  1*16^37*G: */\n\t\t{{{0x096943e8, 0x3b683d6d, 0x273c5a5d, 0x1bc7f19f, 0x0f06231d, 0x08d2a846, 0x3b840793, 0x20320a02, 0xd68a}},\n\t\t {{0x2b133120, 0x25321099, 0x045295a2, 0x039ee3de, 0x30e28b5b, 0x2c7e45de, 0x186d00c4, 0x2a7ffd2d, 0xdb8b}}},\n\t\t/*  3*16^37*G: */\n\t\t{{{0x0ca1c4f9, 0x16d0aa86, 0x2b7e2823, 0x13bf8d32, 0x1f16f44f, 0x02e0f698, 0x1728c4c4, 0x3de3c8af, 0x7815}},\n\t\t {{0x3778bc15, 0x2ac7a8da, 0x177d1e19, 0x2d0b7985, 0x18c35d5c, 0x24f3cc51, 0x1af6a7dd, 0x007a334e, 0xc1c6}}},\n\t\t/*  5*16^37*G: */\n\t\t{{{0x2e8c8530, 0x349b870f, 0x38f4d8e6, 0x0b7da07b, 0x2a6c6d51, 0x1df19005, 0x040176e3, 0x1cf3683b, 0xc392}},\n\t\t {{0x398446c7, 0x100c3c3d, 0x2eed715c, 0x3b7f2f68, 0x03199850, 0x074e5107, 0x33c8e9d0, 0x2f9095d0, 0x8c41}}},\n\t\t/*  7*16^37*G: */\n\t\t{{{0x237a26c1, 0x07c902ec, 0x0dbf6a53, 0x1b1b9630, 0x103b2516, 0x0890c707, 0x011b0275, 0x1d11fd61, 0xda31}},\n\t\t {{0x2cf74d6f, 0x1460dbb3, 0x3a81525f, 0x1a0db175, 0x19d8b7d3, 0x21059f09, 0x18c69d23, 0x25ee1fd7, 0x753b}}},\n\t\t/*  9*16^37*G: */\n\t\t{{{0x3739dc49, 0x0ad8a2a4, 0x2f55603d, 0x24e4b699, 0x3f231a23, 0x12b1422f, 0x30e6c106, 0x39b2c0ab, 0x6a4b}},\n\t\t {{0x32edd5cf, 0x39a8ae77, 0x14a4a4d3, 0x1f8ad32c, 0x3a8058ab, 0x059b8d83, 0x107597dc, 0x23ea8aa2, 0xf15d}}},\n\t\t/* 11*16^37*G: */\n\t\t{{{0x06987fac, 0x22fa2831, 0x0a86f679, 0x3243e190, 0x098a3c8b, 0x260980fb, 0x27f1344e, 0x31a7c4eb, 0x01f7}},\n\t\t {{0x19174c68, 0x3e479ce0, 0x1f6bc263, 0x1fd77886, 0x1ab6f9cb, 0x040db8ca, 0x1a22de5b, 0x330fcdbf, 0x9d4e}}},\n\t\t/* 13*16^37*G: */\n\t\t{{{0x36daba4d, 0x34ce86f5, 0x03196261, 0x197ec388, 0x3a2bcb9c, 0x018bb763, 0x3d381cb7, 0x25005d87, 0x557e}},\n\t\t {{0x37a52316, 0x04dd286e, 0x243590a5, 0x3a6e3d7e, 0x0cbc86c5, 0x0d73e857, 0x3a7e046d, 0x23ce9807, 0x7a7e}}},\n\t\t/* 15*16^37*G: */\n\t\t{{{0x29f5341a, 0x0e3d4bfc, 0x29636b80, 0x31e8cb19, 0x3101419c, 0x27503a9e, 0x085a93b2, 0x36a08666, 0x3ada}},\n\t\t {{0x2586c6cc, 0x1456024d, 0x05e8fbcb, 0x35b4b96d, 0x2b1017e9, 0x38d6fcda, 0x1369f552, 0x0788a266, 0xbfea}}}\n\t},\n\t{\n\t\t/*  1*16^38*G: */\n\t\t{{{0x028d3d5d, 0x0256603f, 0x3449cea4, 0x04abae5c, 0x3a30b096, 0x3009c241, 0x0804252d, 0x3b5f7d97, 0x324a}},\n\t\t {{0x16ab7c84, 0x19c892be, 0x23328439, 0x084ec31f, 0x2c1f4f19, 0x03030d6b, 0x21f2ff13, 0x0d95dd2d, 0x648a}}},\n\t\t/*  3*16^38*G: */\n\t\t{{{0x2fd53ed3, 0x17245d60, 0x1a56ccef, 0x0fdd3ee7, 0x1f7c4916, 0x3d82e4c7, 0x372ad5b8, 0x02f56659, 0x2084}},\n\t\t {{0x1a7a7132, 0x1c50ff94, 0x0e708998, 0x21f11ce5, 0x3afac254, 0x2f51da9a, 0x18243487, 0x0d25f3b0, 0xf299}}},\n\t\t/*  5*16^38*G: */\n\t\t{{{0x08a35b35, 0x2f4b2ed6, 0x00a121ed, 0x2d762297, 0x08ebfd1a, 0x0f40a796, 0x339bbbd1, 0x2ffd83ac, 0xe6b6}},\n\t\t {{0x1c1007bd, 0x15ca4f6e, 0x3e999c7c, 0x0edb274e, 0x1961ddfe, 0x3d0f8e0d, 0x0d2f3266, 0x3caf4cc0, 0x1a5f}}},\n\t\t/*  7*16^38*G: */\n\t\t{{{0x00360dd3, 0x353be34b, 0x050e2090, 0x2a2a0db6, 0x0ce3bb47, 0x02e021b8, 0x099b288b, 0x05dd16f9, 0xe053}},\n\t\t {{0x3c24f87b, 0x0abb3644, 0x0103dc2b, 0x2e61f7a6, 0x36a01461, 0x02560ad6, 0x12f39cd8, 0x0edc6976, 0xdc1c}}},\n\t\t/*  9*16^38*G: */\n\t\t{{{0x1098dfea, 0x3051998b, 0x2a678797, 0x372cf24b, 0x3a5e57fa, 0x23974aa0, 0x06c59e01, 0x0ece9de2, 0xa815}},\n\t\t {{0x2e6d892f, 0x2926a77d, 0x2daf4158, 0x2d783dd0, 0x053e03b1, 0x236e715e, 0x060fc53d, 0x0e591874, 0x2a47}}},\n\t\t/* 11*16^38*G: */\n\t\t{{{0x0bcecfa5, 0x29f9de92, 0x316bb020, 0x0358b686, 0x0eda3b2a, 0x11a5718e, 0x0addadeb, 0x30ecc3fb, 0x4f05}},\n\t\t {{0x15d37b53, 0x3b34092a, 0x01b48cd2, 0x1fb90c7c, 0x1534b944, 0x18c8d856, 0x1426fadd, 0x267a980f, 0x53a4}}},\n\t\t/* 13*16^38*G: */\n\t\t{{{0x084b96aa, 0x1879d964, 0x22abcce4, 0x0a618d54, 0x3b980ed0, 0x101786a8, 0x3a91be26, 0x26ae67d9, 0xd930}},\n\t\t {{0x02b28a86, 0x09b13cdf, 0x3cfe978f, 0x2db27eeb, 0x34cb5fd3, 0x043c1989, 0x2c557d7e, 0x26caa6d3, 0x6ef9}}},\n\t\t/* 15*16^38*G: */\n\t\t{{{0x1f8fcf0e, 0x3dee3416, 0x3c4a6fac, 0x16dbff79, 0x2a3411d6, 0x30d11b7a, 0x22d35ba9, 0x1f284e15, 0x7d58}},\n\t\t {{0x18bc9459, 0x00706827, 0x323780a5, 0x18e402b4, 0x3d6ad0c4, 0x0d002db3, 0x04c61272, 0x1700e20c, 0xa729}}}\n\t},\n\t{\n\t\t/*  1*16^39*G: */\n\t\t{{{0x3d054c96, 0x3a2f4dcf, 0x0d1ca888, 0x31050eea, 0x3ee5dcee, 0x077f6f97, 0x1e61f6d5, 0x30524673, 0x4df9}},\n\t\t {{0x0ad10d5d, 0x0baeb01b, 0x28849019, 0x3541b370, 0x1d85d4b5, 0x25d308e8, 0x18728050, 0x3b14424b, 0x0035}}},\n\t\t/*  3*16^39*G: */\n\t\t{{{0x1def001d, 0x13c89769, 0x09ba27ef, 0x3e6ef5a6, 0x23b64b21, 0x02f47027, 0x22caf20e, 0x28cb6c9f, 0xa549}},\n\t\t {{0x30624783, 0x3576c69f, 0x2c9705ad, 0x05078a98, 0x259456eb, 0x330c3b62, 0x166cbdf4, 0x1e9e41b6, 0x799b}}},\n\t\t/*  5*16^39*G: */\n\t\t{{{0x052ed4cb, 0x16bbc797, 0x009ec5a0, 0x1537becf, 0x132e6ec9, 0x022f660d, 0x3ecd123f, 0x23cc3681, 0x7e79}},\n\t\t {{0x14bb9462, 0x15c5981e, 0x39f37a12, 0x1cd5c6ff, 0x32f057b1, 0x2a55277b, 0x1ac83041, 0x33312893, 0xd23d}}},\n\t\t/*  7*16^39*G: */\n\t\t{{{0x13630834, 0x37ce83ef, 0x3dac067f, 0x18fc4a18, 0x0c810884, 0x2e7a5aea, 0x14783ad5, 0x28800c54, 0x224f}},\n\t\t {{0x047a2272, 0x34f11cdf, 0x0a50f75c, 0x18a493b0, 0x1d09f53d, 0x2dc3e8e4, 0x2da5c3c4, 0x138caecf, 0xbbe5}}},\n\t\t/*  9*16^39*G: */\n\t\t{{{0x183c19d7, 0x19d92745, 0x02cf57bb, 0x2ed7916b, 0x228ef2bb, 0x28973390, 0x239e4129, 0x28331802, 0xc2d4}},\n\t\t {{0x0507928d, 0x0bca2e0b, 0x3345c977, 0x2012a0c5, 0x01260d26, 0x20ed7dfd, 0x06294d41, 0x283e7020, 0x65ad}}},\n\t\t/* 11*16^39*G: */\n\t\t{{{0x3c940c9a, 0x13202b52, 0x2f423308, 0x33cf384e, 0x0ddc2113, 0x161789d1, 0x1f3190e5, 0x0a9fb0c1, 0x2ec2}},\n\t\t {{0x051e7a4d, 0x34653f66, 0x1a35bdac, 0x101460f6, 0x1c7feb12, 0x3893d40a, 0x379684c2, 0x291a378c, 0x8b1d}}},\n\t\t/* 13*16^39*G: */\n\t\t{{{0x1d683eeb, 0x29c3b97f, 0x08d3133a, 0x0dbace28, 0x04b8f33e, 0x2bd94942, 0x28cecab1, 0x1a5ce3e6, 0xafc6}},\n\t\t {{0x30cd4509, 0x078a72ac, 0x1eddfdc9, 0x02ead549, 0x239c1657, 0x1671ff28, 0x22752bc3, 0x0865db74, 0x002c}}},\n\t\t/* 15*16^39*G: */\n\t\t{{{0x376f4293, 0x28807e1e, 0x13c5139e, 0x3a5e2d59, 0x0b282e10, 0x2f233cdc, 0x03309121, 0x1ed6a7cd, 0xd255}},\n\t\t {{0x1282740a, 0x36c61e89, 0x2405a5f1, 0x12da0e37, 0x0ad21fe3, 0x20bc1bad, 0x027f0126, 0x2cd0d579, 0xa787}}}\n\t},\n\t{\n\t\t/*  1*16^40*G: */\n\t\t{{{0x2c1f98cd, 0x2ff26722, 0x17f0308c, 0x0d224153, 0x06602152, 0x362a7073, 0x34870fae, 0x066a1291, 0x9c39}},\n\t\t {{0x14fc599d, 0x39f9780f, 0x064c8e6b, 0x14c9bddb, 0x20e64190, 0x3c112fc9, 0x1dd57584, 0x13c3d293, 0xddb8}}},\n\t\t/*  3*16^40*G: */\n\t\t{{{0x0fb64db3, 0x1ee6354e, 0x1dd53841, 0x3b79328e, 0x13b8d6a7, 0x2ee0fef9, 0x1ccb740b, 0x08e48a6f, 0xc114}},\n\t\t {{0x3c0259be, 0x08c33a7f, 0x14567d1e, 0x1d602413, 0x178bd1a8, 0x3b3793fa, 0x06fc2a5c, 0x3db716d2, 0x1237}}},\n\t\t/*  5*16^40*G: */\n\t\t{{{0x03081e46, 0x3b7b60d0, 0x14559ea1, 0x14886315, 0x2634713a, 0x3670b064, 0x37224082, 0x12fe0c69, 0x6c5b}},\n\t\t {{0x0bfbcd70, 0x347e72e0, 0x2c22a62e, 0x3433e09a, 0x2be47841, 0x11e18f38, 0x2d42fb23, 0x04dc5249, 0xcb05}}},\n\t\t/*  7*16^40*G: */\n\t\t{{{0x064dcd4b, 0x32b96bb1, 0x111c124d, 0x0c31f566, 0x310a450c, 0x1c19972a, 0x0ade4b56, 0x2a1599c3, 0xe1e9}},\n\t\t {{0x3b041f2c, 0x342d897a, 0x0a16b292, 0x113466ab, 0x2577927f, 0x310d666c, 0x1c531b7a, 0x02a55115, 0x562b}}},\n\t\t/*  9*16^40*G: */\n\t\t{{{0x2badd73c, 0x0161dbf8, 0x2a64b7d0, 0x36737640, 0x1c14208f, 0x29d390bb, 0x1b099778, 0x0695eb44, 0x51b2}},\n\t\t {{0x2b36d8d1, 0x3df52b87, 0x0c734ba6, 0x0804c3ca, 0x2c1cfa6c, 0x281fc074, 0x3d3e5d54, 0x0c040007, 0x0079}}},\n\t\t/* 11*16^40*G: */\n\t\t{{{0x3b09f34b, 0x35d742dc, 0x0cc66ce6, 0x221cf982, 0x339d61e5, 0x2d8a5bcf, 0x0b79861a, 0x3ce98ec7, 0x9701}},\n\t\t {{0x00df5793, 0x33721433, 0x3dcc794a, 0x012f0e5f, 0x16833771, 0x00c6d4c5, 0x30ed15d7, 0x12eee32b, 0x3dd4}}},\n\t\t/* 13*16^40*G: */\n\t\t{{{0x3f1e2f46, 0x1739888e, 0x32778301, 0x1c3dc7a1, 0x163c5752, 0x164b8103, 0x266cc445, 0x2d074b27, 0xa036}},\n\t\t {{0x1effb349, 0x1cc789a5, 0x3f0b1f4f, 0x2038a0b3, 0x1eb08d06, 0x07daa91e, 0x16b3d7df, 0x246800fa, 0xc3bf}}},\n\t\t/* 15*16^40*G: */\n\t\t{{{0x0c4cea08, 0x3362e40e, 0x20ea21db, 0x12d62e83, 0x00465265, 0x298454d0, 0x28c506f4, 0x3eb6ea93, 0x6a85}},\n\t\t {{0x1862f4f3, 0x0677b396, 0x3d721b6a, 0x09c692d0, 0x3e6230b4, 0x24cf0523, 0x0659d531, 0x11812eb9, 0x00b6}}}\n\t},\n\t{\n\t\t/*  1*16^41*G: */\n\t\t{{{0x20a959e5, 0x2884e084, 0x391d4cc5, 0x38524ea2, 0x0e06bb91, 0x017ca076, 0x12fdf8de, 0x05c2c774, 0x6057}},\n\t\t {{0x2385a2a8, 0x2266fa4c, 0x2e24c65e, 0x1454af0f, 0x1df26246, 0x268b6bdc, 0x24807add, 0x3c2c9a9a, 0x9a1a}}},\n\t\t/*  3*16^41*G: */\n\t\t{{{0x171c032b, 0x3536858a, 0x3afdc980, 0x1ad9a285, 0x0766c5ff, 0x046d7f7f, 0x002603dd, 0x2a3f35b8, 0x71eb}},\n\t\t {{0x1668359f, 0x1ead6a38, 0x34b4755e, 0x24c6b45d, 0x0cbb7f71, 0x18145bd5, 0x1d39def6, 0x049892d8, 0xd2ff}}},\n\t\t/*  5*16^41*G: */\n\t\t{{{0x2a03a61c, 0x01b91d14, 0x1070574d, 0x1e1a3d1a, 0x2a9dd050, 0x05d10aea, 0x09d232ca, 0x30c16cc9, 0x855e}},\n\t\t {{0x065dfc07, 0x37f1baab, 0x17e44965, 0x0cbdd3a8, 0x02fb4ed3, 0x0f2ffe6d, 0x01c17f54, 0x174bb17c, 0x0dd8}}},\n\t\t/*  7*16^41*G: */\n\t\t{{{0x1f32d706, 0x00302920, 0x06a0678b, 0x0633291d, 0x15bfa206, 0x034a68c2, 0x3fbf1f15, 0x121aaeac, 0x3ce4}},\n\t\t {{0x3c7fd9e4, 0x02dcd8df, 0x161e89f4, 0x345590f3, 0x094906ed, 0x3f411ac4, 0x3785288e, 0x10236ab8, 0xe775}}},\n\t\t/*  9*16^41*G: */\n\t\t{{{0x391cd3fb, 0x36d032ed, 0x329be686, 0x0a8cff65, 0x0844eb4a, 0x380c863e, 0x237faf02, 0x31450fd3, 0x11cc}},\n\t\t {{0x15160d86, 0x24dc5ae9, 0x0dd3472a, 0x02c7bf4b, 0x0cc239fa, 0x2389124e, 0x311deb52, 0x1acaa40a, 0x4aa5}}},\n\t\t/* 11*16^41*G: */\n\t\t{{{0x218f7552, 0x21ee4465, 0x0054fac3, 0x1044e2e6, 0x2382ddbd, 0x25ddd3e0, 0x09c6f43b, 0x2ec5f945, 0x0250}},\n\t\t {{0x3510b14d, 0x3c212588, 0x33d6f1e3, 0x001bcf0c, 0x29d817da, 0x35f7dd7f, 0x28082342, 0x0c3f26ef, 0x7319}}},\n\t\t/* 13*16^41*G: */\n\t\t{{{0x1f725d12, 0x1744fa4e, 0x0b5f4750, 0x1190aef7, 0x022fbfd9, 0x28e73828, 0x27fd3ab4, 0x27222cd1, 0x1a74}},\n\t\t {{0x23ac56e4, 0x04d94534, 0x190daa70, 0x1c821a62, 0x2f3d8f60, 0x22f9d70a, 0x00e2cf45, 0x34655cfb, 0x7e91}}},\n\t\t/* 15*16^41*G: */\n\t\t{{{0x29fae458, 0x18412394, 0x26ec97fd, 0x0297109d, 0x3b7b328b, 0x3455a977, 0x0218c109, 0x1a16f83e, 0xc750}},\n\t\t {{0x1757b598, 0x005a1065, 0x35951a2b, 0x1772940c, 0x32c7b40a, 0x0bd05319, 0x21e05fb5, 0x257e33e4, 0xead7}}}\n\t},\n\t{\n\t\t/*  1*16^42*G: */\n\t\t{{{0x2cb94266, 0x069a5cfb, 0x3d4df12b, 0x33bc3ee9, 0x0da31880, 0x10e69146, 0x08411421, 0x37e388e8, 0xa576}},\n\t\t {{0x21b28ec8, 0x3a2f846b, 0x114d9f3e, 0x0b8429fd, 0x0cd82c43, 0x2e5ebf96, 0x240b2c92, 0x2fc839d9, 0x40a6}}},\n\t\t/*  3*16^42*G: */\n\t\t{{{0x0d9ed6c1, 0x1a2bad63, 0x3d593d6b, 0x139d16f0, 0x1edd0ec2, 0x3f061dc1, 0x0f53e80b, 0x0cdb72dd, 0x0328}},\n\t\t {{0x38fafeee, 0x3b1baf9b, 0x1cb494ad, 0x16fd37c9, 0x0d7c8c26, 0x35650e88, 0x19f28c46, 0x260e04bf, 0x71a8}}},\n\t\t/*  5*16^42*G: */\n\t\t{{{0x3235983a, 0x066a6a34, 0x13bceb29, 0x22840dc0, 0x3e1531e3, 0x0e49b5c3, 0x11c54dc6, 0x13aba2e4, 0xce4f}},\n\t\t {{0x0d3cdecf, 0x33f5ac64, 0x2bf740ae, 0x1b1948a3, 0x30754352, 0x37809279, 0x0fbbb3ea, 0x3e5cf0e4, 0xf3c9}}},\n\t\t/*  7*16^42*G: */\n\t\t{{{0x15b0e6c9, 0x1b6aad99, 0x06e4c89a, 0x17fe73de, 0x38bcbddb, 0x0a3ecdb7, 0x0622278e, 0x2fe952e6, 0x4dbe}},\n\t\t {{0x1eb2cc25, 0x2529e155, 0x0504efae, 0x24c46caf, 0x2229f358, 0x2989b9b8, 0x13aedf45, 0x39ec0f24, 0x10fe}}},\n\t\t/*  9*16^42*G: */\n\t\t{{{0x25857295, 0x13806846, 0x3433f016, 0x32391fc0, 0x1ca12069, 0x38463f28, 0x05c218b2, 0x0902ffbd, 0xa42a}},\n\t\t {{0x0a7eb9c1, 0x1acddffb, 0x15193955, 0x28708b34, 0x1da4c427, 0x1ac8ac93, 0x05d4567a, 0x2cfc9840, 0x3aa0}}},\n\t\t/* 11*16^42*G: */\n\t\t{{{0x2fcdc098, 0x0883fd55, 0x2e468032, 0x02b803da, 0x0499c155, 0x3c7e1b03, 0x322267a7, 0x0acbe5be, 0x34e1}},\n\t\t {{0x2a7474e2, 0x132c6b79, 0x19883f66, 0x37d44c3c, 0x3972db04, 0x132f2105, 0x1d322d97, 0x30b775ed, 0xa64a}}},\n\t\t/* 13*16^42*G: */\n\t\t{{{0x0f173b92, 0x335bad7a, 0x29fb7611, 0x1f9cbd05, 0x0d65683b, 0x0c68863d, 0x391f29be, 0x3490366e, 0x10f4}},\n\t\t {{0x233146c2, 0x240801b5, 0x086adb7c, 0x2edda745, 0x3908ba90, 0x2c96968c, 0x353ad211, 0x0b654245, 0x850e}}},\n\t\t/* 15*16^42*G: */\n\t\t{{{0x28d84958, 0x39bf4766, 0x0acc5cae, 0x0477ac5b, 0x00cc866a, 0x066e5db5, 0x277e749f, 0x3a02da6d, 0xe846}},\n\t\t {{0x3882cf9f, 0x031191ed, 0x1e0c1a64, 0x1468cd9c, 0x18b76fad, 0x2f64411e, 0x07e2541d, 0x2e3f2253, 0xa29c}}}\n\t},\n\t{\n\t\t/*  1*16^43*G: */\n\t\t{{{0x3e58ad71, 0x3dd8e226, 0x39a3a208, 0x0c347d73, 0x1e8c38bb, 0x17fa58a7, 0x2c3e30a0, 0x29e30a37, 0x7778}},\n\t\t {{0x3d9f43ac, 0x2d44ff07, 0x324ac563, 0x2ce1047f, 0x3f580087, 0x26384bcb, 0x1b22ff70, 0x1b66ad69, 0x3462}}},\n\t\t/*  3*16^43*G: */\n\t\t{{{0x3319c869, 0x3df1bab8, 0x21eb2702, 0x2a7e575d, 0x0cacdc18, 0x20e408bf, 0x33fc8d01, 0x01176605, 0x3018}},\n\t\t {{0x12b856f0, 0x3031db27, 0x23d9a7bf, 0x0aa13292, 0x222e3bca, 0x1890c835, 0x3b7b6f86, 0x315e0940, 0xac5f}}},\n\t\t/*  5*16^43*G: */\n\t\t{{{0x25ed29b5, 0x319a61be, 0x12add1b4, 0x20c2d81c, 0x23c885f5, 0x2d9f6e69, 0x17ef343a, 0x206d87b9, 0x3228}},\n\t\t {{0x3cd15ad2, 0x3d3c49b9, 0x0ee7604e, 0x20ebaae5, 0x1531e1ca, 0x02c677d0, 0x0344eb11, 0x00a105e8, 0x1677}}},\n\t\t/*  7*16^43*G: */\n\t\t{{{0x06c96100, 0x2fea101e, 0x2e9c8e63, 0x18c046a9, 0x33dbcca1, 0x0f766cb7, 0x31b9ffb4, 0x11ceb03e, 0x3f38}},\n\t\t {{0x32624707, 0x078ab06f, 0x375f1bcf, 0x15c71f02, 0x079ce566, 0x131118bc, 0x00395253, 0x27157d75, 0x70c6}}},\n\t\t/*  9*16^43*G: */\n\t\t{{{0x3d22d2ac, 0x0d31bb1b, 0x1caace02, 0x377f849b, 0x05df2f10, 0x0f03825e, 0x3a76dcb4, 0x04f17f49, 0x2881}},\n\t\t {{0x0f42a268, 0x207ad57e, 0x148c8fd0, 0x30f51285, 0x176137dd, 0x1ddc9832, 0x3c5c8f20, 0x3ac0563e, 0xa1a7}}},\n\t\t/* 11*16^43*G: */\n\t\t{{{0x245f8ea8, 0x12ea0374, 0x24d2900d, 0x1c9238e5, 0x119fe5d1, 0x3d36575c, 0x23a2a553, 0x28803211, 0xf963}},\n\t\t {{0x19bc99eb, 0x2f157ec1, 0x18b60824, 0x2e3c8d67, 0x3427208b, 0x1c88c07f, 0x383c0a3b, 0x2509a31f, 0x9c85}}},\n\t\t/* 13*16^43*G: */\n\t\t{{{0x2606a315, 0x386a20c4, 0x26963ad9, 0x1c981cbc, 0x0e097e40, 0x362ca964, 0x0d9a7f98, 0x08933fdc, 0xa5d9}},\n\t\t {{0x1e3b68d1, 0x0d584cd6, 0x111a7c9d, 0x13434d1f, 0x180de9ed, 0x0c1aaf5e, 0x0da5b343, 0x22c00ec8, 0x8732}}},\n\t\t/* 15*16^43*G: */\n\t\t{{{0x06231493, 0x336ded50, 0x0cc4d469, 0x1046a0c3, 0x25e6a496, 0x13907403, 0x3c3604eb, 0x260b86dc, 0xf1fe}},\n\t\t {{0x358848c1, 0x25aa6699, 0x25ff0d01, 0x1cfecd1b, 0x3d99d3f1, 0x34f0817d, 0x24ddc216, 0x067abb66, 0x2e20}}}\n\t},\n\t{\n\t\t/*  1*16^44*G: */\n\t\t{{{0x06d903ac, 0x027b6a70, 0x1ad7e5cb, 0x3e589d39, 0x3afd2ed5, 0x0a7f4c39, 0x3a844637, 0x2557b98d, 0x0928}},\n\t\t {{0x1bcd091f, 0x14603a4d, 0x0a8d83fc, 0x0f49bbea, 0x3a95eeac, 0x1e284c24, 0x342a827b, 0x08400f4f, 0xc256}}},\n\t\t/*  3*16^44*G: */\n\t\t{{{0x3874b839, 0x0444a1d5, 0x13d2b418, 0x10456ce5, 0x30b6aebe, 0x37c37ec8, 0x1e5a8053, 0x2e07f038, 0x3e03}},\n\t\t {{0x3c0594ba, 0x03073959, 0x1ab5b8da, 0x39717c3f, 0x198f667d, 0x3d981d5c, 0x07f42c44, 0x3858f7fc, 0xd13a}}},\n\t\t/*  5*16^44*G: */\n\t\t{{{0x0357a513, 0x28fde39a, 0x1b3023f3, 0x146f44d1, 0x2922c5f1, 0x3e8a0ea8, 0x0492cd62, 0x302de8bd, 0xe662}},\n\t\t {{0x2017d07e, 0x24a88072, 0x1538d891, 0x00d73589, 0x21a419d8, 0x2b882284, 0x2452305d, 0x064f3984, 0xab0b}}},\n\t\t/*  7*16^44*G: */\n\t\t{{{0x1f37d242, 0x2657dfbf, 0x39c14b04, 0x27fb2981, 0x23587dc2, 0x218b1f2f, 0x0f6cb843, 0x202c7253, 0x40bf}},\n\t\t {{0x26405088, 0x347609e6, 0x2bd35583, 0x0c87ae90, 0x26fe1274, 0x0ffa6c6c, 0x2aaf04f5, 0x374d7615, 0xb579}}},\n\t\t/*  9*16^44*G: */\n\t\t{{{0x195a3558, 0x2bcacd91, 0x234a7f2b, 0x01c7e178, 0x1b59f6ac, 0x3e5e04e3, 0x1ca70806, 0x3fa5d807, 0x3d14}},\n\t\t {{0x2443df4c, 0x1ab6ceb1, 0x3c1d727c, 0x3828b851, 0x356e1482, 0x26a4c76f, 0x281ef8f2, 0x2f75ba11, 0x16c6}}},\n\t\t/* 11*16^44*G: */\n\t\t{{{0x02b1fc24, 0x37a7d6b6, 0x23f7570e, 0x0a36071f, 0x12486525, 0x06b134b2, 0x265251cc, 0x29503a0b, 0xdd6f}},\n\t\t {{0x0e9b74ca, 0x290c7118, 0x17322304, 0x04379afb, 0x257e77ec, 0x1bc7afc5, 0x3186fe36, 0x0adfac74, 0x67e6}}},\n\t\t/* 13*16^44*G: */\n\t\t{{{0x3dd08e02, 0x07aa4564, 0x1adf0288, 0x2151edff, 0x3d1e8010, 0x1a5266a8, 0x15d780f8, 0x0b6a0b79, 0x13fa}},\n\t\t {{0x3cb03410, 0x29550770, 0x1a42b97d, 0x112beec6, 0x3432c7e6, 0x0d5881ae, 0x1da72313, 0x0e2c1155, 0x1363}}},\n\t\t/* 15*16^44*G: */\n\t\t{{{0x144ee41a, 0x308ceae6, 0x37d69a6a, 0x26d5b74e, 0x06828287, 0x3042d9cb, 0x30a443f7, 0x121474f1, 0xd06c}},\n\t\t {{0x0b295e6f, 0x3c7e13a6, 0x162ee252, 0x1ee10d18, 0x3630919b, 0x02b353d3, 0x0d0adbbb, 0x3f530161, 0x5815}}}\n\t},\n\t{\n\t\t/*  1*16^45*G: */\n\t\t{{{0x23d82751, 0x1eab9d45, 0x3ad35452, 0x116d2a41, 0x23b28556, 0x0193ce83, 0x1b109399, 0x3fbcfb1b, 0x85d0}},\n\t\t {{0x0eb1f962, 0x0b08de89, 0x07733158, 0x21d47a5a, 0x2cf5663e, 0x3525b960, 0x38c0be29, 0x192104e8, 0x1f03}}},\n\t\t/*  3*16^45*G: */\n\t\t{{{0x2cde4cf3, 0x26554187, 0x38a066ab, 0x10394d51, 0x1d9ae793, 0x30b49b45, 0x022c3be7, 0x2ad2b045, 0x384d}},\n\t\t {{0x252d0566, 0x1f1e5ac8, 0x351ba73b, 0x10c28ce5, 0x34c6f01f, 0x13b5b68a, 0x1ca43bfb, 0x316f346e, 0xd6e3}}},\n\t\t/*  5*16^45*G: */\n\t\t{{{0x1e5238c2, 0x22bcfa48, 0x00ecb8b9, 0x0d57d70e, 0x02ed4840, 0x05842d3a, 0x015aa41b, 0x3b03adf5, 0x14f0}},\n\t\t {{0x12f07922, 0x3a1a8d1e, 0x304939d6, 0x17003600, 0x02747fd2, 0x3f1cf8e1, 0x35d80921, 0x354f7520, 0xab12}}},\n\t\t/*  7*16^45*G: */\n\t\t{{{0x1543e94d, 0x3d8d4bbf, 0x2f98e188, 0x04c0a9d5, 0x1a0ddadd, 0x30d19e29, 0x0287ec41, 0x3ceede0b, 0xeb42}},\n\t\t {{0x05924d89, 0x01567791, 0x20d6d424, 0x3611a379, 0x0dfb774c, 0x03755cbf, 0x1d92dc9a, 0x1b41d3c9, 0x234a}}},\n\t\t/*  9*16^45*G: */\n\t\t{{{0x3e19aaed, 0x0c9396d5, 0x06673270, 0x26eb37a3, 0x06a92045, 0x3b00bdb8, 0x020d9a9e, 0x0e32945a, 0x1cf1}},\n\t\t {{0x292f400e, 0x04dba975, 0x3c77ffbc, 0x27bbe3fb, 0x2dde1747, 0x0dca99ad, 0x063865f4, 0x36bcc5c7, 0xd6ff}}},\n\t\t/* 11*16^45*G: */\n\t\t{{{0x36a8aa39, 0x3db03a7e, 0x278fac55, 0x2998ded2, 0x1990d937, 0x16825a12, 0x0d412c87, 0x21af97d0, 0xb586}},\n\t\t {{0x2b493c1f, 0x3f1e4d74, 0x2db347b8, 0x2f6be639, 0x00a91dab, 0x11e35153, 0x38c2c149, 0x3550c931, 0x5632}}},\n\t\t/* 13*16^45*G: */\n\t\t{{{0x303b4cc5, 0x3a47af8e, 0x21c77c2e, 0x0a0c6e96, 0x33a80257, 0x16f13f9f, 0x3cc2b67b, 0x276c1ae2, 0x5fc1}},\n\t\t {{0x25b57c28, 0x0ece7ee1, 0x0087ec4a, 0x1dbd40f3, 0x3a5ef492, 0x084e3e68, 0x0c7c66ee, 0x21303b26, 0xec8e}}},\n\t\t/* 15*16^45*G: */\n\t\t{{{0x0cb38cb5, 0x2d2e15f5, 0x1388948b, 0x02dff7d3, 0x3eea1be1, 0x2a2903f4, 0x1e289deb, 0x2dc350bb, 0xb88f}},\n\t\t {{0x1965f3d7, 0x1efe9d59, 0x3af8c719, 0x13cf8489, 0x35a8e24d, 0x12ee652c, 0x23280603, 0x0dab51ba, 0xd6c7}}}\n\t},\n\t{\n\t\t/*  1*16^46*G: */\n\t\t{{{0x0526087e, 0x3d501209, 0x2da20308, 0x3edb6220, 0x18b85dfd, 0x26d8105e, 0x2ce97c1c, 0x0373a5fb, 0xff2b}},\n\t\t {{0x30c29907, 0x32547807, 0x10e2ceb2, 0x2dfb5bee, 0x107936c7, 0x13137153, 0x0ba188af, 0x04ffbd49, 0x493d}}},\n\t\t/*  3*16^46*G: */\n\t\t{{{0x39d681f9, 0x164153f9, 0x08feb9fc, 0x3383bbeb, 0x2c94b066, 0x1ffc9780, 0x3230888b, 0x3f7c9dd7, 0xc745}},\n\t\t {{0x3bbb1247, 0x00c5cd0d, 0x27d45c76, 0x36f4cd71, 0x2818678c, 0x04e531c3, 0x1e5e78a7, 0x08bcbdae, 0x5902}}},\n\t\t/*  5*16^46*G: */\n\t\t{{{0x35cd0ea3, 0x38133bb4, 0x0cac4815, 0x111e3a08, 0x32e7f2b3, 0x16797ad9, 0x1050b27a, 0x1e7cea5d, 0xabb2}},\n\t\t {{0x3c307bce, 0x1c24c4cd, 0x202f3b64, 0x25da4167, 0x078ed47c, 0x12f8300c, 0x3970d9fb, 0x040eefc5, 0x5dee}}},\n\t\t/*  7*16^46*G: */\n\t\t{{{0x1bc9ee3e, 0x30b8bcfc, 0x3e7382c5, 0x27e86a58, 0x27ed11ea, 0x2baa9d09, 0x0682827f, 0x0542d67f, 0x3f81}},\n\t\t {{0x199aae06, 0x33ab6c31, 0x0da81603, 0x08ecb73f, 0x39566276, 0x06facf11, 0x3a82d467, 0x229a3f6f, 0x19c8}}},\n\t\t/*  9*16^46*G: */\n\t\t{{{0x38e4a007, 0x05c6fbeb, 0x0bb358b6, 0x3b3bb3c2, 0x16c7ec15, 0x12e8cea9, 0x02de6959, 0x04cb7402, 0x5cf8}},\n\t\t {{0x1068b883, 0x398fc242, 0x39c7fe8c, 0x251be5b1, 0x0c3df6c8, 0x35056212, 0x1fa0df4a, 0x3b970358, 0xb45a}}},\n\t\t/* 11*16^46*G: */\n\t\t{{{0x26c2d4a7, 0x255bf9ec, 0x3cfffb10, 0x30dbe4ce, 0x004ed21b, 0x38ce5cf1, 0x3a494653, 0x3f934352, 0xb6d5}},\n\t\t {{0x3ae86371, 0x063739f8, 0x35e3cc81, 0x16df939b, 0x3ffd8e74, 0x33e48277, 0x3d6c14df, 0x1ce84eae, 0x47f3}}},\n\t\t/* 13*16^46*G: */\n\t\t{{{0x3c66dd33, 0x024cd88b, 0x1dc76dc5, 0x23ef23fc, 0x29b022ea, 0x2c6c5400, 0x3588706b, 0x2ef019b3, 0x61c8}},\n\t\t {{0x36f10bfa, 0x0eeea7ce, 0x2820c8ca, 0x1441bab0, 0x05d3fb6a, 0x1a6652e6, 0x0f703446, 0x2788e795, 0x9359}}},\n\t\t/* 15*16^46*G: */\n\t\t{{{0x1d6b2ff8, 0x2016df33, 0x286c8fa9, 0x18cdb05c, 0x03bdf187, 0x27d4dcfb, 0x2785187c, 0x0ae95d09, 0x94e3}},\n\t\t {{0x2ce1af3e, 0x37521554, 0x26bfe13a, 0x0ebc1094, 0x2d9e8cb3, 0x07922198, 0x204e192f, 0x1122d0f6, 0x0d1b}}}\n\t},\n\t{\n\t\t/*  1*16^47*G: */\n\t\t{{{0x3856e241, 0x203978b3, 0x0d6dd287, 0x3c7b8523, 0x1b212b57, 0x0acb98c0, 0x080ea9ed, 0x2ef92c7a, 0x827f}},\n\t\t {{0x2ec293ec, 0x1816da2e, 0x2903166d, 0x3de98c61, 0x1d12687f, 0x3bcb19f4, 0x27b0b71b, 0x27248f1c, 0xc60f}}},\n\t\t/*  3*16^47*G: */\n\t\t{{{0x3bb80fa7, 0x0d12172c, 0x30413886, 0x29f69aed, 0x20819f3a, 0x0681af4c, 0x0c2fbc0d, 0x38c7d8c2, 0x0857}},\n\t\t {{0x09366b2d, 0x3660847c, 0x0d7016ab, 0x0b8dc10f, 0x0b714717, 0x1f327477, 0x0172092d, 0x24d08eb8, 0xf643}}},\n\t\t/*  5*16^47*G: */\n\t\t{{{0x09c70e63, 0x1740b0e8, 0x353d496f, 0x2ee2de39, 0x0a672e9c, 0x171955d9, 0x16004354, 0x333a95af, 0x28aa}},\n\t\t {{0x3057da4e, 0x27c0e20b, 0x04da1e8b, 0x3f167391, 0x28ebb7f5, 0x22599f1d, 0x20e1567a, 0x0c8bbe06, 0x2b69}}},\n\t\t/*  7*16^47*G: */\n\t\t{{{0x33e674b5, 0x007714bd, 0x3060aac6, 0x363da739, 0x2b8a4f92, 0x36cb26f3, 0x1a66145d, 0x2d896815, 0xa2f3}},\n\t\t {{0x0e937941, 0x024e3238, 0x033fa53b, 0x08be8c5f, 0x2a7c4b92, 0x112a43cc, 0x068ae800, 0x28565853, 0x620e}}},\n\t\t/*  9*16^47*G: */\n\t\t{{{0x191eb056, 0x1d8058c7, 0x2cfd386c, 0x00bbf6e3, 0x3515f5a0, 0x22d71a8f, 0x259231d9, 0x20f27aab, 0x3c4f}},\n\t\t {{0x205cecab, 0x109624f6, 0x1cf6b877, 0x20ad5120, 0x32788019, 0x3595cf0e, 0x28b6a33a, 0x2401d452, 0x9447}}},\n\t\t/* 11*16^47*G: */\n\t\t{{{0x3d86dfa9, 0x24187f6e, 0x1b993a71, 0x0e2d2902, 0x103baadc, 0x30780fa0, 0x167d4e29, 0x384a22a6, 0xaff8}},\n\t\t {{0x01d12681, 0x1c40f0db, 0x019f9c70, 0x045b6a51, 0x0f53f4f9, 0x0faea87f, 0x37c3fd3d, 0x12ecc84d, 0x8d8b}}},\n\t\t/* 13*16^47*G: */\n\t\t{{{0x189ba9c1, 0x23c9cdae, 0x09d338e2, 0x03df2968, 0x0ee579e4, 0x16098abb, 0x000b3e84, 0x1e114a37, 0xd3fb}},\n\t\t {{0x2b51b267, 0x186e237f, 0x011ade00, 0x073b7570, 0x370fe634, 0x32815d62, 0x2b4e7ca7, 0x350d3be9, 0xf894}}},\n\t\t/* 15*16^47*G: */\n\t\t{{{0x0f2bb909, 0x36a5b074, 0x3598d999, 0x24409f14, 0x187d7f63, 0x1ca620e4, 0x1aa88ff4, 0x0c0382b2, 0x4ec9}},\n\t\t {{0x24cf4071, 0x2228e0fe, 0x1ac3827b, 0x0b85a083, 0x0c49bad5, 0x03711461, 0x304dc5c8, 0x2841af86, 0x782b}}}\n\t},\n\t{\n\t\t/*  1*16^48*G: */\n\t\t{{{0x2120e2b3, 0x3ced63e8, 0x347f9aa7, 0x163f739f, 0x26e5217a, 0x392b8d33, 0x1bdbae7b, 0x127c87d4, 0xeaa6}},\n\t\t {{0x3a5ad93d, 0x11e94c16, 0x13f7e59d, 0x29ae597c, 0x39aa5a01, 0x2a03e261, 0x3b03ac69, 0x1e7b56ee, 0xbe32}}},\n\t\t/*  3*16^48*G: */\n\t\t{{{0x3f2e070d, 0x160ff4e8, 0x12a6a98f, 0x2aadc731, 0x1047e229, 0x1cc70ee1, 0x34abff48, 0x297a410b, 0x4b72}},\n\t\t {{0x296dd780, 0x112ea0bb, 0x2948c3de, 0x2d197774, 0x0f3c10b0, 0x1deecdb4, 0x2e1cf602, 0x0753875a, 0x599e}}},\n\t\t/*  5*16^48*G: */\n\t\t{{{0x0a02591c, 0x2739ff61, 0x05125a1e, 0x3d526596, 0x21fd613e, 0x1afefad7, 0x1c8e285a, 0x24ff194e, 0xa9fc}},\n\t\t {{0x29bec2dc, 0x242b77bd, 0x3cf72537, 0x22231057, 0x1165e5ca, 0x1305e86a, 0x387173e8, 0x39ce7714, 0x9c2c}}},\n\t\t/*  7*16^48*G: */\n\t\t{{{0x2d968b59, 0x0401b838, 0x3cbbc2e1, 0x28a2eb84, 0x1b027709, 0x35eb0482, 0x39f0a6a7, 0x005f069b, 0xc940}},\n\t\t {{0x0de572fb, 0x3bf5d902, 0x390c9c8f, 0x210b2d90, 0x35742ce2, 0x2286fe96, 0x3862013b, 0x08940326, 0x39d9}}},\n\t\t/*  9*16^48*G: */\n\t\t{{{0x326b3332, 0x0a1cccd5, 0x3ee5de6a, 0x00e2341c, 0x0bf8e031, 0x1e4e97dc, 0x10024ec6, 0x2ee75fbb, 0x1f84}},\n\t\t {{0x14e8d52e, 0x1510a28c, 0x36dc3a25, 0x2f338b50, 0x39edf0c2, 0x1f09fdd6, 0x29ecc254, 0x1b41caf2, 0xee72}}},\n\t\t/* 11*16^48*G: */\n\t\t{{{0x0defa98e, 0x336a952b, 0x1ac27995, 0x12111a04, 0x11e9c772, 0x2055ece6, 0x1fcd06ca, 0x38224251, 0x0f13}},\n\t\t {{0x3e286767, 0x0229dda6, 0x2ceaccdc, 0x1f9c1785, 0x3362db28, 0x0fe2c29e, 0x27c5035e, 0x087c5d93, 0xadd5}}},\n\t\t/* 13*16^48*G: */\n\t\t{{{0x29f59b6b, 0x178700ef, 0x1888e2fa, 0x2ce318f0, 0x1826d3e9, 0x0a2874b5, 0x1ec7db37, 0x24695477, 0xdde1}},\n\t\t {{0x26cb1410, 0x1ab658a4, 0x3154fecf, 0x15ce2ef9, 0x12e14e8b, 0x1d5f5871, 0x275cbe0a, 0x3ede00a0, 0x5b2b}}},\n\t\t/* 15*16^48*G: */\n\t\t{{{0x09c6b699, 0x1a3157f7, 0x3e46871b, 0x1bd5cd5a, 0x341682a8, 0x1b5efe5e, 0x36f7a5a1, 0x004bbb60, 0x5fab}},\n\t\t {{0x01c6c3aa, 0x05cc854b, 0x2883519b, 0x2ac45ffa, 0x162f7b90, 0x2ed044c3, 0x3d144e9e, 0x3e9c28f0, 0x2d9b}}}\n\t},\n\t{\n\t\t/*  1*16^49*G: */\n\t\t{{{0x1a34d24f, 0x388d8cb7, 0x1a137401, 0x2db63c32, 0x342ee541, 0x077db7b3, 0x3169d939, 0x0b50f173, 0xe4a4}},\n\t\t {{0x1eba9414, 0x29fdc4c7, 0x0d8e4f13, 0x21bbb7ea, 0x0ad34ce8, 0x326733ee, 0x1c73526f, 0x24b9c5b4, 0x4d9f}}},\n\t\t/*  3*16^49*G: */\n\t\t{{{0x3bea0c68, 0x321042bc, 0x37b392b5, 0x10c048d9, 0x396faf09, 0x26f23a34, 0x2a3a2494, 0x258d3855, 0x3e41}},\n\t\t {{0x1a45edb6, 0x32edbfdc, 0x03cda1ab, 0x2846518c, 0x0693062f, 0x0f2ff8dc, 0x321f7f37, 0x31676492, 0x0123}}},\n\t\t/*  5*16^49*G: */\n\t\t{{{0x139824d7, 0x3dd748f2, 0x11c9897a, 0x2ded930d, 0x3f0b576e, 0x128f98bd, 0x17508eed, 0x0e3d5157, 0x8d94}},\n\t\t {{0x1366489f, 0x28013d22, 0x26b063d8, 0x2e78ae0c, 0x36ef6f8f, 0x182f4c6a, 0x26c2a2ca, 0x381cd3fb, 0x3261}}},\n\t\t/*  7*16^49*G: */\n\t\t{{{0x18d713de, 0x39201c6a, 0x028e6208, 0x1830bedd, 0x25454393, 0x2a44a8bf, 0x254420d4, 0x0931563b, 0xb725}},\n\t\t {{0x1b8350e9, 0x1bff9496, 0x04a5fcb7, 0x20b49bf9, 0x16941504, 0x0b460ba7, 0x03e45104, 0x2ce6a28a, 0x4c51}}},\n\t\t/*  9*16^49*G: */\n\t\t{{{0x3e3b2cb4, 0x331b0a4f, 0x37210402, 0x127cd6fc, 0x21149e30, 0x31db8e04, 0x112519ad, 0x17d6885b, 0x3de4}},\n\t\t {{0x307eb02f, 0x1878ceb0, 0x287044cf, 0x0f8a3996, 0x3c910682, 0x022a92a5, 0x2addc50e, 0x21661017, 0xba2a}}},\n\t\t/* 11*16^49*G: */\n\t\t{{{0x2ce4e5bf, 0x08d1d9bd, 0x09005b17, 0x19f2a1a8, 0x0906ae9b, 0x0ff38dd2, 0x1be87c1e, 0x3c71a256, 0x8511}},\n\t\t {{0x01789c08, 0x3f24a513, 0x05365262, 0x2a1e226f, 0x2a00232d, 0x377dfb1a, 0x0d4874c1, 0x3d73e46f, 0xecdf}}},\n\t\t/* 13*16^49*G: */\n\t\t{{{0x3d3258ab, 0x06d59a28, 0x2bc14dc3, 0x3490a062, 0x14ab5957, 0x2871cbb8, 0x360222cf, 0x014ba073, 0x8c5a}},\n\t\t {{0x022d0f8f, 0x15f8214c, 0x0d944ade, 0x36ba3e70, 0x0c08c246, 0x2a031e41, 0x3bda1079, 0x36d2ed10, 0x6811}}},\n\t\t/* 15*16^49*G: */\n\t\t{{{0x3f91bcee, 0x1630a82a, 0x20c0d841, 0x33c763c7, 0x2bf137f5, 0x18f3b155, 0x13560bdc, 0x3e05b7af, 0xcef7}},\n\t\t {{0x01966b33, 0x2ed36a7e, 0x172f6ac6, 0x0f92c0a8, 0x1d245fa6, 0x0ecce700, 0x08701246, 0x1320d8dd, 0x67e7}}}\n\t},\n\t{\n\t\t/*  1*16^50*G: */\n\t\t{{{0x0300bf19, 0x1c5cee75, 0x08fea494, 0x2d4d5daa, 0x352b6b92, 0x183eb6ac, 0x0bdd9541, 0x03fbcd83, 0x1ec8}},\n\t\t {{0x0107cefd, 0x1c737073, 0x295a07b6, 0x11b9dfd8, 0x2bbf5e01, 0x2925629e, 0x1340d2f3, 0x3a4dd5ad, 0xaeef}}},\n\t\t/*  3*16^50*G: */\n\t\t{{{0x12fea1f9, 0x2c5f2ef1, 0x00452b94, 0x3fc2d423, 0x106531c4, 0x3f76ad9c, 0x1f2e83bc, 0x22029574, 0xa6dc}},\n\t\t {{0x3bc345e9, 0x2c705391, 0x268f7e63, 0x1ee276df, 0x2cbc5005, 0x1a0e845a, 0x367c3038, 0x2a151f70, 0x7ef1}}},\n\t\t/*  5*16^50*G: */\n\t\t{{{0x06d6c9b3, 0x235030fc, 0x0865637c, 0x1b133a1d, 0x2481ba8c, 0x308a71e2, 0x245992bd, 0x2a4ffa90, 0xfe6b}},\n\t\t {{0x2948bdfb, 0x30b1e23e, 0x1c2e9b00, 0x203c6fc1, 0x013b56d9, 0x2d06cd15, 0x39872b6b, 0x0635d014, 0x7ee9}}},\n\t\t/*  7*16^50*G: */\n\t\t{{{0x0cf95151, 0x08bc41cc, 0x02c4b644, 0x19201b91, 0x08ded1b9, 0x03230b70, 0x098bfb02, 0x38bc51bf, 0x15d5}},\n\t\t {{0x2ff8ecf2, 0x20a81f30, 0x1d8c0f94, 0x0813ee5f, 0x1023f9bb, 0x038425e2, 0x3d4ec7f9, 0x0b8c6457, 0xa5b7}}},\n\t\t/*  9*16^50*G: */\n\t\t{{{0x296a5658, 0x35e042e4, 0x1ef65643, 0x052c9490, 0x2e29be38, 0x1f80249e, 0x0447ad8c, 0x3a1c95a2, 0x84c0}},\n\t\t {{0x181b80d1, 0x3659ca6f, 0x34f1fd22, 0x2986a607, 0x13725ed3, 0x1f8c6419, 0x022c4a08, 0x20e03058, 0x2659}}},\n\t\t/* 11*16^50*G: */\n\t\t{{{0x14dc6a0f, 0x1d6ed722, 0x2fe15753, 0x10d06450, 0x0077c274, 0x09939e8b, 0x3731d565, 0x2c71c6a4, 0xfed6}},\n\t\t {{0x176fc7e0, 0x32e35cb6, 0x23fc409c, 0x1d3564c2, 0x13ae2313, 0x24606b93, 0x3ff0a847, 0x2af9ac3f, 0x8de2}}},\n\t\t/* 13*16^50*G: */\n\t\t{{{0x18e29355, 0x2ce217c4, 0x1720d86d, 0x0723a4ce, 0x23b9d82f, 0x3be18100, 0x3cbc70fc, 0x137664b4, 0x2a6a}},\n\t\t {{0x35cc2872, 0x014f803e, 0x0c4c76c0, 0x24168e99, 0x28f90dfe, 0x3f720789, 0x27e0c760, 0x37ee9f12, 0x8677}}},\n\t\t/* 15*16^50*G: */\n\t\t{{{0x2148dabf, 0x3e7ea23f, 0x09d78eb1, 0x2b74ae4d, 0x3ae735c1, 0x193b08d7, 0x27546d97, 0x24c09b24, 0xe42d}},\n\t\t {{0x011e1361, 0x1dcb1d5a, 0x1e77eb9d, 0x1c9d5c06, 0x33853032, 0x0e33aff7, 0x184b0d8b, 0x218b1b8b, 0x6413}}}\n\t},\n\t{\n\t\t/*  1*16^51*G: */\n\t\t{{{0x366642be, 0x376d64a0, 0x158ba889, 0x0d241c5f, 0x0dfa8bce, 0x002bd1a0, 0x30c2f91b, 0x1de30119, 0x146a}},\n\t\t {{0x3d83efd0, 0x02ca5d20, 0x37e5ed1d, 0x2aa5c74b, 0x14b2870a, 0x1a609fe7, 0x0028add6, 0x383b0cd5, 0xb318}}},\n\t\t/*  3*16^51*G: */\n\t\t{{{0x27315443, 0x364e1ce0, 0x2e867299, 0x1e6ef552, 0x2142a13d, 0x32266082, 0x0935ff42, 0x1b010198, 0xfc69}},\n\t\t {{0x17d28960, 0x1243582d, 0x09bd1b17, 0x1ffd2184, 0x1677b548, 0x0387375a, 0x35892bbf, 0x09fafe0e, 0xe0ce}}},\n\t\t/*  5*16^51*G: */\n\t\t{{{0x16fdb4eb, 0x06ecbd70, 0x22e6a79d, 0x28f75e71, 0x3eb0928f, 0x15a8d58a, 0x3f2ad1ae, 0x3c887fd3, 0x974a}},\n\t\t {{0x29f6f484, 0x10270f7e, 0x3ffc2348, 0x0715ca8e, 0x0090ed11, 0x0790f40b, 0x003ca64d, 0x0e1f54d4, 0x5552}}},\n\t\t/*  7*16^51*G: */\n\t\t{{{0x1d5aeee3, 0x0e412b6d, 0x258c8137, 0x0a12f0d9, 0x1270c5e8, 0x086ce99a, 0x2398b091, 0x2d66d277, 0x5baa}},\n\t\t {{0x30f69717, 0x0b4a6bed, 0x3d31eed8, 0x1777276a, 0x3fdaf721, 0x28021987, 0x37e856e5, 0x1fd85f03, 0x8a57}}},\n\t\t/*  9*16^51*G: */\n\t\t{{{0x35726890, 0x146c7913, 0x0837d158, 0x24097fab, 0x110a0ee5, 0x0cbf3afe, 0x1c43d010, 0x17e9fad2, 0xfb68}},\n\t\t {{0x3835783a, 0x01baa3ce, 0x10e79b26, 0x29b2c4ba, 0x24ba094f, 0x3285b661, 0x25e2e869, 0x37c8b263, 0xd750}}},\n\t\t/* 11*16^51*G: */\n\t\t{{{0x28bca48a, 0x1192fc4e, 0x03df62f5, 0x2d357d3a, 0x07f71d78, 0x09ee470a, 0x2995a0ab, 0x23fd9678, 0x5de5}},\n\t\t {{0x12fd41cd, 0x21e53a03, 0x20f8aa95, 0x396f6713, 0x2d3c843f, 0x2988f094, 0x19b55309, 0x0ecf600d, 0x685a}}},\n\t\t/* 13*16^51*G: */\n\t\t{{{0x25ef63b6, 0x378e0d13, 0x31b182eb, 0x2d34059c, 0x0fc1c85a, 0x2dff68ed, 0x218bfaf1, 0x09737ab5, 0x6f18}},\n\t\t {{0x05c655f3, 0x0b211b3d, 0x27f94541, 0x22569900, 0x3334553c, 0x108135e0, 0x1911b98f, 0x1f9f7564, 0xff09}}},\n\t\t/* 15*16^51*G: */\n\t\t{{{0x34a63f3b, 0x2d411fb7, 0x178f9727, 0x080ec066, 0x36c76583, 0x1c457d79, 0x2a376b58, 0x2e257dd8, 0xc5ec}},\n\t\t {{0x05005024, 0x14fcdd1a, 0x230bee5b, 0x3ad97b97, 0x1233ec8b, 0x290163fe, 0x081f374e, 0x0946065e, 0x2225}}}\n\t},\n\t{\n\t\t/*  1*16^52*G: */\n\t\t{{{0x3180eef9, 0x35daa1e4, 0x228b9776, 0x00048826, 0x207b128d, 0x2b3aec6a, 0x2e5f07e3, 0x303d8748, 0xfa50}},\n\t\t {{0x3f4f2811, 0x233635f4, 0x17a213b3, 0x1a0ca4e9, 0x01a68a5e, 0x334a1c8a, 0x3eba9b72, 0x31a488e5, 0x6b84}}},\n\t\t/*  3*16^52*G: */\n\t\t{{{0x11da5e12, 0x07b838ce, 0x1cacb297, 0x31829005, 0x1ca2b6a9, 0x0ca7e4e8, 0x1e31bcda, 0x0b8f10de, 0xf750}},\n\t\t {{0x0385f4eb, 0x292e717a, 0x325cebc7, 0x21b4cbbd, 0x1672047b, 0x1c25170f, 0x0fafd599, 0x3d7b759f, 0x3c57}}},\n\t\t/*  5*16^52*G: */\n\t\t{{{0x10b7d105, 0x01d24cc4, 0x0e57c9f2, 0x329712e5, 0x3455b3f4, 0x13d98938, 0x25862a3a, 0x1e3e60eb, 0x12fe}},\n\t\t {{0x1f794a60, 0x162b1bee, 0x2ee90b84, 0x3b389975, 0x27cb771d, 0x2d6a8666, 0x2bcf7786, 0x3c68ce35, 0x2062}}},\n\t\t/*  7*16^52*G: */\n\t\t{{{0x1e0c5d05, 0x188760ce, 0x2572daff, 0x039b142a, 0x084b1a48, 0x12ec40a0, 0x3473d58c, 0x30c4d1f7, 0x76aa}},\n\t\t {{0x11ece63e, 0x159866dd, 0x15e6ee35, 0x048973c0, 0x02625f4b, 0x3ccb20c8, 0x070efabe, 0x1dbbc357, 0xef55}}},\n\t\t/*  9*16^52*G: */\n\t\t{{{0x3c53c086, 0x389bd217, 0x09a1aec9, 0x2d570d27, 0x288104c6, 0x1830c517, 0x05ccc87e, 0x3f96ef97, 0xa663}},\n\t\t {{0x25016201, 0x1a7140ca, 0x3994fc0e, 0x07b3295c, 0x023dc399, 0x2c40b226, 0x11fbf5d1, 0x265fdac8, 0xb541}}},\n\t\t/* 11*16^52*G: */\n\t\t{{{0x0b758574, 0x2b6007b5, 0x34f9c6e9, 0x0c99a250, 0x22bdf3d8, 0x328409eb, 0x2cd825b7, 0x149e8081, 0xde95}},\n\t\t {{0x3b67232a, 0x2df7c7f3, 0x15a2deb4, 0x39a84145, 0x169ed7ba, 0x077211fc, 0x3d14e4e2, 0x3815ab24, 0x4cd3}}},\n\t\t/* 13*16^52*G: */\n\t\t{{{0x3d85474f, 0x1de6e2af, 0x1634668d, 0x13128ae2, 0x385aea89, 0x3732f911, 0x32addbfe, 0x2f3819b4, 0x8da6}},\n\t\t {{0x3d7b4ef7, 0x3f7e71f4, 0x1dbdd7a5, 0x073164c1, 0x1dfff10b, 0x377d741c, 0x2d4ff84f, 0x1b1abcc7, 0x13fc}}},\n\t\t/* 15*16^52*G: */\n\t\t{{{0x3dd042ea, 0x2d750959, 0x18eafd06, 0x3e89a991, 0x3c93beeb, 0x3599278c, 0x3ba39b1b, 0x2b31f3ec, 0x7329}},\n\t\t {{0x2f5c94a1, 0x36a33fb0, 0x1fab4f0a, 0x1225dcc7, 0x2b68ee18, 0x2139e53e, 0x36f14892, 0x124d506d, 0x9272}}}\n\t},\n\t{\n\t\t/*  1*16^53*G: */\n\t\t{{{0x1f067ec2, 0x394f4cad, 0x1bba5220, 0x0a22ad75, 0x08e8421a, 0x16fdadf6, 0x21a11b1a, 0x1874329c, 0xda1d}},\n\t\t {{0x1ad836f1, 0x157ee83c, 0x279b48a6, 0x29ce2674, 0x091e2966, 0x01d98587, 0x1306c79c, 0x3d569f26, 0x8157}}},\n\t\t/*  3*16^53*G: */\n\t\t{{{0x3a95a8db, 0x1761dccb, 0x39d36f61, 0x0fb03111, 0x1b1723b8, 0x25991a64, 0x3dd0419e, 0x036918c0, 0xe3e9}},\n\t\t {{0x1b0d1cf9, 0x005b3dfc, 0x0984d3d1, 0x2c7be5f3, 0x02e76afb, 0x3eaa431c, 0x0178bb00, 0x0ef0015b, 0xfbe5}}},\n\t\t/*  5*16^53*G: */\n\t\t{{{0x112ee214, 0x1eabf590, 0x19315401, 0x0a93a5e5, 0x00c01c78, 0x19437f57, 0x3d775a8b, 0x3fb1ccb8, 0x9f4f}},\n\t\t {{0x1085f37a, 0x3bd10889, 0x3c880283, 0x066da4c2, 0x35c69d97, 0x259a0bf5, 0x22f2e60e, 0x38b84c63, 0x639c}}},\n\t\t/*  7*16^53*G: */\n\t\t{{{0x1f61a0a5, 0x22da0514, 0x3c14e3ef, 0x0494f86c, 0x040b2c4b, 0x0682907d, 0x34ac1b17, 0x188b5044, 0x431f}},\n\t\t {{0x38cef899, 0x1adedff9, 0x15657724, 0x2eaa810d, 0x23aa7241, 0x3799465c, 0x2438f6d6, 0x0c9ff9ea, 0xa298}}},\n\t\t/*  9*16^53*G: */\n\t\t{{{0x27748503, 0x2b099f55, 0x31328e7c, 0x1b8391dc, 0x0a12ac0e, 0x18bbce7e, 0x38fb86cb, 0x2eb77b39, 0x993d}},\n\t\t {{0x3eb0cee2, 0x2e9cd84d, 0x38adaa49, 0x3e1efda6, 0x21f51a17, 0x3de11e1e, 0x1eeeb785, 0x2a7ba15a, 0xa521}}},\n\t\t/* 11*16^53*G: */\n\t\t{{{0x26d23d80, 0x37a889d6, 0x2474d478, 0x02f447c9, 0x0962c0e1, 0x250c72e4, 0x15ea5a33, 0x1eae81ab, 0x75f1}},\n\t\t {{0x280dd57e, 0x21aa16c0, 0x34ea5909, 0x0bfefb6e, 0x1b629237, 0x31f42fc6, 0x39a80c7f, 0x18bf8558, 0xa07a}}},\n\t\t/* 13*16^53*G: */\n\t\t{{{0x21ad3413, 0x38ae6db5, 0x327d684a, 0x2e700100, 0x387b7a8d, 0x257d2172, 0x1f4a0a6e, 0x15578476, 0x6678}},\n\t\t {{0x3ebca672, 0x09204081, 0x2dc66601, 0x338b454e, 0x0bdf9ea6, 0x099b649f, 0x0f646925, 0x368f789e, 0x510d}}},\n\t\t/* 15*16^53*G: */\n\t\t{{{0x06cc8563, 0x3002bd6c, 0x3e101eaa, 0x0937d6ff, 0x16368892, 0x320af606, 0x27748ada, 0x128d8b36, 0xebdc}},\n\t\t {{0x2394ccfa, 0x26c5ef3a, 0x1204f924, 0x3101e492, 0x1d4f07be, 0x3b8d79b3, 0x2d35f9b1, 0x0c513a15, 0x659a}}}\n\t},\n\t{\n\t\t/*  1*16^54*G: */\n\t\t{{{0x0d064e13, 0x29cec184, 0x06f1e062, 0x0c477811, 0x3d416615, 0x17fe63a3, 0x30690721, 0x20bfc325, 0xa8e2}},\n\t\t {{0x11f4cc0c, 0x3bdf1cc4, 0x0dd6bd6c, 0x19e68f94, 0x2515888b, 0x2dfcf16c, 0x01c09abf, 0x0d56e36e, 0x7f97}}},\n\t\t/*  3*16^54*G: */\n\t\t{{{0x3a3979b5, 0x0a8666c2, 0x27e829e2, 0x0a23e379, 0x240e50ba, 0x0dfc2c7b, 0x1e26327f, 0x01f1736b, 0xae22}},\n\t\t {{0x0450fa6f, 0x23cf359a, 0x3d4f8896, 0x2a1edf4d, 0x2d7060fc, 0x3249148e, 0x39f71ad4, 0x3f944301, 0xea91}}},\n\t\t/*  5*16^54*G: */\n\t\t{{{0x0efca824, 0x10406440, 0x22164fae, 0x2f8313fa, 0x185461e0, 0x31504019, 0x2ace59ce, 0x3b432b5c, 0xcb8d}},\n\t\t {{0x0f227361, 0x0502f416, 0x3931742f, 0x2b47f7f1, 0x2ccbc496, 0x05b121e8, 0x188c85b3, 0x0023dd03, 0x33a5}}},\n\t\t/*  7*16^54*G: */\n\t\t{{{0x3bcbd327, 0x1046d368, 0x1e4aaee9, 0x13821488, 0x276ed6b0, 0x2524035f, 0x1836708e, 0x0eca62bc, 0xb0c5}},\n\t\t {{0x2d7be436, 0x185af128, 0x0636a0f1, 0x0a88831d, 0x26b2afd8, 0x3da9806d, 0x17ea1638, 0x25d007ef, 0xee2a}}},\n\t\t/*  9*16^54*G: */\n\t\t{{{0x17b836a1, 0x39bbed8e, 0x3679ef7d, 0x019017fd, 0x37f526c8, 0x2218bb39, 0x1b920d4d, 0x29cfcca7, 0x6f6b}},\n\t\t {{0x06832b84, 0x36f7cbec, 0x0e1ff934, 0x264314a2, 0x3ee9c0d8, 0x02e29016, 0x3c18e3db, 0x2285ffd7, 0xdc77}}},\n\t\t/* 11*16^54*G: */\n\t\t{{{0x1eb39ede, 0x2bb8d082, 0x30612d42, 0x02200cb5, 0x02436031, 0x3fd19f84, 0x22af4bbc, 0x069f71d0, 0x7d47}},\n\t\t {{0x2bf6607e, 0x326f3652, 0x022a8fd0, 0x2573df47, 0x3c86fa77, 0x2088c7bf, 0x2856507b, 0x1ec67ce9, 0x004a}}},\n\t\t/* 13*16^54*G: */\n\t\t{{{0x165eb1c1, 0x15b52789, 0x1ae5c5aa, 0x335d59f3, 0x02f0967f, 0x03f30c66, 0x33fac707, 0x1458fe6d, 0xf002}},\n\t\t {{0x2dde2ae0, 0x369f5c11, 0x2cd11e57, 0x1dbfd735, 0x26afed85, 0x1ad29768, 0x120df4c6, 0x2a7a220f, 0x054e}}},\n\t\t/* 15*16^54*G: */\n\t\t{{{0x1ac32c64, 0x33cd424f, 0x0ae4bf84, 0x0dbf80fb, 0x07715e0e, 0x013a543d, 0x123aa0f7, 0x0500007b, 0xac12}},\n\t\t {{0x1eb1a867, 0x204ab6eb, 0x253f0898, 0x16974e96, 0x0499a3ed, 0x02da55cc, 0x38baf187, 0x2f32eb0c, 0xce8e}}}\n\t},\n\t{\n\t\t/*  1*16^55*G: */\n\t\t{{{0x0319497c, 0x0bce0b7a, 0x12508c02, 0x166c7e94, 0x13cab15d, 0x2795b9a4, 0x285872d3, 0x14ee7268, 0x174a}},\n\t\t {{0x079afa73, 0x0f684eb0, 0x0b985438, 0x1ace8763, 0x07f9e664, 0x10557cb1, 0x09c1657b, 0x370deaff, 0xccc9}}},\n\t\t/*  3*16^55*G: */\n\t\t{{{0x354b8367, 0x25201cf5, 0x3d506bfe, 0x1d6ddf59, 0x036a5db7, 0x2a975161, 0x2526e40c, 0x0252b911, 0x5e5a}},\n\t\t {{0x11ce85ca, 0x14ca6a76, 0x1e5ffa44, 0x1aaa7bcf, 0x2a4b7a79, 0x2407c55c, 0x15e05c2c, 0x3e32691e, 0xae8a}}},\n\t\t/*  5*16^55*G: */\n\t\t{{{0x17b10d9d, 0x06615e4e, 0x11f8fcaf, 0x294bc627, 0x0cb82de6, 0x332e0cc4, 0x02e859de, 0x382b6e5c, 0x00d4}},\n\t\t {{0x3140dced, 0x20840121, 0x0e2d923e, 0x1626325e, 0x2287f70b, 0x0be1190c, 0x3640947d, 0x0066060d, 0x87b8}}},\n\t\t/*  7*16^55*G: */\n\t\t{{{0x1c9caee8, 0x02046982, 0x1a270bb2, 0x0b88116c, 0x04a66763, 0x1e866bbb, 0x374c0f6f, 0x1484da3b, 0x0366}},\n\t\t {{0x3772b711, 0x2a7b1a8e, 0x295ba7f0, 0x32ea624c, 0x26944501, 0x27f1a06e, 0x3ded9994, 0x30cacaa4, 0x1f18}}},\n\t\t/*  9*16^55*G: */\n\t\t{{{0x1446c85c, 0x0ffe5d46, 0x201c0635, 0x0df78239, 0x36c6eade, 0x19db114f, 0x38f1faa0, 0x24415bf6, 0x0e58}},\n\t\t {{0x2148972e, 0x3db1df9c, 0x0cddadd5, 0x2408d3a0, 0x081898f4, 0x1d062ebd, 0x27bda0ec, 0x1217c47e, 0xe39a}}},\n\t\t/* 11*16^55*G: */\n\t\t{{{0x022e1259, 0x3c62b7cf, 0x281362af, 0x05ce6901, 0x07777193, 0x33d7ea80, 0x1463f2b6, 0x049b49bc, 0xa740}},\n\t\t {{0x334a5f43, 0x3ddc5c90, 0x31d6dad5, 0x21979d4e, 0x3c7ee517, 0x17c5d299, 0x0f1ff1b0, 0x3feebc65, 0x05a9}}},\n\t\t/* 13*16^55*G: */\n\t\t{{{0x0b08f1fe, 0x22285e8f, 0x3a087bfd, 0x339fb9c2, 0x02d177d7, 0x1015d976, 0x074e4a65, 0x2e085b65, 0x87e4}},\n\t\t {{0x2ed5e2ec, 0x17dd2b26, 0x2786d9d7, 0x0bc8f6f5, 0x38c2cc6e, 0x35fe3a8b, 0x348cecd7, 0x0eb01d98, 0xf74e}}},\n\t\t/* 15*16^55*G: */\n\t\t{{{0x21c4d15c, 0x2a1c039a, 0x3c0e74b9, 0x17a9efc1, 0x254a4410, 0x308b0304, 0x279a5a92, 0x06d18ffa, 0x35ea}},\n\t\t {{0x3f3fe1ea, 0x324e6ebd, 0x065095ed, 0x18cea80c, 0x0d3b185d, 0x23e97f5d, 0x2d2cd788, 0x245946e7, 0xad21}}}\n\t},\n\t{\n\t\t/*  1*16^56*G: */\n\t\t{{{0x1475b7ba, 0x213f7fc2, 0x0918b3d8, 0x0e79cc39, 0x018cdbe0, 0x395fb7d4, 0x3785c3d3, 0x25a60650, 0x9593}},\n\t\t {{0x3524f2fd, 0x26e2afe1, 0x0709385e, 0x194fd932, 0x1cd6849c, 0x00e1a92e, 0x331dd8ba, 0x154a2230, 0x2e7e}}},\n\t\t/*  3*16^56*G: */\n\t\t{{{0x0fd69985, 0x02717764, 0x1df72aea, 0x0c2732db, 0x0ccf149f, 0x3da437ef, 0x32f7e788, 0x1d9d73ad, 0x0ae9}},\n\t\t {{0x1409a003, 0x2723ad04, 0x2ee1aff8, 0x2e67505e, 0x1a54c5d0, 0x237fb814, 0x08d14e9b, 0x265cfdb9, 0x9121}}},\n\t\t/*  5*16^56*G: */\n\t\t{{{0x19262b90, 0x37064f7f, 0x23cc29a9, 0x08f1307f, 0x025d1fb7, 0x197c5de0, 0x1612ec9b, 0x218a96b0, 0x2b15}},\n\t\t {{0x083d7557, 0x24665b99, 0x19489a49, 0x14d25c3e, 0x0749066f, 0x0c354b6a, 0x233faa7a, 0x014f6a82, 0x2eb0}}},\n\t\t/*  7*16^56*G: */\n\t\t{{{0x28e7be40, 0x0fe5c532, 0x1040ee59, 0x34b22524, 0x24769af2, 0x2570585b, 0x2ee677ee, 0x3abb46a5, 0x6af9}},\n\t\t {{0x2e387e1c, 0x2905b809, 0x0f59569f, 0x38fd99a8, 0x07dc8145, 0x27a90a0d, 0x06649670, 0x0a845a40, 0xb381}}},\n\t\t/*  9*16^56*G: */\n\t\t{{{0x3482801e, 0x09adbe83, 0x1bd4155d, 0x1e53e2f1, 0x38d6f940, 0x2aad0932, 0x0144eeb3, 0x1a3b8111, 0x5966}},\n\t\t {{0x04870c37, 0x11dc523c, 0x3d3535ad, 0x2db072d8, 0x31304e8d, 0x23e5821d, 0x2ef5f1ec, 0x282a16ee, 0x949a}}},\n\t\t/* 11*16^56*G: */\n\t\t{{{0x032c19fd, 0x1326cb9f, 0x18028c3e, 0x32ae3a41, 0x170b5b4a, 0x3d345ead, 0x050762fd, 0x346206d4, 0xbe84}},\n\t\t {{0x32f1281f, 0x1da5294d, 0x250dc376, 0x1569fd57, 0x08399479, 0x3997d20c, 0x050944d1, 0x1832ccb7, 0xeff9}}},\n\t\t/* 13*16^56*G: */\n\t\t{{{0x16c69482, 0x346dd7f5, 0x32fa167b, 0x3aad5004, 0x32bc88cb, 0x15c9d32b, 0x17ee541f, 0x280c5303, 0x9867}},\n\t\t {{0x2f792cd7, 0x1bc18451, 0x15628a91, 0x189173d4, 0x3a99639e, 0x24b556c6, 0x0834f9c7, 0x18568ec4, 0xd02e}}},\n\t\t/* 15*16^56*G: */\n\t\t{{{0x1d557aa1, 0x2288e764, 0x101fc297, 0x0764bfb3, 0x19d6abdf, 0x1fcba802, 0x0815a592, 0x3c915036, 0xa866}},\n\t\t {{0x01430634, 0x2606eed3, 0x0611a4b7, 0x3ada719f, 0x30e13961, 0x0f63e976, 0x22b44d79, 0x0e7daa00, 0xb587}}}\n\t},\n\t{\n\t\t/*  1*16^57*G: */\n\t\t{{{0x1d82b151, 0x2d44d032, 0x21fba2db, 0x28290f55, 0x109a8fcc, 0x168454ec, 0x01e56d64, 0x0e942b90, 0xd2a6}},\n\t\t {{0x1cf89405, 0x105085d3, 0x084ca52d, 0x03dd42bd, 0x148220a7, 0x2bb962ca, 0x3fcb7565, 0x21bed910, 0xe82d}}},\n\t\t/*  3*16^57*G: */\n\t\t{{{0x2e4b3ba0, 0x2167d8d7, 0x18bf1f17, 0x0aafbd7c, 0x3f245f5c, 0x385c3cc6, 0x3fb73bef, 0x04414887, 0x4108}},\n\t\t {{0x17525595, 0x21a58770, 0x1a064554, 0x0d926159, 0x2b849813, 0x2996b875, 0x35668f2c, 0x3cda5dbf, 0xdc37}}},\n\t\t/*  5*16^57*G: */\n\t\t{{{0x13d98ded, 0x18a726e2, 0x38a02184, 0x37c8a0ce, 0x31d65edb, 0x3c8a6414, 0x0c0c8c8c, 0x2884285b, 0x63a2}},\n\t\t {{0x20d1cfc2, 0x06465f53, 0x1c7873a5, 0x2afda802, 0x2d94461f, 0x140cc953, 0x2c76fd06, 0x10b8b9ff, 0x882b}}},\n\t\t/*  7*16^57*G: */\n\t\t{{{0x38045445, 0x2a186942, 0x01e8d7ee, 0x3fdcdc64, 0x17bef080, 0x04b8b975, 0x167ca3df, 0x20575127, 0x0c15}},\n\t\t {{0x0054a206, 0x053e1f55, 0x258cea32, 0x0c15390d, 0x23cd28ba, 0x24f0ed99, 0x14115d0a, 0x35828eba, 0x2f30}}},\n\t\t/*  9*16^57*G: */\n\t\t{{{0x03857faf, 0x3a448e73, 0x29619701, 0x0bf2b787, 0x28ef7f88, 0x1eea3d20, 0x28a9c0d5, 0x3adae26b, 0xc757}},\n\t\t {{0x20584ca4, 0x07676c32, 0x01894c10, 0x1f4c4344, 0x3ec61b62, 0x0da7c822, 0x3ff36257, 0x1673f348, 0xf03a}}},\n\t\t/* 11*16^57*G: */\n\t\t{{{0x1459225d, 0x3934613d, 0x18858d10, 0x3ebddf8b, 0x1c02a244, 0x17502646, 0x3a0d0f81, 0x18ebab6b, 0xfa80}},\n\t\t {{0x3ece1507, 0x28adf8ed, 0x007c59c3, 0x0adb0db4, 0x0c425c0a, 0x37888209, 0x0c069160, 0x07e415f0, 0x0ba7}}},\n\t\t/* 13*16^57*G: */\n\t\t{{{0x16f0d044, 0x19e7fa50, 0x09e61a79, 0x2ea7f524, 0x2ee0a5aa, 0x3da73e18, 0x257a89e2, 0x28f16740, 0x658c}},\n\t\t {{0x37cb872d, 0x3747ccbb, 0x018ce89a, 0x2859d8f1, 0x3bd37655, 0x197589c4, 0x225460f1, 0x304ddeba, 0xae5c}}},\n\t\t/* 15*16^57*G: */\n\t\t{{{0x3696756d, 0x2d6b255c, 0x2561417a, 0x1abc5815, 0x3f305c67, 0x30660d74, 0x1f2bace4, 0x12d2abe4, 0x31c9}},\n\t\t {{0x1e08ae78, 0x2f117a37, 0x2ad1070a, 0x2bb7f2b9, 0x34160683, 0x2e2d66ab, 0x283a9bf4, 0x2212d55b, 0xf80f}}}\n\t},\n\t{\n\t\t/*  1*16^58*G: */\n\t\t{{{0x1617e073, 0x10dbe6d1, 0x039317b3, 0x2b2f6f4e, 0x0fdc866b, 0x39e25b5f, 0x31eb890e, 0x1f88cd51, 0x6458}},\n\t\t {{0x1faf6589, 0x20a6797a, 0x33aeab35, 0x2e428e44, 0x0299a185, 0x1b75911f, 0x102e2ae9, 0x33756fda, 0xd99f}}},\n\t\t/*  3*16^58*G: */\n\t\t{{{0x0e103dd6, 0x37dc51c8, 0x0004859a, 0x1181301f, 0x12a17ac3, 0x084f3f16, 0x203f836a, 0x1ef55690, 0xbc47}},\n\t\t {{0x16f7c343, 0x0e420b63, 0x23b44ac6, 0x0a4d5cb1, 0x1ea6395d, 0x2b154b1b, 0x0dd526cb, 0x07890a6a, 0xe31e}}},\n\t\t/*  5*16^58*G: */\n\t\t{{{0x144eab31, 0x34370ec3, 0x0e634907, 0x316bc501, 0x3bf8e80a, 0x0ed08c99, 0x3b838030, 0x2d3f969a, 0x589d}},\n\t\t {{0x11361f6a, 0x106baf9d, 0x148f8db9, 0x18439548, 0x3d90f31f, 0x1c188092, 0x2a2a4f60, 0x11170422, 0x6255}}},\n\t\t/*  7*16^58*G: */\n\t\t{{{0x1a0c2c41, 0x2fe585ca, 0x20336c67, 0x20c70715, 0x2edb7c42, 0x286182b5, 0x22fa2ea8, 0x2ccdf45b, 0x1339}},\n\t\t {{0x29f1bc2b, 0x217c152e, 0x1e923a41, 0x0489fe1f, 0x13a3406b, 0x0c903f44, 0x3ae5ba7a, 0x0a58d8b1, 0x9f9b}}},\n\t\t/*  9*16^58*G: */\n\t\t{{{0x18fc47af, 0x1c12c7e1, 0x2c0cdec3, 0x377fb20c, 0x01b568a8, 0x00ca6d40, 0x3cf17cc5, 0x2ee844d8, 0x7ff3}},\n\t\t {{0x39ba43a7, 0x3e185933, 0x18bac297, 0x294ec6b4, 0x33446b17, 0x32246dd1, 0x0a629a0b, 0x29eba006, 0x1f6b}}},\n\t\t/* 11*16^58*G: */\n\t\t{{{0x15213775, 0x06135802, 0x3d42a990, 0x2d0a4ec8, 0x2c7f6100, 0x07a4e57f, 0x360bb614, 0x1c118f3a, 0x8ec6}},\n\t\t {{0x3841ffff, 0x38043cf9, 0x0cf51e90, 0x36a6282f, 0x2dee0e71, 0x190d0573, 0x25be306e, 0x299be836, 0x8f58}}},\n\t\t/* 13*16^58*G: */\n\t\t{{{0x3452abbb, 0x32cffe34, 0x2b95c2e3, 0x1aa9cbf8, 0x15d495ae, 0x2eb0ffb6, 0x301bb89d, 0x186d1079, 0x83de}},\n\t\t {{0x054eb66e, 0x28145dac, 0x3ce42918, 0x2717cdae, 0x0e1563d7, 0x3edabe31, 0x0609fa6b, 0x38cd28d3, 0x32f0}}},\n\t\t/* 15*16^58*G: */\n\t\t{{{0x359276f1, 0x25a2309b, 0x2a17b15e, 0x2b896ca4, 0x3cd86833, 0x2ed7003d, 0x0c1db1a8, 0x18e263d4, 0x3d76}},\n\t\t {{0x059cbcb3, 0x0792996e, 0x1b197860, 0x08660806, 0x18333ef3, 0x1db8d36b, 0x07ddb609, 0x1a5cde86, 0xd376}}}\n\t},\n\t{\n\t\t/*  1*16^59*G: */\n\t\t{{{0x1d45e458, 0x1635b21b, 0x250e7fd3, 0x02a9b3a8, 0x09de042f, 0x151b4f95, 0x0d885b3a, 0x2f783939, 0x8481}},\n\t\t {{0x1779057e, 0x3592c6d6, 0x3262e556, 0x029e710a, 0x2cb2ca90, 0x096fce73, 0x004dd84a, 0x1ee32e95, 0x38ee}}},\n\t\t/*  3*16^59*G: */\n\t\t{{{0x152da17d, 0x18283e90, 0x0d0646b1, 0x3704f6c2, 0x200bc811, 0x139ac17f, 0x18c5f089, 0x3b4783d4, 0x3bea}},\n\t\t {{0x2cc768d2, 0x39c12617, 0x1fec416c, 0x3379dee3, 0x00e1b554, 0x12a2fafa, 0x37acdfef, 0x35fd56bf, 0xc3b0}}},\n\t\t/*  5*16^59*G: */\n\t\t{{{0x3a4edcc5, 0x0d3e85f6, 0x20311b72, 0x138c8850, 0x275997e7, 0x0b7f00e4, 0x09d61875, 0x36e832f7, 0x6e73}},\n\t\t {{0x159da0e4, 0x2cc7df37, 0x00679037, 0x229df69c, 0x02869327, 0x11542222, 0x2cc48bea, 0x307f127b, 0xee0a}}},\n\t\t/*  7*16^59*G: */\n\t\t{{{0x0a80b979, 0x02713109, 0x29abb314, 0x243d7e8c, 0x07c31004, 0x1f65faa9, 0x1b592762, 0x37624df9, 0x7706}},\n\t\t {{0x0126cfde, 0x133d2041, 0x17efe321, 0x3e828d3f, 0x2a9c7117, 0x2375e647, 0x3b714777, 0x2a609f56, 0x8a02}}},\n\t\t/*  9*16^59*G: */\n\t\t{{{0x326fe285, 0x336e712d, 0x13ef127d, 0x16eb0a50, 0x39e06aa4, 0x3cf1e907, 0x3c0f80d2, 0x08b164a6, 0x16d4}},\n\t\t {{0x0155b441, 0x0f83ff9b, 0x3364d423, 0x0fc3044d, 0x3531b1e9, 0x2df9a698, 0x22641a8a, 0x223e9478, 0x0df8}}},\n\t\t/* 11*16^59*G: */\n\t\t{{{0x3acfa513, 0x38c42f2a, 0x260e3aea, 0x0901e7e6, 0x356a9c4e, 0x28d11d43, 0x36d63aa5, 0x0391fbb1, 0x1fcc}},\n\t\t {{0x107afc9c, 0x141d6e90, 0x09839187, 0x3b7b7459, 0x39f9b44b, 0x38e1d50c, 0x35478b48, 0x30681078, 0x165d}}},\n\t\t/* 13*16^59*G: */\n\t\t{{{0x3edc69b2, 0x0689c1f3, 0x26b77172, 0x0298226c, 0x0aa386a5, 0x190c10d7, 0x0b8a1730, 0x241ceb5b, 0xc12b}},\n\t\t {{0x20dd41dd, 0x0caba6c0, 0x127b2a00, 0x3b876f8f, 0x094976b8, 0x1cb7227e, 0x0cdf1d97, 0x310ff94d, 0x3173}}},\n\t\t/* 15*16^59*G: */\n\t\t{{{0x3961fe4d, 0x2dbd6177, 0x3107197a, 0x05221be2, 0x2ca73e8a, 0x0fa4c4c4, 0x27a8fa3f, 0x2fe1770c, 0xd059}},\n\t\t {{0x2ae823c2, 0x264d6c19, 0x0dab64cb, 0x0e22e87d, 0x0955b4fd, 0x01d97721, 0x3525e3fe, 0x1e983022, 0x4510}}}\n\t},\n\t{\n\t\t/*  1*16^60*G: */\n\t\t{{{0x2caf666b, 0x3358c0fd, 0x0b1ce30b, 0x3f3fb4f1, 0x17f4637f, 0x1a5e6ba0, 0x102aa62b, 0x1295e9e0, 0x1346}},\n\t\t {{0x3f6ecc27, 0x3d256a41, 0x10942e13, 0x3cc02a07, 0x0cb0ca48, 0x390cd14f, 0x14580ef7, 0x05640118, 0x69be}}},\n\t\t/*  3*16^60*G: */\n\t\t{{{0x0eca5f51, 0x085ac826, 0x0fc9aebf, 0x3a85c6e5, 0x05b5cfdd, 0x3b5acafc, 0x2e6962c6, 0x35453767, 0xdde9}},\n\t\t {{0x10c638f7, 0x2b5a69cf, 0x289571f9, 0x3fbafa37, 0x3f8f0950, 0x07cd2c29, 0x28111d89, 0x1a44cf38, 0xb84e}}},\n\t\t/*  5*16^60*G: */\n\t\t{{{0x199c88e4, 0x3e41ac16, 0x0ad46ec2, 0x3b544f88, 0x204b179a, 0x3d01bac4, 0x193736e9, 0x188408da, 0xfd1a}},\n\t\t {{0x195bc8df, 0x27232459, 0x1cc00f29, 0x1adc7525, 0x177782dc, 0x0f01a552, 0x0c20bfb1, 0x1ed52e72, 0x1ac9}}},\n\t\t/*  7*16^60*G: */\n\t\t{{{0x1f8018ce, 0x35456d6d, 0x1892d68b, 0x0b695ce3, 0x086dc7cf, 0x3ff393cb, 0x296b9f13, 0x214c7630, 0x4ee4}},\n\t\t {{0x1e48381f, 0x30d6986c, 0x0e806013, 0x01d25c6d, 0x07c5e671, 0x2d102343, 0x3f8b5fc7, 0x27b52042, 0xb68f}}},\n\t\t/*  9*16^60*G: */\n\t\t{{{0x31473678, 0x0a14ba47, 0x14392f70, 0x2815e542, 0x38c070cb, 0x38c53156, 0x000dbff5, 0x33270d31, 0xfd76}},\n\t\t {{0x0d144f4f, 0x38593baa, 0x001c8437, 0x18a3bb85, 0x032cd660, 0x3b829cf4, 0x143dae0f, 0x1950de1c, 0xf204}}},\n\t\t/* 11*16^60*G: */\n\t\t{{{0x0d7a2193, 0x3c02dc52, 0x197546ed, 0x1a47913c, 0x34ea212c, 0x1b3a09d2, 0x3b40219e, 0x2ae8cc48, 0x85a2}},\n\t\t {{0x30cdcf3a, 0x3c320f52, 0x03b12427, 0x31b6b7e7, 0x0c029fe1, 0x31820b47, 0x30516d82, 0x2615faca, 0x9c12}}},\n\t\t/* 13*16^60*G: */\n\t\t{{{0x377568b0, 0x16c0c16c, 0x1e03b053, 0x2ba37406, 0x03650f35, 0x2db5b15e, 0x3fe74440, 0x36ff1cf3, 0xd25d}},\n\t\t {{0x1f39929c, 0x0284e49b, 0x23c3f006, 0x089ce207, 0x27d92b83, 0x2bbdd337, 0x048938be, 0x3fdd64fe, 0x7a3a}}},\n\t\t/* 15*16^60*G: */\n\t\t{{{0x271d7c13, 0x17f94462, 0x20ffa385, 0x06ad7dfe, 0x2ac80564, 0x01fa6a5e, 0x14a7255f, 0x0d4c50fa, 0x4581}},\n\t\t {{0x3aff63cf, 0x18e2f154, 0x2bd96b99, 0x08019550, 0x1d69c970, 0x3d43c5df, 0x39ad8b57, 0x163b0525, 0x9f58}}}\n\t},\n\t{\n\t\t/*  1*16^61*G: */\n\t\t{{{0x2d83f366, 0x2b68e834, 0x2f28588c, 0x36733b78, 0x1dc97a0c, 0x3d0c2f30, 0x3fe2e9ae, 0x277d6dc4, 0xbc4a}},\n\t\t {{0x181f33c1, 0x1d635999, 0x2547b16d, 0x3a2a7efe, 0x3798caa6, 0x24deb7d2, 0x05c06383, 0x20729b9e, 0x0d3a}}},\n\t\t/*  3*16^61*G: */\n\t\t{{{0x3712be3c, 0x01a8b8cb, 0x2146a66b, 0x257c63b6, 0x00153472, 0x1c976eac, 0x1b378d3c, 0x0d2764cc, 0x39d7}},\n\t\t {{0x1c6ff65c, 0x30c067d0, 0x0a41644c, 0x17bde97b, 0x2812e8ef, 0x09d55319, 0x33bf7fb1, 0x26d3d5bb, 0x8f92}}},\n\t\t/*  5*16^61*G: */\n\t\t{{{0x1f77f22b, 0x2ab93ef3, 0x0f82e035, 0x265c8e65, 0x15af26c6, 0x0735b0a6, 0x01dd09e5, 0x2985fdf7, 0xf0cb}},\n\t\t {{0x1909a03c, 0x3f238b1d, 0x0a095661, 0x3c631fa4, 0x16d04004, 0x0c9b0d94, 0x1df989ef, 0x2ad0c4fe, 0x1a25}}},\n\t\t/*  7*16^61*G: */\n\t\t{{{0x06509c12, 0x22b37353, 0x3d1f4765, 0x1aff88d6, 0x3268ed8d, 0x05c3a361, 0x154d321d, 0x1eae76c8, 0x381d}},\n\t\t {{0x2eb46102, 0x1190aa38, 0x0e6eaf75, 0x160a161b, 0x2581e720, 0x34915ce9, 0x23da9eb5, 0x2ad6dff6, 0xa47a}}},\n\t\t/*  9*16^61*G: */\n\t\t{{{0x384fe955, 0x36ced358, 0x063bce48, 0x2655a968, 0x0c8a53f6, 0x0edcf9a5, 0x387e6479, 0x3c1519ea, 0xa703}},\n\t\t {{0x161344bd, 0x09acbbef, 0x197277fa, 0x27858a71, 0x19199b53, 0x29e4b5ac, 0x047adc0e, 0x3e4d68ac, 0xd500}}},\n\t\t/* 11*16^61*G: */\n\t\t{{{0x06eace58, 0x126595b0, 0x2f3211d3, 0x1f9158e8, 0x13a03f1b, 0x1ab435c1, 0x150d746c, 0x2cf16ab5, 0x73c6}},\n\t\t {{0x2af8654e, 0x05c2a45c, 0x3b8d2917, 0x1aa1e36e, 0x2d91c6aa, 0x242644d9, 0x24f741ba, 0x2d291cce, 0x3a2f}}},\n\t\t/* 13*16^61*G: */\n\t\t{{{0x00181d5e, 0x12ce22fc, 0x15aaf205, 0x1c6cea6e, 0x0eddb8de, 0x0034e870, 0x147fda1d, 0x3cf9d41b, 0xc627}},\n\t\t {{0x369f886d, 0x09e40298, 0x1cbe2c39, 0x3dac0152, 0x21f7d68e, 0x1a5804e2, 0x02a63b2d, 0x2775c791, 0xd78f}}},\n\t\t/* 15*16^61*G: */\n\t\t{{{0x37828b16, 0x138a367e, 0x0a4847f3, 0x11e563ca, 0x06de53a0, 0x17d029bc, 0x3d233fa2, 0x3eaf83b7, 0xbb88}},\n\t\t {{0x0aea5df7, 0x1451ce88, 0x3a1e969c, 0x12a05d38, 0x159163ec, 0x37165804, 0x1e8dd345, 0x1dacc13d, 0xb736}}}\n\t},\n\t{\n\t\t/*  1*16^62*G: */\n\t\t{{{0x25324caa, 0x152acc3f, 0x29472a39, 0x12d978c2, 0x12a32e69, 0x3631d251, 0x18bc0d23, 0x2a5efe0a, 0x8c28}},\n\t\t {{0x0bef9482, 0x39c771cf, 0x11cb9459, 0x39e13c11, 0x3cc0eb7a, 0x3fb7cc7d, 0x05193378, 0x0118e8cc, 0x40a3}}},\n\t\t/*  3*16^62*G: */\n\t\t{{{0x0754dd40, 0x18fa1c55, 0x03466cf8, 0x10898c7f, 0x32f6e9a2, 0x12107f35, 0x0dfcf45b, 0x091c0cb0, 0x9729}},\n\t\t {{0x2aa36143, 0x212d24bc, 0x1acaf493, 0x36ba1495, 0x14df3690, 0x171d772f, 0x3ea1dcd1, 0x28910997, 0x91d1}}},\n\t\t/*  5*16^62*G: */\n\t\t{{{0x0c2ca7ff, 0x30b60bae, 0x1df021a3, 0x00d91765, 0x2f27af18, 0x1e46b568, 0x2796e050, 0x1fe5d602, 0x8963}},\n\t\t {{0x30493e68, 0x3b505785, 0x242eab7b, 0x1ef1a8e3, 0x357489f8, 0x2e73c550, 0x08424d57, 0x38492322, 0x2d1f}}},\n\t\t/*  7*16^62*G: */\n\t\t{{{0x0ca8dd7f, 0x061b58e8, 0x2a1381a6, 0x31ca00d5, 0x1357421b, 0x327680f5, 0x25e092fd, 0x0e39c6f8, 0x3081}},\n\t\t {{0x0a92c7f2, 0x1057c91e, 0x34ad915e, 0x05959190, 0x008e18c8, 0x27b11745, 0x0fc925e3, 0x38b4a20a, 0x28d1}}},\n\t\t/*  9*16^62*G: */\n\t\t{{{0x066a3fb1, 0x037315a2, 0x192e206c, 0x30024a06, 0x36862f6e, 0x15d43216, 0x1eb65d1e, 0x313a0a9b, 0x575f}},\n\t\t {{0x102655ad, 0x26e3a42a, 0x2a3af2f0, 0x0ced5cf1, 0x0e87daed, 0x076f0a5e, 0x2fca2d67, 0x36e410a9, 0x6f6e}}},\n\t\t/* 11*16^62*G: */\n\t\t{{{0x390117df, 0x06daa291, 0x22010292, 0x094eeef3, 0x2a2a8fda, 0x3c9be07b, 0x2ab7a227, 0x240dad93, 0xa5ec}},\n\t\t {{0x386462fe, 0x204a04cf, 0x214a363d, 0x21187c15, 0x1fa0f71c, 0x25e60eb4, 0x140400c5, 0x319897b0, 0xb79d}}},\n\t\t/* 13*16^62*G: */\n\t\t{{{0x172ad712, 0x2c3e5d70, 0x21047290, 0x0e632c37, 0x2349b95a, 0x39e5d851, 0x10b0949d, 0x37fa44cc, 0xa153}},\n\t\t {{0x0d48fdd2, 0x2297d94e, 0x2f0b329c, 0x014fca16, 0x31b89abd, 0x0c6357c7, 0x05b2fc48, 0x36104fec, 0xfd94}}},\n\t\t/* 15*16^62*G: */\n\t\t{{{0x11cf5b3a, 0x0c30dc04, 0x1b5a7810, 0x10cea0ef, 0x2dc824c4, 0x30d34223, 0x14615935, 0x06b1abde, 0x9a54}},\n\t\t {{0x36a44ae4, 0x0fd55d7c, 0x21ea52d6, 0x123fb894, 0x0f475f55, 0x386bcda2, 0x06ab7caf, 0x123072c4, 0xb661}}}\n\t},\n\t{\n\t\t/*  1*16^63*G: */\n\t\t{{{0x1faccae0, 0x2312e844, 0x24bb3374, 0x22cd4316, 0x071fd23c, 0x3653393c, 0x127a8c1d, 0x259984e5, 0x08ea}},\n\t\t {{0x0e62b945, 0x16bcd28c, 0x0f0f8e95, 0x2de0efa7, 0x15c5d735, 0x39f033ee, 0x22782e24, 0x3eaef23b, 0x620e}}},\n\t\t/*  3*16^63*G: */\n\t\t{{{0x26a06f5e, 0x06902d65, 0x2a083702, 0x1064945b, 0x23b716a3, 0x2c350849, 0x0253ac37, 0x093efa85, 0x383b}},\n\t\t {{0x13c6e772, 0x227d1e1b, 0x38c2b040, 0x3dab9d2e, 0x2a5a19e8, 0x3d59b553, 0x1ba2044c, 0x1c1ab13b, 0x54cf}}},\n\t\t/*  5*16^63*G: */\n\t\t{{{0x0638a136, 0x1e5d7075, 0x2838195c, 0x034738cd, 0x0d790c2b, 0x39671ad8, 0x2ed6d789, 0x0cb40f80, 0xe684}},\n\t\t {{0x0c6c2584, 0x2bf46042, 0x3357336a, 0x0278faf6, 0x01e6472e, 0x0a9cc0e8, 0x35a6624d, 0x3904e638, 0xca5b}}},\n\t\t/*  7*16^63*G: */\n\t\t{{{0x16e8c10c, 0x33a1f110, 0x11bd6807, 0x1ca617ce, 0x306e7fb4, 0x3ef7b39c, 0x25c2a0ee, 0x355678bf, 0x395d}},\n\t\t {{0x05fe638e, 0x30f5b64c, 0x066922cb, 0x24270137, 0x3a4e274c, 0x04fa1ebf, 0x12ac5d04, 0x37352d16, 0xfd62}}},\n\t\t/*  9*16^63*G: */\n\t\t{{{0x0d6c14ef, 0x059936c8, 0x2f93c8f5, 0x163f1d41, 0x22648008, 0x3bb56fbb, 0x25dcb9f6, 0x12b70d54, 0x7a51}},\n\t\t {{0x0b3fbd13, 0x2b4f861c, 0x2a6e24f7, 0x2fabbdca, 0x0f5c3729, 0x1fc2e532, 0x2e4d8e89, 0x347fb454, 0x56ed}}},\n\t\t/* 11*16^63*G: */\n\t\t{{{0x0f6d65eb, 0x2a518f41, 0x04021524, 0x26441dd5, 0x108f235a, 0x23bcefd2, 0x1d90d8ea, 0x3f5610c9, 0x1ee1}},\n\t\t {{0x1d22941c, 0x380dae49, 0x23582b11, 0x0cbd3a61, 0x02fcfaca, 0x2ae7f13d, 0x2c73c1cf, 0x0a246f75, 0xbb69}}},\n\t\t/* 13*16^63*G: */\n\t\t{{{0x0e36cb44, 0x3c6543bc, 0x1ca20191, 0x1fa2db23, 0x03357d61, 0x163f4362, 0x3aaa8bc0, 0x158d34e3, 0x1551}},\n\t\t {{0x1f495a68, 0x0a6bd194, 0x020c1e53, 0x30dc5d7c, 0x23205da8, 0x038fc2d1, 0x35215e37, 0x3ff1d555, 0xab4f}}},\n\t\t/* 15*16^63*G: */\n\t\t{{{0x3427bacc, 0x07e51841, 0x12d62e15, 0x1ccc5937, 0x0dc4aa9e, 0x163ac256, 0x35201363, 0x2f1911af, 0x3bc6}},\n\t\t {{0x2ad6fda6, 0x130cff57, 0x28beb471, 0x06dd6948, 0x16c02bd7, 0x18bb889b, 0x2c305cdb, 0x17301c5d, 0x8e30}}}\n\t},\n"
  },
  {
    "path": "src/utility/trezor/sha2.c",
    "content": "/**\n * Copyright (c) 2000-2001 Aaron D. Gifford\n * Copyright (c) 2013-2014 Pavol Rusnak\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n#include <string.h>\n#include <stdint.h>\n#include \"sha2.h\"\n#include \"memzero.h\"\n\n/*\n * ASSERT NOTE:\n * Some sanity checking code is included using assert().  On my FreeBSD\n * system, this additional code can be removed by compiling with NDEBUG\n * defined.  Check your own systems manpage on assert() to see how to\n * compile WITHOUT the sanity checking code on your system.\n *\n * UNROLLED TRANSFORM LOOP NOTE:\n * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform\n * loop version for the hash transform rounds (defined using macros\n * later in this file).  Either define on the command line, for example:\n *\n *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c\n *\n * or define below:\n *\n *   #define SHA2_UNROLL_TRANSFORM\n *\n */\n\n\n/*** SHA-256/384/512 Machine Architecture Definitions *****************/\n/*\n * BYTE_ORDER NOTE:\n *\n * Please make sure that your system defines BYTE_ORDER.  If your\n * architecture is little-endian, make sure it also defines\n * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are\n * equivilent.\n *\n * If your system does not define the above, then you can do so by\n * hand like this:\n *\n *   #define LITTLE_ENDIAN 1234\n *   #define BIG_ENDIAN    4321\n *\n * And for little-endian machines, add:\n *\n *   #define BYTE_ORDER LITTLE_ENDIAN \n *\n * Or for big-endian machines:\n *\n *   #define BYTE_ORDER BIG_ENDIAN\n *\n * The FreeBSD machine this was written on defines BYTE_ORDER\n * appropriately by including <sys/types.h> (which in turn includes\n * <machine/endian.h> where the appropriate definitions are actually\n * made).\n */\n\n#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)\n#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN\n#endif\n\ntypedef uint8_t  sha2_byte;\t/* Exactly 1 byte */\ntypedef uint32_t sha2_word32;\t/* Exactly 4 bytes */\ntypedef uint64_t sha2_word64;\t/* Exactly 8 bytes */\n\n/*** SHA-256/384/512 Various Length Definitions ***********************/\n/* NOTE: Most of these are in sha2.h */\n#define   SHA1_SHORT_BLOCK_LENGTH\t(SHA1_BLOCK_LENGTH - 8)\n#define SHA256_SHORT_BLOCK_LENGTH\t(SHA256_BLOCK_LENGTH - 8)\n#define SHA512_SHORT_BLOCK_LENGTH\t(SHA512_BLOCK_LENGTH - 16)\n\n/*\n * Macro for incrementally adding the unsigned 64-bit integer n to the\n * unsigned 128-bit integer (represented using a two-element array of\n * 64-bit words):\n */\n#define ADDINC128(w,n)\t{ \\\n\t(w)[0] += (sha2_word64)(n); \\\n\tif ((w)[0] < (n)) { \\\n\t\t(w)[1]++; \\\n\t} \\\n}\n\n#define MEMCPY_BCOPY(d,s,l)\tmemcpy((d), (s), (l))\n\n/*** THE SIX LOGICAL FUNCTIONS ****************************************/\n/*\n * Bit shifting and rotation (used by the six SHA-XYZ logical functions:\n *\n *   NOTE:  In the original SHA-256/384/512 document, the shift-right\n *   function was named R and the rotate-right function was called S.\n *   (See: http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf on the\n *   web.)\n *\n *   The newer NIST FIPS 180-2 document uses a much clearer naming\n *   scheme, SHR for shift-right, ROTR for rotate-right, and ROTL for\n *   rotate-left.  (See:\n *   http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\n *   on the web.)\n *\n *   WARNING: These macros must be used cautiously, since they reference\n *   supplied parameters sometimes more than once, and thus could have\n *   unexpected side-effects if used without taking this into account.\n */\n\n/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */\n#define SHR(b,x) \t\t((x) >> (b))\n/* 32-bit Rotate-right (used in SHA-256): */\n#define ROTR32(b,x)\t(((x) >> (b)) | ((x) << (32 - (b))))\n/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */\n#define ROTR64(b,x)\t(((x) >> (b)) | ((x) << (64 - (b))))\n/* 32-bit Rotate-left (used in SHA-1): */\n#define ROTL32(b,x)\t(((x) << (b)) | ((x) >> (32 - (b))))\n\n/* Two of six logical functions used in SHA-1, SHA-256, SHA-384, and SHA-512: */\n#define Ch(x,y,z)\t(((x) & (y)) ^ ((~(x)) & (z)))\n#define Maj(x,y,z)\t(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))\n\n/* Function used in SHA-1: */\n#define Parity(x,y,z)\t((x) ^ (y) ^ (z))\n\n/* Four of six logical functions used in SHA-256: */\n#define Sigma0_256(x)\t(ROTR32(2,  (x)) ^ ROTR32(13, (x)) ^ ROTR32(22, (x)))\n#define Sigma1_256(x)\t(ROTR32(6,  (x)) ^ ROTR32(11, (x)) ^ ROTR32(25, (x)))\n#define sigma0_256(x)\t(ROTR32(7,  (x)) ^ ROTR32(18, (x)) ^ SHR(3 ,   (x)))\n#define sigma1_256(x)\t(ROTR32(17, (x)) ^ ROTR32(19, (x)) ^ SHR(10,   (x)))\n\n/* Four of six logical functions used in SHA-384 and SHA-512: */\n#define Sigma0_512(x)\t(ROTR64(28, (x)) ^ ROTR64(34, (x)) ^ ROTR64(39, (x)))\n#define Sigma1_512(x)\t(ROTR64(14, (x)) ^ ROTR64(18, (x)) ^ ROTR64(41, (x)))\n#define sigma0_512(x)\t(ROTR64( 1, (x)) ^ ROTR64( 8, (x)) ^ SHR( 7,   (x)))\n#define sigma1_512(x)\t(ROTR64(19, (x)) ^ ROTR64(61, (x)) ^ SHR( 6,   (x)))\n\n/*** INTERNAL FUNCTION PROTOTYPES *************************************/\n/* NOTE: These should not be accessed directly from outside this\n * library -- they are intended for private internal visibility/use\n * only.\n */\nstatic void sha512_Last(SHA512_CTX*);\n\n\n/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/\n\n/* Hash constant words K for SHA-1: */\n#define K1_0_TO_19\t0x5a827999UL\n#define K1_20_TO_39\t0x6ed9eba1UL\n#define K1_40_TO_59\t0x8f1bbcdcUL\n#define K1_60_TO_79\t0xca62c1d6UL\n\n/* Hash constant words K for SHA-256: */\nstatic const sha2_word32 K256[64] = {\n\t0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,\n\t0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,\n\t0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,\n\t0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,\n\t0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,\n\t0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,\n\t0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,\n\t0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,\n\t0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,\n\t0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,\n\t0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,\n\t0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,\n\t0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,\n\t0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,\n\t0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,\n\t0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL\n};\n\n/* Initial hash value H for SHA-256: */\nconst sha2_word32 sha256_initial_hash_value[8] = {\n\t0x6a09e667UL,\n\t0xbb67ae85UL,\n\t0x3c6ef372UL,\n\t0xa54ff53aUL,\n\t0x510e527fUL,\n\t0x9b05688cUL,\n\t0x1f83d9abUL,\n\t0x5be0cd19UL\n};\n\n/* Hash constant words K for SHA-384 and SHA-512: */\nstatic const sha2_word64 K512[80] = {\n\t0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,\n\t0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,\n\t0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,\n\t0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,\n\t0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,\n\t0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,\n\t0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,\n\t0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,\n\t0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,\n\t0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,\n\t0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,\n\t0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,\n\t0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,\n\t0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,\n\t0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,\n\t0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,\n\t0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,\n\t0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,\n\t0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,\n\t0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,\n\t0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,\n\t0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,\n\t0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,\n\t0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,\n\t0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,\n\t0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,\n\t0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,\n\t0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,\n\t0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,\n\t0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,\n\t0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,\n\t0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,\n\t0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,\n\t0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,\n\t0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,\n\t0x113f9804bef90daeULL, 0x1b710b35131c471bULL,\n\t0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,\n\t0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,\n\t0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,\n\t0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL\n};\n\n/* Initial hash value H for SHA-512 */\nconst sha2_word64 sha512_initial_hash_value[8] = {\n\t0x6a09e667f3bcc908ULL,\n\t0xbb67ae8584caa73bULL,\n\t0x3c6ef372fe94f82bULL,\n\t0xa54ff53a5f1d36f1ULL,\n\t0x510e527fade682d1ULL,\n\t0x9b05688c2b3e6c1fULL,\n\t0x1f83d9abfb41bd6bULL,\n\t0x5be0cd19137e2179ULL\n};\n\n/*\n * Constant used by SHA256/384/512_End() functions for converting the\n * digest to a readable hexadecimal character string:\n */\nstatic const char *sha2_hex_digits = \"0123456789abcdef\";\n\n/*** SHA-256: *********************************************************/\nvoid sha256_Init(SHA256_CTX* context) {\n\tif (context == (SHA256_CTX*)0) {\n\t\treturn;\n\t}\n\tMEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);\n\tmemzero(context->buffer, SHA256_BLOCK_LENGTH);\n\tcontext->bitcount = 0;\n}\n\n#ifdef SHA2_UNROLL_TRANSFORM\n\n/* Unrolled SHA-256 round macros: */\n\n#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)\t\\\n\tT1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \\\n\t     K256[j] + (W256[j] = *data++); \\\n\t(d) += T1; \\\n\t(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \\\n\tj++\n\n#define ROUND256(a,b,c,d,e,f,g,h)\t\\\n\ts0 = W256[(j+1)&0x0f]; \\\n\ts0 = sigma0_256(s0); \\\n\ts1 = W256[(j+14)&0x0f]; \\\n\ts1 = sigma1_256(s1); \\\n\tT1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \\\n\t     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \\\n\t(d) += T1; \\\n\t(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \\\n\tj++\n\nvoid sha256_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) {\n\tsha2_word32\ta, b, c, d, e, f, g, h, s0, s1;\n\tsha2_word32\tT1;\n\tsha2_word32 W256[16];\n\tint\t\tj;\n\n\t/* Initialize registers with the prev. intermediate value */\n\ta = state_in[0];\n\tb = state_in[1];\n\tc = state_in[2];\n\td = state_in[3];\n\te = state_in[4];\n\tf = state_in[5];\n\tg = state_in[6];\n\th = state_in[7];\n\n\tj = 0;\n\tdo {\n\t\t/* Rounds 0 to 15 (unrolled): */\n\t\tROUND256_0_TO_15(a,b,c,d,e,f,g,h);\n\t\tROUND256_0_TO_15(h,a,b,c,d,e,f,g);\n\t\tROUND256_0_TO_15(g,h,a,b,c,d,e,f);\n\t\tROUND256_0_TO_15(f,g,h,a,b,c,d,e);\n\t\tROUND256_0_TO_15(e,f,g,h,a,b,c,d);\n\t\tROUND256_0_TO_15(d,e,f,g,h,a,b,c);\n\t\tROUND256_0_TO_15(c,d,e,f,g,h,a,b);\n\t\tROUND256_0_TO_15(b,c,d,e,f,g,h,a);\n\t} while (j < 16);\n\n\t/* Now for the remaining rounds to 64: */\n\tdo {\n\t\tROUND256(a,b,c,d,e,f,g,h);\n\t\tROUND256(h,a,b,c,d,e,f,g);\n\t\tROUND256(g,h,a,b,c,d,e,f);\n\t\tROUND256(f,g,h,a,b,c,d,e);\n\t\tROUND256(e,f,g,h,a,b,c,d);\n\t\tROUND256(d,e,f,g,h,a,b,c);\n\t\tROUND256(c,d,e,f,g,h,a,b);\n\t\tROUND256(b,c,d,e,f,g,h,a);\n\t} while (j < 64);\n\n\t/* Compute the current intermediate hash value */\n\tstate_out[0] = state_in[0] + a;\n\tstate_out[1] = state_in[1] + b;\n\tstate_out[2] = state_in[2] + c;\n\tstate_out[3] = state_in[3] + d;\n\tstate_out[4] = state_in[4] + e;\n\tstate_out[5] = state_in[5] + f;\n\tstate_out[6] = state_in[6] + g;\n\tstate_out[7] = state_in[7] + h;\n\n\t/* Clean up */\n\ta = b = c = d = e = f = g = h = T1 = 0;\n}\n\n#else /* SHA2_UNROLL_TRANSFORM */\n\nvoid sha256_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) {\n\tsha2_word32\ta, b, c, d, e, f, g, h, s0, s1;\n\tsha2_word32\tT1, T2, W256[16];\n\tint\t\tj;\n\n\t/* Initialize registers with the prev. intermediate value */\n\ta = state_in[0];\n\tb = state_in[1];\n\tc = state_in[2];\n\td = state_in[3];\n\te = state_in[4];\n\tf = state_in[5];\n\tg = state_in[6];\n\th = state_in[7];\n\n\tj = 0;\n\tdo {\n\t\t/* Apply the SHA-256 compression function to update a..h with copy */\n\t\tT1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);\n\t\tT2 = Sigma0_256(a) + Maj(a, b, c);\n\t\th = g;\n\t\tg = f;\n\t\tf = e;\n\t\te = d + T1;\n\t\td = c;\n\t\tc = b;\n\t\tb = a;\n\t\ta = T1 + T2;\n\n\t\tj++;\n\t} while (j < 16);\n\n\tdo {\n\t\t/* Part of the message block expansion: */\n\t\ts0 = W256[(j+1)&0x0f];\n\t\ts0 = sigma0_256(s0);\n\t\ts1 = W256[(j+14)&0x0f];\t\n\t\ts1 = sigma1_256(s1);\n\n\t\t/* Apply the SHA-256 compression function to update a..h */\n\t\tT1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + \n\t\t     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);\n\t\tT2 = Sigma0_256(a) + Maj(a, b, c);\n\t\th = g;\n\t\tg = f;\n\t\tf = e;\n\t\te = d + T1;\n\t\td = c;\n\t\tc = b;\n\t\tb = a;\n\t\ta = T1 + T2;\n\n\t\tj++;\n\t} while (j < 64);\n\n\t/* Compute the current intermediate hash value */\n\tstate_out[0] = state_in[0] + a;\n\tstate_out[1] = state_in[1] + b;\n\tstate_out[2] = state_in[2] + c;\n\tstate_out[3] = state_in[3] + d;\n\tstate_out[4] = state_in[4] + e;\n\tstate_out[5] = state_in[5] + f;\n\tstate_out[6] = state_in[6] + g;\n\tstate_out[7] = state_in[7] + h;\n\n\t/* Clean up */\n\ta = b = c = d = e = f = g = h = T1 = T2 = 0;\n}\n\n#endif /* SHA2_UNROLL_TRANSFORM */\n\nvoid sha256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {\n\tunsigned int\tfreespace, usedspace;\n\n\tif (len == 0) {\n\t\t/* Calling with no data is valid - we do nothing */\n\t\treturn;\n\t}\n\n\tusedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;\n\tif (usedspace > 0) {\n\t\t/* Calculate how much free space is available in the buffer */\n\t\tfreespace = SHA256_BLOCK_LENGTH - usedspace;\n\n\t\tif (len >= freespace) {\n\t\t\t/* Fill the buffer completely and process it */\n\t\t\tMEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, freespace);\n\t\t\tcontext->bitcount += freespace << 3;\n\t\t\tlen -= freespace;\n\t\t\tdata += freespace;\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t\t/* Convert TO host byte order */\n\t\t\tfor (int j = 0; j < 16; j++) {\n\t\t\t\tREVERSE32(context->buffer[j],context->buffer[j]);\n\t\t\t}\n#endif\n\t\t\tsha256_Transform(context->state, context->buffer, context->state);\n\t\t} else {\n\t\t\t/* The buffer is not yet full */\n\t\t\tMEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, len);\n\t\t\tcontext->bitcount += len << 3;\n\t\t\t/* Clean up: */\n\t\t\tusedspace = freespace = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\twhile (len >= SHA256_BLOCK_LENGTH) {\n\t\t/* Process as many complete blocks as we can */\n\t\tMEMCPY_BCOPY(context->buffer, data, SHA256_BLOCK_LENGTH);\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t/* Convert TO host byte order */\n\t\tfor (int j = 0; j < 16; j++) {\n\t\t\tREVERSE32(context->buffer[j],context->buffer[j]);\n\t\t}\n#endif\n\t\tsha256_Transform(context->state, context->buffer, context->state);\n\t\tcontext->bitcount += SHA256_BLOCK_LENGTH << 3;\n\t\tlen -= SHA256_BLOCK_LENGTH;\n\t\tdata += SHA256_BLOCK_LENGTH;\n\t}\n\tif (len > 0) {\n\t\t/* There's left-overs, so save 'em */\n\t\tMEMCPY_BCOPY(context->buffer, data, len);\n\t\tcontext->bitcount += len << 3;\n\t}\n\t/* Clean up: */\n\tusedspace = freespace = 0;\n}\n\nvoid sha256_Final(SHA256_CTX* context, uint8_t digest[SHA256_DIGEST_LENGTH]) {\n\tunsigned int\tusedspace;\n\n\t/* If no digest buffer is passed, we don't bother doing this: */\n\tif (digest != (sha2_byte*)0) {\n\t\tusedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;\n\t\t/* Begin padding with a 1 bit: */\n\t\t((uint8_t*)context->buffer)[usedspace++] = 0x80;\n\t\t\n\t\tif (usedspace > SHA256_SHORT_BLOCK_LENGTH) {\n\t\t\tmemzero(((uint8_t*)context->buffer) + usedspace, SHA256_BLOCK_LENGTH - usedspace);\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t\t/* Convert TO host byte order */\n\t\t\tfor (int j = 0; j < 16; j++) {\n\t\t\t\tREVERSE32(context->buffer[j],context->buffer[j]);\n\t\t\t}\n#endif\n\t\t\t/* Do second-to-last transform: */\n\t\t\tsha256_Transform(context->state, context->buffer, context->state);\n\t\t\t\n\t\t\t/* And prepare the last transform: */\n\t\t\tusedspace = 0;\n\t\t}\n\t\t/* Set-up for the last transform: */\n\t\tmemzero(((uint8_t*)context->buffer) + usedspace, SHA256_SHORT_BLOCK_LENGTH - usedspace);\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t/* Convert TO host byte order */\n\t\tfor (int j = 0; j < 14; j++) {\n\t\t\tREVERSE32(context->buffer[j],context->buffer[j]);\n\t\t}\n#endif\n\t\t/* Set the bit count: */\n\t\tcontext->buffer[14] = context->bitcount >> 32;\n\t\tcontext->buffer[15] = context->bitcount & 0xffffffff;\n\n\t\t/* Final transform: */\n\t\tsha256_Transform(context->state, context->buffer, context->state);\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t/* Convert FROM host byte order */\n\t\tfor (int j = 0; j < 8; j++) {\n\t\t\tREVERSE32(context->state[j],context->state[j]);\n\t\t}\n#endif\n\t\tMEMCPY_BCOPY(digest, context->state, SHA256_DIGEST_LENGTH);\n\t}\n\n\t/* Clean up state data: */\n\tmemzero(context, sizeof(SHA256_CTX));\n\tusedspace = 0;\n}\n\nchar* sha256_End(SHA256_CTX* context, char buffer[SHA256_DIGEST_STRING_LENGTH]) {\n\tsha2_byte\tdigest[SHA256_DIGEST_LENGTH], *d = digest;\n\tint\t\ti;\n\n\tif (buffer != (char*)0) {\n\t\tsha256_Final(context, digest);\n\n\t\tfor (i = 0; i < SHA256_DIGEST_LENGTH; i++) {\n\t\t\t*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];\n\t\t\t*buffer++ = sha2_hex_digits[*d & 0x0f];\n\t\t\td++;\n\t\t}\n\t\t*buffer = (char)0;\n\t} else {\n\t\tmemzero(context, sizeof(SHA256_CTX));\n\t}\n\tmemzero(digest, SHA256_DIGEST_LENGTH);\n\treturn buffer;\n}\n\nvoid sha256_Raw(const sha2_byte* data, size_t len, uint8_t digest[SHA256_DIGEST_LENGTH]) {\n\tSHA256_CTX\tcontext;\n\tsha256_Init(&context);\n\tsha256_Update(&context, data, len);\n\tsha256_Final(&context, digest);\n}\n\nchar* sha256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {\n\tSHA256_CTX\tcontext;\n\n\tsha256_Init(&context);\n\tsha256_Update(&context, data, len);\n\treturn sha256_End(&context, digest);\n}\n\n\n/*** SHA-512: *********************************************************/\nvoid sha512_Init(SHA512_CTX* context) {\n\tif (context == (SHA512_CTX*)0) {\n\t\treturn;\n\t}\n\tMEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);\n\tmemzero(context->buffer, SHA512_BLOCK_LENGTH);\n\tcontext->bitcount[0] = context->bitcount[1] =  0;\n}\n\n#ifdef SHA2_UNROLL_TRANSFORM\n\n/* Unrolled SHA-512 round macros: */\n#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)\t\\\n\tT1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \\\n             K512[j] + (W512[j] = *data++); \\\n\t(d) += T1; \\\n\t(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \\\n\tj++\n\n#define ROUND512(a,b,c,d,e,f,g,h)\t\\\n\ts0 = W512[(j+1)&0x0f]; \\\n\ts0 = sigma0_512(s0); \\\n\ts1 = W512[(j+14)&0x0f]; \\\n\ts1 = sigma1_512(s1); \\\n\tT1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \\\n             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \\\n\t(d) += T1; \\\n\t(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \\\n\tj++\n\nvoid sha512_Transform(const sha2_word64* state_in, const sha2_word64* data, sha2_word64* state_out) {\n\tsha2_word64\ta, b, c, d, e, f, g, h, s0, s1;\n\tsha2_word64\tT1, W512[16];\n\tint\t\tj;\n\n\t/* Initialize registers with the prev. intermediate value */\n\ta = state_in[0];\n\tb = state_in[1];\n\tc = state_in[2];\n\td = state_in[3];\n\te = state_in[4];\n\tf = state_in[5];\n\tg = state_in[6];\n\th = state_in[7];\n\n\tj = 0;\n\tdo {\n\t\tROUND512_0_TO_15(a,b,c,d,e,f,g,h);\n\t\tROUND512_0_TO_15(h,a,b,c,d,e,f,g);\n\t\tROUND512_0_TO_15(g,h,a,b,c,d,e,f);\n\t\tROUND512_0_TO_15(f,g,h,a,b,c,d,e);\n\t\tROUND512_0_TO_15(e,f,g,h,a,b,c,d);\n\t\tROUND512_0_TO_15(d,e,f,g,h,a,b,c);\n\t\tROUND512_0_TO_15(c,d,e,f,g,h,a,b);\n\t\tROUND512_0_TO_15(b,c,d,e,f,g,h,a);\n\t} while (j < 16);\n\n\t/* Now for the remaining rounds up to 79: */\n\tdo {\n\t\tROUND512(a,b,c,d,e,f,g,h);\n\t\tROUND512(h,a,b,c,d,e,f,g);\n\t\tROUND512(g,h,a,b,c,d,e,f);\n\t\tROUND512(f,g,h,a,b,c,d,e);\n\t\tROUND512(e,f,g,h,a,b,c,d);\n\t\tROUND512(d,e,f,g,h,a,b,c);\n\t\tROUND512(c,d,e,f,g,h,a,b);\n\t\tROUND512(b,c,d,e,f,g,h,a);\n\t} while (j < 80);\n\n\t/* Compute the current intermediate hash value */\n\tstate_out[0] = state_in[0] + a;\n\tstate_out[1] = state_in[1] + b;\n\tstate_out[2] = state_in[2] + c;\n\tstate_out[3] = state_in[3] + d;\n\tstate_out[4] = state_in[4] + e;\n\tstate_out[5] = state_in[5] + f;\n\tstate_out[6] = state_in[6] + g;\n\tstate_out[7] = state_in[7] + h;\n\n\t/* Clean up */\n\ta = b = c = d = e = f = g = h = T1 = 0;\n}\n\n#else /* SHA2_UNROLL_TRANSFORM */\n\nvoid sha512_Transform(const sha2_word64* state_in, const sha2_word64* data, sha2_word64* state_out) {\n\tsha2_word64\ta, b, c, d, e, f, g, h, s0, s1;\n\tsha2_word64\tT1, T2, W512[16];\n\tint\t\tj;\n\n\t/* Initialize registers with the prev. intermediate value */\n\ta = state_in[0];\n\tb = state_in[1];\n\tc = state_in[2];\n\td = state_in[3];\n\te = state_in[4];\n\tf = state_in[5];\n\tg = state_in[6];\n\th = state_in[7];\n\n\tj = 0;\n\tdo {\n\t\t/* Apply the SHA-512 compression function to update a..h with copy */\n\t\tT1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);\n\t\tT2 = Sigma0_512(a) + Maj(a, b, c);\n\t\th = g;\n\t\tg = f;\n\t\tf = e;\n\t\te = d + T1;\n\t\td = c;\n\t\tc = b;\n\t\tb = a;\n\t\ta = T1 + T2;\n\n\t\tj++;\n\t} while (j < 16);\n\n\tdo {\n\t\t/* Part of the message block expansion: */\n\t\ts0 = W512[(j+1)&0x0f];\n\t\ts0 = sigma0_512(s0);\n\t\ts1 = W512[(j+14)&0x0f];\n\t\ts1 =  sigma1_512(s1);\n\n\t\t/* Apply the SHA-512 compression function to update a..h */\n\t\tT1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +\n\t\t     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);\n\t\tT2 = Sigma0_512(a) + Maj(a, b, c);\n\t\th = g;\n\t\tg = f;\n\t\tf = e;\n\t\te = d + T1;\n\t\td = c;\n\t\tc = b;\n\t\tb = a;\n\t\ta = T1 + T2;\n\n\t\tj++;\n\t} while (j < 80);\n\n\t/* Compute the current intermediate hash value */\n\tstate_out[0] = state_in[0] + a;\n\tstate_out[1] = state_in[1] + b;\n\tstate_out[2] = state_in[2] + c;\n\tstate_out[3] = state_in[3] + d;\n\tstate_out[4] = state_in[4] + e;\n\tstate_out[5] = state_in[5] + f;\n\tstate_out[6] = state_in[6] + g;\n\tstate_out[7] = state_in[7] + h;\n\n\t/* Clean up */\n\ta = b = c = d = e = f = g = h = T1 = T2 = 0;\n}\n\n#endif /* SHA2_UNROLL_TRANSFORM */\n\nvoid sha512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {\n\tunsigned int\tfreespace, usedspace;\n\n\tif (len == 0) {\n\t\t/* Calling with no data is valid - we do nothing */\n\t\treturn;\n\t}\n\n\tusedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;\n\tif (usedspace > 0) {\n\t\t/* Calculate how much free space is available in the buffer */\n\t\tfreespace = SHA512_BLOCK_LENGTH - usedspace;\n\n\t\tif (len >= freespace) {\n\t\t\t/* Fill the buffer completely and process it */\n\t\t\tMEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, freespace);\n\t\t\tADDINC128(context->bitcount, freespace << 3);\n\t\t\tlen -= freespace;\n\t\t\tdata += freespace;\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t\t/* Convert TO host byte order */\n\t\t\tfor (int j = 0; j < 16; j++) {\n\t\t\t\tREVERSE64(context->buffer[j],context->buffer[j]);\n\t\t\t}\n#endif\n\t\t\tsha512_Transform(context->state, context->buffer, context->state);\n\t\t} else {\n\t\t\t/* The buffer is not yet full */\n\t\t\tMEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, len);\n\t\t\tADDINC128(context->bitcount, len << 3);\n\t\t\t/* Clean up: */\n\t\t\tusedspace = freespace = 0;\n\t\t\treturn;\n\t\t}\n\t}\n\twhile (len >= SHA512_BLOCK_LENGTH) {\n\t\t/* Process as many complete blocks as we can */\n\t\tMEMCPY_BCOPY(context->buffer, data, SHA512_BLOCK_LENGTH);\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t/* Convert TO host byte order */\n\t\tfor (int j = 0; j < 16; j++) {\n\t\t\tREVERSE64(context->buffer[j],context->buffer[j]);\n\t\t}\n#endif\n\t\tsha512_Transform(context->state, context->buffer, context->state);\n\t\tADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);\n\t\tlen -= SHA512_BLOCK_LENGTH;\n\t\tdata += SHA512_BLOCK_LENGTH;\n\t}\n\tif (len > 0) {\n\t\t/* There's left-overs, so save 'em */\n\t\tMEMCPY_BCOPY(context->buffer, data, len);\n\t\tADDINC128(context->bitcount, len << 3);\n\t}\n\t/* Clean up: */\n\tusedspace = freespace = 0;\n}\n\nstatic void sha512_Last(SHA512_CTX* context) {\n\tunsigned int\tusedspace;\n\n\tusedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;\n\t/* Begin padding with a 1 bit: */\n\t((uint8_t*)context->buffer)[usedspace++] = 0x80;\n\t\n\tif (usedspace > SHA512_SHORT_BLOCK_LENGTH) {\n\t\tmemzero(((uint8_t*)context->buffer) + usedspace, SHA512_BLOCK_LENGTH - usedspace);\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t/* Convert TO host byte order */\n\t\tfor (int j = 0; j < 16; j++) {\n\t\t\tREVERSE64(context->buffer[j],context->buffer[j]);\n\t\t}\n#endif\n\t\t/* Do second-to-last transform: */\n\t\tsha512_Transform(context->state, context->buffer, context->state);\n\n\t\t/* And prepare the last transform: */\n\t\tusedspace = 0;\n\t}\n\t/* Set-up for the last transform: */\n\tmemzero(((uint8_t*)context->buffer) + usedspace, SHA512_SHORT_BLOCK_LENGTH - usedspace);\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t/* Convert TO host byte order */\n\tfor (int j = 0; j < 14; j++) {\n\t\tREVERSE64(context->buffer[j],context->buffer[j]);\n\t}\n#endif\n\t/* Store the length of input data (in bits): */\n\tcontext->buffer[14] = context->bitcount[1];\n\tcontext->buffer[15] = context->bitcount[0];\n\n\t/* Final transform: */\n\tsha512_Transform(context->state, context->buffer, context->state);\n}\n\nvoid sha512_Final(SHA512_CTX* context, uint8_t digest[SHA512_DIGEST_LENGTH]) {\n\t/* If no digest buffer is passed, we don't bother doing this: */\n\tif (digest != (sha2_byte*)0) {\n\t\tsha512_Last(context);\n\n\t\t/* Save the hash data for output: */\n#if BYTE_ORDER == LITTLE_ENDIAN\n\t\t/* Convert FROM host byte order */\n\t\tfor (int j = 0; j < 8; j++) {\n\t\t\tREVERSE64(context->state[j],context->state[j]);\n\t\t}\n#endif\n\t\tMEMCPY_BCOPY(digest, context->state, SHA512_DIGEST_LENGTH);\n\t}\n\n\t/* Zero out state data */\n\tmemzero(context, sizeof(SHA512_CTX));\n}\n\nchar* sha512_End(SHA512_CTX* context, char buffer[SHA512_DIGEST_STRING_LENGTH]) {\n\tsha2_byte\tdigest[SHA512_DIGEST_LENGTH], *d = digest;\n\tint\t\ti;\n\n\tif (buffer != (char*)0) {\n\t\tsha512_Final(context, digest);\n\n\t\tfor (i = 0; i < SHA512_DIGEST_LENGTH; i++) {\n\t\t\t*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];\n\t\t\t*buffer++ = sha2_hex_digits[*d & 0x0f];\n\t\t\td++;\n\t\t}\n\t\t*buffer = (char)0;\n\t} else {\n\t\tmemzero(context, sizeof(SHA512_CTX));\n\t}\n\tmemzero(digest, SHA512_DIGEST_LENGTH);\n\treturn buffer;\n}\n\nvoid sha512_Raw(const sha2_byte* data, size_t len, uint8_t digest[SHA512_DIGEST_LENGTH]) {\n\tSHA512_CTX\tcontext;\n\tsha512_Init(&context);\n\tsha512_Update(&context, data, len);\n\tsha512_Final(&context, digest);\n}\n\nchar* sha512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {\n\tSHA512_CTX\tcontext;\n\n\tsha512_Init(&context);\n\tsha512_Update(&context, data, len);\n\treturn sha512_End(&context, digest);\n}\n"
  },
  {
    "path": "src/utility/trezor/sha2.h",
    "content": "/**\n * Copyright (c) 2000-2001 Aaron D. Gifford\n * Copyright (c) 2013-2014 Pavol Rusnak\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n#ifndef __SHA2_H__\n#define __SHA2_H__\n\n#include <stdint.h>\n#include <stddef.h>\n\n#define SHA256_BLOCK_LENGTH\t\t64\n#define SHA256_DIGEST_LENGTH\t\t32\n#define SHA256_DIGEST_STRING_LENGTH\t(SHA256_DIGEST_LENGTH * 2 + 1)\n#define SHA512_BLOCK_LENGTH\t\t128\n#define SHA512_DIGEST_LENGTH\t\t64\n#define SHA512_DIGEST_STRING_LENGTH\t(SHA512_DIGEST_LENGTH * 2 + 1)\n\ntypedef struct _SHA256_CTX {\n\tuint32_t\tstate[8];\n\tuint64_t\tbitcount;\n\tuint32_t\tbuffer[SHA256_BLOCK_LENGTH/sizeof(uint32_t)];\n} SHA256_CTX;\ntypedef struct _SHA512_CTX {\n\tuint64_t\tstate[8];\n\tuint64_t\tbitcount[2];\n\tuint64_t\tbuffer[SHA512_BLOCK_LENGTH/sizeof(uint64_t)];\n} SHA512_CTX;\n\n/*** ENDIAN REVERSAL MACROS *******************************************/\n#ifndef LITTLE_ENDIAN\n#define LITTLE_ENDIAN 1234\n#define BIG_ENDIAN    4321\n#endif\n\n#ifndef BYTE_ORDER\n#define BYTE_ORDER LITTLE_ENDIAN\n#endif\n\n#if BYTE_ORDER == LITTLE_ENDIAN\n#define REVERSE32(w,x)\t{ \\\n\tuint32_t tmp = (w); \\\n\ttmp = (tmp >> 16) | (tmp << 16); \\\n\t(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \\\n}\n#define REVERSE64(w,x)\t{ \\\n\tuint64_t tmp = (w); \\\n\ttmp = (tmp >> 32) | (tmp << 32); \\\n\ttmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \\\n\t      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \\\n\t(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \\\n\t      ((tmp & 0x0000ffff0000ffffULL) << 16); \\\n}\n#endif /* BYTE_ORDER == LITTLE_ENDIAN */\n\nextern const uint32_t sha1_initial_hash_value[5];\nextern const uint32_t sha256_initial_hash_value[8];\nextern const uint64_t sha512_initial_hash_value[8];\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nvoid sha256_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);\nvoid sha256_Init(SHA256_CTX *);\nvoid sha256_Update(SHA256_CTX*, const uint8_t*, size_t);\nvoid sha256_Final(SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]);\nchar* sha256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);\nvoid sha256_Raw(const uint8_t*, size_t, uint8_t[SHA256_DIGEST_LENGTH]);\nchar* sha256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);\n\nvoid sha512_Transform(const uint64_t* state_in, const uint64_t* data, uint64_t* state_out);\nvoid sha512_Init(SHA512_CTX*);\nvoid sha512_Update(SHA512_CTX*, const uint8_t*, size_t);\nvoid sha512_Final(SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]);\nchar* sha512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);\nvoid sha512_Raw(const uint8_t*, size_t, uint8_t[SHA512_DIGEST_LENGTH]);\nchar* sha512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);\n\n#ifdef __cplusplus\n} /* end of extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "src/utility/trezor/sha3.c",
    "content": "/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).\n * based on the\n * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011\n * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche\n *\n * Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission is hereby granted,  free of charge,  to any person  obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction,  including without limitation\n * the rights to  use, copy, modify,  merge, publish, distribute, sublicense,\n * and/or sell copies  of  the Software,  and to permit  persons  to whom the\n * Software is furnished to do so.\n *\n * This program  is  distributed  in  the  hope  that it will be useful,  but\n * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  Use this program  at  your own risk!\n */\n\n#include <assert.h>\n#include <string.h>\n\n#include \"sha3.h\"\n#include \"memzero.h\"\n\n#define I64(x) x##LL\n#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))\n#define le2me_64(x) (x)\n#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))\n# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))\n\n/* constants */\n#define NumberOfRounds 24\n\n/* SHA3 (Keccak) constants for 24 rounds */\nstatic uint64_t keccak_round_constants[NumberOfRounds] = {\n\tI64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),\n\tI64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),\n\tI64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),\n\tI64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),\n\tI64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),\n\tI64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)\n};\n\n/* Initializing a sha3 context for given number of output bits */\nstatic void keccak_Init(SHA3_CTX *ctx, unsigned bits)\n{\n\t/* NB: The Keccak capacity parameter = bits * 2 */\n\tunsigned rate = 1600 - bits * 2;\n\n\tmemset(ctx, 0, sizeof(SHA3_CTX));\n\tctx->block_size = rate / 8;\n\tassert(rate <= 1600 && (rate % 64) == 0);\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid sha3_224_Init(SHA3_CTX *ctx)\n{\n\tkeccak_Init(ctx, 224);\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid sha3_256_Init(SHA3_CTX *ctx)\n{\n\tkeccak_Init(ctx, 256);\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid sha3_384_Init(SHA3_CTX *ctx)\n{\n\tkeccak_Init(ctx, 384);\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid sha3_512_Init(SHA3_CTX *ctx)\n{\n\tkeccak_Init(ctx, 512);\n}\n\n/* Keccak theta() transformation */\nstatic void keccak_theta(uint64_t *A)\n{\n\tunsigned int x;\n\tuint64_t C[5], D[5];\n\n\tfor (x = 0; x < 5; x++) {\n\t\tC[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];\n\t}\n\tD[0] = ROTL64(C[1], 1) ^ C[4];\n\tD[1] = ROTL64(C[2], 1) ^ C[0];\n\tD[2] = ROTL64(C[3], 1) ^ C[1];\n\tD[3] = ROTL64(C[4], 1) ^ C[2];\n\tD[4] = ROTL64(C[0], 1) ^ C[3];\n\n\tfor (x = 0; x < 5; x++) {\n\t\tA[x]      ^= D[x];\n\t\tA[x + 5]  ^= D[x];\n\t\tA[x + 10] ^= D[x];\n\t\tA[x + 15] ^= D[x];\n\t\tA[x + 20] ^= D[x];\n\t}\n}\n\n/* Keccak pi() transformation */\nstatic void keccak_pi(uint64_t *A)\n{\n\tuint64_t A1;\n\tA1 = A[1];\n\tA[ 1] = A[ 6];\n\tA[ 6] = A[ 9];\n\tA[ 9] = A[22];\n\tA[22] = A[14];\n\tA[14] = A[20];\n\tA[20] = A[ 2];\n\tA[ 2] = A[12];\n\tA[12] = A[13];\n\tA[13] = A[19];\n\tA[19] = A[23];\n\tA[23] = A[15];\n\tA[15] = A[ 4];\n\tA[ 4] = A[24];\n\tA[24] = A[21];\n\tA[21] = A[ 8];\n\tA[ 8] = A[16];\n\tA[16] = A[ 5];\n\tA[ 5] = A[ 3];\n\tA[ 3] = A[18];\n\tA[18] = A[17];\n\tA[17] = A[11];\n\tA[11] = A[ 7];\n\tA[ 7] = A[10];\n\tA[10] = A1;\n\t/* note: A[ 0] is left as is */\n}\n\n/* Keccak chi() transformation */\nstatic void keccak_chi(uint64_t *A)\n{\n\tint i;\n\tfor (i = 0; i < 25; i += 5) {\n\t\tuint64_t A0 = A[0 + i], A1 = A[1 + i];\n\t\tA[0 + i] ^= ~A1 & A[2 + i];\n\t\tA[1 + i] ^= ~A[2 + i] & A[3 + i];\n\t\tA[2 + i] ^= ~A[3 + i] & A[4 + i];\n\t\tA[3 + i] ^= ~A[4 + i] & A0;\n\t\tA[4 + i] ^= ~A0 & A1;\n\t}\n}\n\nstatic void sha3_permutation(uint64_t *state)\n{\n\tint round;\n\tfor (round = 0; round < NumberOfRounds; round++)\n\t{\n\t\tkeccak_theta(state);\n\n\t\t/* apply Keccak rho() transformation */\n\t\tstate[ 1] = ROTL64(state[ 1],  1);\n\t\tstate[ 2] = ROTL64(state[ 2], 62);\n\t\tstate[ 3] = ROTL64(state[ 3], 28);\n\t\tstate[ 4] = ROTL64(state[ 4], 27);\n\t\tstate[ 5] = ROTL64(state[ 5], 36);\n\t\tstate[ 6] = ROTL64(state[ 6], 44);\n\t\tstate[ 7] = ROTL64(state[ 7],  6);\n\t\tstate[ 8] = ROTL64(state[ 8], 55);\n\t\tstate[ 9] = ROTL64(state[ 9], 20);\n\t\tstate[10] = ROTL64(state[10],  3);\n\t\tstate[11] = ROTL64(state[11], 10);\n\t\tstate[12] = ROTL64(state[12], 43);\n\t\tstate[13] = ROTL64(state[13], 25);\n\t\tstate[14] = ROTL64(state[14], 39);\n\t\tstate[15] = ROTL64(state[15], 41);\n\t\tstate[16] = ROTL64(state[16], 45);\n\t\tstate[17] = ROTL64(state[17], 15);\n\t\tstate[18] = ROTL64(state[18], 21);\n\t\tstate[19] = ROTL64(state[19],  8);\n\t\tstate[20] = ROTL64(state[20], 18);\n\t\tstate[21] = ROTL64(state[21],  2);\n\t\tstate[22] = ROTL64(state[22], 61);\n\t\tstate[23] = ROTL64(state[23], 56);\n\t\tstate[24] = ROTL64(state[24], 14);\n\n\t\tkeccak_pi(state);\n\t\tkeccak_chi(state);\n\n\t\t/* apply iota(state, round) */\n\t\t*state ^= keccak_round_constants[round];\n\t}\n}\n\n/**\n * The core transformation. Process the specified block of data.\n *\n * @param hash the algorithm state\n * @param block the message block to process\n * @param block_size the size of the processed block in bytes\n */\nstatic void sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size)\n{\n\t/* expanded loop */\n\thash[ 0] ^= le2me_64(block[ 0]);\n\thash[ 1] ^= le2me_64(block[ 1]);\n\thash[ 2] ^= le2me_64(block[ 2]);\n\thash[ 3] ^= le2me_64(block[ 3]);\n\thash[ 4] ^= le2me_64(block[ 4]);\n\thash[ 5] ^= le2me_64(block[ 5]);\n\thash[ 6] ^= le2me_64(block[ 6]);\n\thash[ 7] ^= le2me_64(block[ 7]);\n\thash[ 8] ^= le2me_64(block[ 8]);\n\t/* if not sha3-512 */\n\tif (block_size > 72) {\n\t\thash[ 9] ^= le2me_64(block[ 9]);\n\t\thash[10] ^= le2me_64(block[10]);\n\t\thash[11] ^= le2me_64(block[11]);\n\t\thash[12] ^= le2me_64(block[12]);\n\t\t/* if not sha3-384 */\n\t\tif (block_size > 104) {\n\t\t\thash[13] ^= le2me_64(block[13]);\n\t\t\thash[14] ^= le2me_64(block[14]);\n\t\t\thash[15] ^= le2me_64(block[15]);\n\t\t\thash[16] ^= le2me_64(block[16]);\n\t\t\t/* if not sha3-256 */\n\t\t\tif (block_size > 136) {\n\t\t\t\thash[17] ^= le2me_64(block[17]);\n#ifdef FULL_SHA3_FAMILY_SUPPORT\n\t\t\t\t/* if not sha3-224 */\n\t\t\t\tif (block_size > 144) {\n\t\t\t\t\thash[18] ^= le2me_64(block[18]);\n\t\t\t\t\thash[19] ^= le2me_64(block[19]);\n\t\t\t\t\thash[20] ^= le2me_64(block[20]);\n\t\t\t\t\thash[21] ^= le2me_64(block[21]);\n\t\t\t\t\thash[22] ^= le2me_64(block[22]);\n\t\t\t\t\thash[23] ^= le2me_64(block[23]);\n\t\t\t\t\thash[24] ^= le2me_64(block[24]);\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t}\n\t}\n\t/* make a permutation of the hash */\n\tsha3_permutation(hash);\n}\n\n#define SHA3_FINALIZED 0x80000000\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid sha3_Update(SHA3_CTX *ctx, const unsigned char *msg, size_t size)\n{\n\tsize_t idx = (size_t)ctx->rest;\n\tsize_t block_size = (size_t)ctx->block_size;\n\n\tif (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */\n\tctx->rest = (unsigned)((ctx->rest + size) % block_size);\n\n\t/* fill partial block */\n\tif (idx) {\n\t\tsize_t left = block_size - idx;\n\t\tmemcpy((char*)ctx->message + idx, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\tsha3_process_block(ctx->hash, ctx->message, block_size);\n\t\tmsg  += left;\n\t\tsize -= left;\n\t}\n\twhile (size >= block_size) {\n\t\tuint64_t* aligned_message_block;\n\t\tif (IS_ALIGNED_64(msg)) {\n\t\t\t/* the most common case is processing of an already aligned message\n\t\t\twithout copying it */\n\t\t\taligned_message_block = (uint64_t*)(void*)msg;\n\t\t} else {\n\t\t\tmemcpy(ctx->message, msg, block_size);\n\t\t\taligned_message_block = ctx->message;\n\t\t}\n\n\t\tsha3_process_block(ctx->hash, aligned_message_block, block_size);\n\t\tmsg  += block_size;\n\t\tsize -= block_size;\n\t}\n\tif (size) {\n\t\tmemcpy(ctx->message, msg, size); /* save leftovers */\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid sha3_Final(SHA3_CTX *ctx, unsigned char* result)\n{\n\tsize_t digest_length = 100 - ctx->block_size / 2;\n\tconst size_t block_size = ctx->block_size;\n\n\tif (!(ctx->rest & SHA3_FINALIZED))\n\t{\n\t\t/* clear the rest of the data queue */\n\t\tmemset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);\n\t\t((char*)ctx->message)[ctx->rest] |= 0x06;\n\t\t((char*)ctx->message)[block_size - 1] |= 0x80;\n\n\t\t/* process final block */\n\t\tsha3_process_block(ctx->hash, ctx->message, block_size);\n\t\tctx->rest = SHA3_FINALIZED; /* mark context as finalized */\n\t}\n\n\tassert(block_size > digest_length);\n\tif (result) me64_to_le_str(result, ctx->hash, digest_length);\n\tmemzero(ctx, sizeof(SHA3_CTX));\n}\n\n#if USE_KECCAK\n/**\n* Store calculated hash into the given array.\n*\n* @param ctx the algorithm context containing current hashing state\n* @param result calculated hash in binary form\n*/\nvoid keccak_Final(SHA3_CTX *ctx, unsigned char* result)\n{\n\tsize_t digest_length = 100 - ctx->block_size / 2;\n\tconst size_t block_size = ctx->block_size;\n\n\tif (!(ctx->rest & SHA3_FINALIZED))\n\t{\n\t\t/* clear the rest of the data queue */\n\t\tmemset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);\n\t\t((char*)ctx->message)[ctx->rest] |= 0x01;\n\t\t((char*)ctx->message)[block_size - 1] |= 0x80;\n\n\t\t/* process final block */\n\t\tsha3_process_block(ctx->hash, ctx->message, block_size);\n\t\tctx->rest = SHA3_FINALIZED; /* mark context as finalized */\n\t}\n\n\tassert(block_size > digest_length);\n\tif (result) me64_to_le_str(result, ctx->hash, digest_length);\n\tmemzero(ctx, sizeof(SHA3_CTX));\n}\n\nvoid keccak_256(const unsigned char* data, size_t len, unsigned char* digest)\n{\n\tSHA3_CTX ctx;\n\tkeccak_256_Init(&ctx);\n\tkeccak_Update(&ctx, data, len);\n\tkeccak_Final(&ctx, digest);\n}\n\nvoid keccak_512(const unsigned char* data, size_t len, unsigned char* digest)\n{\n\tSHA3_CTX ctx;\n\tkeccak_512_Init(&ctx);\n\tkeccak_Update(&ctx, data, len);\n\tkeccak_Final(&ctx, digest);\n}\n#endif /* USE_KECCAK */\n\nvoid sha3_256(const unsigned char* data, size_t len, unsigned char* digest)\n{\n\tSHA3_CTX ctx;\n\tsha3_256_Init(&ctx);\n\tsha3_Update(&ctx, data, len);\n\tsha3_Final(&ctx, digest);\n}\n\nvoid sha3_512(const unsigned char* data, size_t len, unsigned char* digest)\n{\n\tSHA3_CTX ctx;\n\tsha3_512_Init(&ctx);\n\tsha3_Update(&ctx, data, len);\n\tsha3_Final(&ctx, digest);\n}\n"
  },
  {
    "path": "src/utility/trezor/sha3.h",
    "content": "/* sha3.h - an implementation of Secure Hash Algorithm 3 (Keccak).\n * based on the\n * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011\n * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche\n *\n * Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission is hereby granted,  free of charge,  to any person  obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction,  including without limitation\n * the rights to  use, copy, modify,  merge, publish, distribute, sublicense,\n * and/or sell copies  of  the Software,  and to permit  persons  to whom the\n * Software is furnished to do so.\n *\n * This program  is  distributed  in  the  hope  that it will be useful,  but\n * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n * or FITNESS FOR A PARTICULAR PURPOSE.  Use this program  at  your own risk!\n */\n\n#ifndef __SHA3_H__\n#define __SHA3_H__\n\n#include <stdint.h>\n#include \"options.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define sha3_224_hash_size  28\n#define sha3_256_hash_size  32\n#define sha3_384_hash_size  48\n#define sha3_512_hash_size  64\n#define sha3_max_permutation_size 25\n#define sha3_max_rate_in_qwords 24\n\n#define SHA3_224_BLOCK_LENGTH   144\n#define SHA3_256_BLOCK_LENGTH   136\n#define SHA3_384_BLOCK_LENGTH   104\n#define SHA3_512_BLOCK_LENGTH   72\n\n#define SHA3_224_DIGEST_LENGTH  sha3_224_hash_size\n#define SHA3_256_DIGEST_LENGTH  sha3_256_hash_size\n#define SHA3_384_DIGEST_LENGTH  sha3_384_hash_size\n#define SHA3_512_DIGEST_LENGTH  sha3_512_hash_size\n\n/**\n * SHA3 Algorithm context.\n */\ntypedef struct SHA3_CTX\n{\n\t/* 1600 bits algorithm hashing state */\n\tuint64_t hash[sha3_max_permutation_size];\n\t/* 1536-bit buffer for leftovers */\n\tuint64_t message[sha3_max_rate_in_qwords];\n\t/* count of bytes in the message[] buffer */\n\tunsigned rest;\n\t/* size of a message block processed at once */\n\tunsigned block_size;\n} SHA3_CTX;\n\n/* methods for calculating the hash function */\n\nvoid sha3_224_Init(SHA3_CTX *ctx);\nvoid sha3_256_Init(SHA3_CTX *ctx);\nvoid sha3_384_Init(SHA3_CTX *ctx);\nvoid sha3_512_Init(SHA3_CTX *ctx);\nvoid sha3_Update(SHA3_CTX *ctx, const unsigned char* msg, size_t size);\nvoid sha3_Final(SHA3_CTX *ctx, unsigned char* result);\n\n#if USE_KECCAK\n#define keccak_224_Init sha3_224_Init\n#define keccak_256_Init sha3_256_Init\n#define keccak_384_Init sha3_384_Init\n#define keccak_512_Init sha3_512_Init\n#define keccak_Update sha3_Update\nvoid keccak_Final(SHA3_CTX *ctx, unsigned char* result);\nvoid keccak_256(const unsigned char* data, size_t len, unsigned char* digest);\nvoid keccak_512(const unsigned char* data, size_t len, unsigned char* digest);\n#endif\n\nvoid sha3_256(const unsigned char* data, size_t len, unsigned char* digest);\nvoid sha3_512(const unsigned char* data, size_t len, unsigned char* digest);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* __SHA3_H__ */\n"
  },
  {
    "path": "tests/Makefile",
    "content": "# Paths\nBUILD_DIR = build\nSRC_DIR = .\n# uBitcoin library\nLIB_DIR = ../src\n\n# Tools\nifeq ($(OS),Windows_NT)\nTOOLCHAIN_PREFIX ?= x86_64-w64-mingw32-\nMKDIR_P = mkdir\nRM_R = rmdir /s /q\nelse\nTOOLCHAIN_PREFIX ?= \nMKDIR_P = mkdir -p\nRM_R = rm -r\nendif\n\n# compilers\nCC := $(TOOLCHAIN_PREFIX)gcc\nCXX := $(TOOLCHAIN_PREFIX)g++\n\n# uBitcoin sources\nCXX_SOURCES += $(wildcard $(LIB_DIR)/*.cpp)\nC_SOURCES += $(wildcard $(LIB_DIR)/utility/trezor/*.c) \\\n\t\t\t$(wildcard $(LIB_DIR)/utility/*.c) \\\n\t\t\t$(wildcard $(LIB_DIR)/*.c) \\\n\t\t\t$(wildcard $(SRC_DIR)/*.c)\n\n# include lib path, don't use mbed or arduino config (-DUSE_STDONLY)\nCFLAGS = -I$(LIB_DIR) -g\nCPPFLAGS = -I$(LIB_DIR) -DUSE_STDONLY -DUBTC_TEST -g\n\nOBJS = $(patsubst $(SRC_DIR)/%, $(BUILD_DIR)/src/%.o, \\\n\t\t$(patsubst $(LIB_DIR)/%, $(BUILD_DIR)/lib/%.o, \\\n\t\t$(C_SOURCES) $(CXX_SOURCES)))\n\nvpath %.cpp $(SRC_DIR)\nvpath %.cpp $(LIB_DIR)\nvpath %.c $(SRC_DIR)\nvpath %.c $(LIB_DIR)\n\nTESTS=$(wildcard $(SRC_DIR)/*.cpp)\nTESTOBJS=$(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/test/%.cpp.o, $(TESTS))\nTESTBINS=$(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/%.test, $(TESTS))\n\n\n.PHONY: clean all run\n\nall: $(TESTBINS)\n\nrun: $(TESTBINS)\n\tfor test in $(TESTBINS); do echo $$test; ./$$test ; done\n\n# keep object files\n.SECONDARY: $(OBJS) $(TESTOBJS)\n\n# lib c sources\n$(BUILD_DIR)/lib/%.c.o: %.c\n\t$(MKDIR_P) $(dir $@)\n\t$(CC) -c $(CFLAGS) $< -o $@\n\n# lib cpp sources\n$(BUILD_DIR)/lib/%.cpp.o: %.cpp\n\t$(MKDIR_P) $(dir $@)\n\t$(CXX) -c $(CPPFLAGS) $< -o $@\n\n# lib c sources\n$(BUILD_DIR)/src/%.c.o: %.c\n\t$(MKDIR_P) $(dir $@)\n\t$(CC) -c $(CFLAGS) $< -o $@\n\n# test cpp sources\n$(BUILD_DIR)/test/%.cpp.o: %.cpp\n\t$(MKDIR_P) $(dir $@)\n\t$(CXX) -c $(CPPFLAGS) $< -o $@\n\n$(BUILD_DIR)/%.test: $(BUILD_DIR)/test/%.cpp.o $(OBJS)\n\t$(CXX) $< $(OBJS) $(CPPFLAGS) -o $@\n\nclean:\n\t$(RM_R) $(BUILD_DIR)\n"
  },
  {
    "path": "tests/minunit.h",
    "content": "/*\n * Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com\n * \n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n#ifndef MINUNIT_MINUNIT_H\n#define MINUNIT_MINUNIT_H\n\n#ifdef __cplusplus\n\textern \"C\" {\n#endif\n\n#if defined(_WIN32)\n#include <Windows.h>\n#if defined(_MSC_VER) && _MSC_VER < 1900\n  #define snprintf _snprintf\n  #define __func__ __FUNCTION__\n#endif\n\n#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))\n\n/* Change POSIX C SOURCE version for pure c99 compilers */\n#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L\n#undef _POSIX_C_SOURCE\n#define _POSIX_C_SOURCE 200112L\n#endif\n\n#include <unistd.h>\t/* POSIX flags */\n#include <time.h>\t/* clock_gettime(), time() */\n#include <sys/time.h>\t/* gethrtime(), gettimeofday() */\n#include <sys/resource.h>\n#include <sys/times.h>\n#include <string.h>\n\n#if defined(__MACH__) && defined(__APPLE__)\n#include <mach/mach.h>\n#include <mach/mach_time.h>\n#endif\n\n#if __GNUC__ >= 5 && !defined(__STDC_VERSION__)\n#define __func__ __extension__ __FUNCTION__\n#endif\n\n#else\n#error \"Unable to define timers for an unknown OS.\"\n#endif\n\n#include <stdio.h>\n#include <math.h>\n\n/*  Maximum length of last message */\n#define MINUNIT_MESSAGE_LEN 1024\n/*  Accuracy with which floats are compared */\n#define MINUNIT_EPSILON 1E-12\n\n/*  Misc. counters */\nstatic int minunit_run = 0;\nstatic int minunit_assert = 0;\nstatic int minunit_fail = 0;\nstatic int minunit_status = 0;\n\n/*  Timers */\nstatic double minunit_real_timer = 0;\nstatic double minunit_proc_timer = 0;\n\n/*  Last message */\nstatic char minunit_last_message[MINUNIT_MESSAGE_LEN];\n\n/*  Test setup and teardown function pointers */\nstatic void (*minunit_setup)(void) = NULL;\nstatic void (*minunit_teardown)(void) = NULL;\n\n/*  Definitions */\n#define MU_TEST(method_name) static void method_name(void)\n#define MU_TEST_SUITE(suite_name) static void suite_name(void)\n\n#define MU__SAFE_BLOCK(block) do {\\\n\tblock\\\n} while(0)\n\n/*  Run test suite and unset setup and teardown functions */\n#define MU_RUN_SUITE(suite_name) MU__SAFE_BLOCK(\\\n\tsuite_name();\\\n\tminunit_setup = NULL;\\\n\tminunit_teardown = NULL;\\\n)\n\n/*  Configure setup and teardown functions */\n#define MU_SUITE_CONFIGURE(setup_fun, teardown_fun) MU__SAFE_BLOCK(\\\n\tminunit_setup = setup_fun;\\\n\tminunit_teardown = teardown_fun;\\\n)\n\n/*  Test runner */\n#define MU_RUN_TEST(test) MU__SAFE_BLOCK(\\\n\tif (minunit_real_timer==0 && minunit_proc_timer==0) {\\\n\t\tminunit_real_timer = mu_timer_real();\\\n\t\tminunit_proc_timer = mu_timer_cpu();\\\n\t}\\\n\tif (minunit_setup) (*minunit_setup)();\\\n\tminunit_status = 0;\\\n\ttest();\\\n\tminunit_run++;\\\n\tif (minunit_status) {\\\n\t\tminunit_fail++;\\\n\t\tprintf(\"F\");\\\n\t\tprintf(\"\\n%s\\n\", minunit_last_message);\\\n\t}\\\n\tfflush(stdout);\\\n\tif (minunit_teardown) (*minunit_teardown)();\\\n)\n\n/*  Report */\n#define MU_REPORT() MU__SAFE_BLOCK(\\\n\tdouble minunit_end_real_timer;\\\n\tdouble minunit_end_proc_timer;\\\n\tprintf(\"\\n\\n%d tests, %d assertions, %d failures\\n\", minunit_run, minunit_assert, minunit_fail);\\\n\tminunit_end_real_timer = mu_timer_real();\\\n\tminunit_end_proc_timer = mu_timer_cpu();\\\n\tprintf(\"\\nFinished in %.8f seconds (real) %.8f seconds (proc)\\n\\n\",\\\n\t\tminunit_end_real_timer - minunit_real_timer,\\\n\t\tminunit_end_proc_timer - minunit_proc_timer);\\\n)\n#define MU_EXIT_CODE minunit_fail\n\n/*  Assertions */\n#define mu_check(test) MU__SAFE_BLOCK(\\\n\tminunit_assert++;\\\n\tif (!(test)) {\\\n\t\tsnprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \"%s failed:\\n\\t%s:%d: %s\", __func__, __FILE__, __LINE__, #test);\\\n\t\tminunit_status = 1;\\\n\t\treturn;\\\n\t} else {\\\n\t\tprintf(\".\");\\\n\t}\\\n)\n\n#define mu_fail(message) MU__SAFE_BLOCK(\\\n\tminunit_assert++;\\\n\tsnprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \"%s failed:\\n\\t%s:%d: %s\", __func__, __FILE__, __LINE__, message);\\\n\tminunit_status = 1;\\\n\treturn;\\\n)\n\n#define mu_assert(test, message) MU__SAFE_BLOCK(\\\n\tminunit_assert++;\\\n\tif (!(test)) {\\\n\t\tsnprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \"%s failed:\\n\\t%s:%d: %s\", __func__, __FILE__, __LINE__, message);\\\n\t\tminunit_status = 1;\\\n\t\treturn;\\\n\t} else {\\\n\t\tprintf(\".\");\\\n\t}\\\n)\n\n#define mu_assert_int_eq(expected, result) MU__SAFE_BLOCK(\\\n\tint minunit_tmp_e;\\\n\tint minunit_tmp_r;\\\n\tminunit_assert++;\\\n\tminunit_tmp_e = (expected);\\\n\tminunit_tmp_r = (result);\\\n\tif (minunit_tmp_e != minunit_tmp_r) {\\\n\t\tsnprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \"%s failed:\\n\\t%s:%d: %d expected but was %d\", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\\\n\t\tminunit_status = 1;\\\n\t\treturn;\\\n\t} else {\\\n\t\tprintf(\".\");\\\n\t}\\\n)\n\n#define mu_assert_double_eq(expected, result) MU__SAFE_BLOCK(\\\n\tdouble minunit_tmp_e;\\\n\tdouble minunit_tmp_r;\\\n\tminunit_assert++;\\\n\tminunit_tmp_e = (expected);\\\n\tminunit_tmp_r = (result);\\\n\tif (fabs(minunit_tmp_e-minunit_tmp_r) > MINUNIT_EPSILON) {\\\n\t\tint minunit_significant_figures = 1 - log10(MINUNIT_EPSILON);\\\n\t\tsnprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \"%s failed:\\n\\t%s:%d: %.*g expected but was %.*g\", __func__, __FILE__, __LINE__, minunit_significant_figures, minunit_tmp_e, minunit_significant_figures, minunit_tmp_r);\\\n\t\tminunit_status = 1;\\\n\t\treturn;\\\n\t} else {\\\n\t\tprintf(\".\");\\\n\t}\\\n)\n\n#define mu_assert_string_eq(expected, result) MU__SAFE_BLOCK(\\\n\tconst char* minunit_tmp_e = expected;\\\n\tconst char* minunit_tmp_r = result;\\\n\tminunit_assert++;\\\n\tif (!minunit_tmp_e) {\\\n\t\tminunit_tmp_e = \"<null pointer>\";\\\n\t}\\\n\tif (!minunit_tmp_r) {\\\n\t\tminunit_tmp_r = \"<null pointer>\";\\\n\t}\\\n\tif(strcmp(minunit_tmp_e, minunit_tmp_r)) {\\\n\t\tsnprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, \"%s failed:\\n\\t%s:%d: '%s' expected but was '%s'\", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\\\n\t\tminunit_status = 1;\\\n\t\treturn;\\\n\t} else {\\\n\t\tprintf(\".\");\\\n\t}\\\n)\n\n/*\n * The following two functions were written by David Robert Nadeau\n * from http://NadeauSoftware.com/ and distributed under the\n * Creative Commons Attribution 3.0 Unported License\n */\n\n/**\n * Returns the real time, in seconds, or -1.0 if an error occurred.\n *\n * Time is measured since an arbitrary and OS-dependent start time.\n * The returned real time is only useful for computing an elapsed time\n * between two calls to this function.\n */\nstatic double mu_timer_real(void)\n{\n#if defined(_WIN32)\n\t/* Windows 2000 and later. ---------------------------------- */\n\tLARGE_INTEGER Time;\n\tLARGE_INTEGER Frequency;\n\t\n\tQueryPerformanceFrequency(&Frequency);\n\tQueryPerformanceCounter(&Time);\n\t\n\tTime.QuadPart *= 1000000;\n\tTime.QuadPart /= Frequency.QuadPart;\n\t\n\treturn (double)Time.QuadPart / 1000000.0;\n\n#elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))\n\t/* HP-UX, Solaris. ------------------------------------------ */\n\treturn (double)gethrtime( ) / 1000000000.0;\n\n#elif defined(__MACH__) && defined(__APPLE__)\n\t/* OSX. ----------------------------------------------------- */\n\tstatic double timeConvert = 0.0;\n\tif ( timeConvert == 0.0 )\n\t{\n\t\tmach_timebase_info_data_t timeBase;\n\t\t(void)mach_timebase_info( &timeBase );\n\t\ttimeConvert = (double)timeBase.numer /\n\t\t\t(double)timeBase.denom /\n\t\t\t1000000000.0;\n\t}\n\treturn (double)mach_absolute_time( ) * timeConvert;\n\n#elif defined(_POSIX_VERSION)\n\t/* POSIX. --------------------------------------------------- */\n\tstruct timeval tm;\n#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)\n\t{\n\t\tstruct timespec ts;\n#if defined(CLOCK_MONOTONIC_PRECISE)\n\t\t/* BSD. --------------------------------------------- */\n\t\tconst clockid_t id = CLOCK_MONOTONIC_PRECISE;\n#elif defined(CLOCK_MONOTONIC_RAW)\n\t\t/* Linux. ------------------------------------------- */\n\t\tconst clockid_t id = CLOCK_MONOTONIC_RAW;\n#elif defined(CLOCK_HIGHRES)\n\t\t/* Solaris. ----------------------------------------- */\n\t\tconst clockid_t id = CLOCK_HIGHRES;\n#elif defined(CLOCK_MONOTONIC)\n\t\t/* AIX, BSD, Linux, POSIX, Solaris. ----------------- */\n\t\tconst clockid_t id = CLOCK_MONOTONIC;\n#elif defined(CLOCK_REALTIME)\n\t\t/* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */\n\t\tconst clockid_t id = CLOCK_REALTIME;\n#else\n\t\tconst clockid_t id = (clockid_t)-1;\t/* Unknown. */\n#endif /* CLOCK_* */\n\t\tif ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )\n\t\t\treturn (double)ts.tv_sec +\n\t\t\t\t(double)ts.tv_nsec / 1000000000.0;\n\t\t/* Fall thru. */\n\t}\n#endif /* _POSIX_TIMERS */\n\n\t/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */\n\tgettimeofday( &tm, NULL );\n\treturn (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0;\n#else\n\treturn -1.0;\t\t/* Failed. */\n#endif\n}\n\n/**\n * Returns the amount of CPU time used by the current process,\n * in seconds, or -1.0 if an error occurred.\n */\nstatic double mu_timer_cpu(void)\n{\n#if defined(_WIN32)\n\t/* Windows -------------------------------------------------- */\n\tFILETIME createTime;\n\tFILETIME exitTime;\n\tFILETIME kernelTime;\n\tFILETIME userTime;\n\n\t/* This approach has a resolution of 1/64 second. Unfortunately, Windows' API does not offer better */\n\tif ( GetProcessTimes( GetCurrentProcess( ),\n\t\t&createTime, &exitTime, &kernelTime, &userTime ) != 0 )\n\t{\n\t\tULARGE_INTEGER userSystemTime;\n\t\tmemcpy(&userSystemTime, &userTime, sizeof(ULARGE_INTEGER));\n\t\treturn (double)userSystemTime.QuadPart / 10000000.0;\n\t}\n\n#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))\n\t/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */\n\n#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)\n\t/* Prefer high-res POSIX timers, when available. */\n\t{\n\t\tclockid_t id;\n\t\tstruct timespec ts;\n#if _POSIX_CPUTIME > 0\n\t\t/* Clock ids vary by OS.  Query the id, if possible. */\n\t\tif ( clock_getcpuclockid( 0, &id ) == -1 )\n#endif\n#if defined(CLOCK_PROCESS_CPUTIME_ID)\n\t\t\t/* Use known clock id for AIX, Linux, or Solaris. */\n\t\t\tid = CLOCK_PROCESS_CPUTIME_ID;\n#elif defined(CLOCK_VIRTUAL)\n\t\t\t/* Use known clock id for BSD or HP-UX. */\n\t\t\tid = CLOCK_VIRTUAL;\n#else\n\t\t\tid = (clockid_t)-1;\n#endif\n\t\tif ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )\n\t\t\treturn (double)ts.tv_sec +\n\t\t\t\t(double)ts.tv_nsec / 1000000000.0;\n\t}\n#endif\n\n#if defined(RUSAGE_SELF)\n\t{\n\t\tstruct rusage rusage;\n\t\tif ( getrusage( RUSAGE_SELF, &rusage ) != -1 )\n\t\t\treturn (double)rusage.ru_utime.tv_sec +\n\t\t\t\t(double)rusage.ru_utime.tv_usec / 1000000.0;\n\t}\n#endif\n\n#if defined(_SC_CLK_TCK)\n\t{\n\t\tconst double ticks = (double)sysconf( _SC_CLK_TCK );\n\t\tstruct tms tms;\n\t\tif ( times( &tms ) != (clock_t)-1 )\n\t\t\treturn (double)tms.tms_utime / ticks;\n\t}\n#endif\n\n#if defined(CLOCKS_PER_SEC)\n\t{\n\t\tclock_t cl = clock( );\n\t\tif ( cl != (clock_t)-1 )\n\t\t\treturn (double)cl / (double)CLOCKS_PER_SEC;\n\t}\n#endif\n\n#endif\n\n\treturn -1;\t\t/* Failed. */\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* MINUNIT_MINUNIT_H */\n"
  },
  {
    "path": "tests/sysrand.c",
    "content": "#ifdef UBTC_TEST // only compile with test flag\n\n#include <stdint.h>\n#include <stdlib.h>\n\n// use system random function\nuint32_t random32(void){\n    return (uint32_t)rand();\n}\n\n#endif // UBTC_TEST\n"
  },
  {
    "path": "tests/test_conversion.cpp",
    "content": "#ifdef UBTC_TEST // only compile with test flag\n\n#include \"minunit.h\"\n#include \"Conversion.h\" // to print byte arrays in hex format\n\nusing std::string;\n\nconst char message[] = \"Hello world!\"; // message to convert\nconst uint8_t * bytes = (const uint8_t *)message;\nconst char b58[] = \"2NEpo7TZRhna7vSvL\";\nconst char b58check[] = \"9wWTEnNTWna86WmtFaRbXa\";\nconst char b64[] = \"SGVsbG8gd29ybGQh\";\n\nuint8_t out[100];\nsize_t sz;\nstring s;\n\nMU_TEST(test_base58) {\n  s = toBase58(bytes, strlen(message));\n  mu_assert(strcmp(s.c_str(), b58) == 0, \"toBase58 conversion is invalid\");\n\n  sz = fromBase58(b58, out, sizeof(out));\n  mu_assert(sz == strlen(message), \"fromBase58 size is wrong\");\n  mu_assert(memcmp(out, bytes, sz) == 0, \"fromBase58 decoding is wrong\");\n\n  s = toBase58Check(bytes, strlen(message));\n  mu_assert(strcmp(s.c_str(), b58check) == 0, \"toBase58 conversion is invalid\");\n\n  sz = fromBase58Check(b58check, out, sizeof(out));\n  mu_assert(sz == strlen(message), \"fromBase58Check size is wrong\");\n  mu_assert(memcmp(out, bytes, sz) == 0, \"fromBase58Check decoding is wrong\");\n\n  sz = fromBase58(b58check, out, sizeof(out));\n  mu_assert(sz == (strlen(message)+4), \"fromBase58 size is wrong\");\n  mu_assert(memcmp(out, bytes, sz-4) == 0, \"fromBase58 decoding is wrong\");\n}\n\nMU_TEST(test_base64) {\n  s = toBase64(bytes, strlen(message));\n  mu_assert(strcmp(s.c_str(), b64) == 0, \"toBase64 conversion is invalid\");\n\n  sz = fromBase64(b64, out, sizeof(out));\n  mu_assert(sz == strlen(message), \"fromBase64 size is wrong\");\n  mu_assert(memcmp(out, bytes, sz) == 0, \"fromBase64 decoding is wrong\");\n\n  char *msgs[] = {\n    \"Man\", \"Ma\", \"M\", \"light w\", \"light wo\", \"light wor\", \"light work\", \"light work.\",\n    \"\\x6c\\x68\\x40\\xa2\\xc4\\xbe\\xfe\\xa7\\x85\\x30\\x20\", NULL\n  };\n  char *b64msgs[] = {\n    \"TWFu\", \"TWE=\", \"TQ==\", \"bGlnaHQgdw==\", \"bGlnaHQgd28=\", \"bGlnaHQgd29y\", \"bGlnaHQgd29yaw==\", \"bGlnaHQgd29yay4=\",\n    \"bGhAosS+/qeFMCA=\", NULL\n  };\n  char *b64msgs_url[] = {\n    \"TWFu\", \"TWE\", \"TQ\", \"bGlnaHQgdw\", \"bGlnaHQgd28\", \"bGlnaHQgd29y\", \"bGlnaHQgd29yaw\", \"bGlnaHQgd29yay4\",\n    \"bGhAosS-_qeFMCA\", NULL\n  };\n  size_t i = 0;\n  while(msgs[i] != NULL){\n    char *msg = msgs[i];\n    s = toBase64((uint8_t*)msg, strlen(msg));\n    mu_assert(strcmp(s.c_str(), b64msgs[i]) == 0, \"toBase64 conversion is invalid\");\n\n    sz = fromBase64(b64msgs[i], out, sizeof(out));\n    mu_assert(sz == strlen(msg), \"fromBase64 size is wrong\");\n    mu_assert(memcmp(out, msg, sz) == 0, \"fromBase64 decoding is wrong\");\n\n    s = toBase64((uint8_t*)msg, strlen(msg), BASE64_NOPADDING | BASE64_URLSAFE);\n    size_t l = toBase64Length((uint8_t*)msg, strlen(msg), BASE64_NOPADDING | BASE64_URLSAFE);\n    mu_assert(strcmp(s.c_str(), b64msgs_url[i]) == 0, \"toBase64 urlsafe conversion is invalid\");\n\n    sz = fromBase64(b64msgs_url[i], out, sizeof(out), BASE64_NOPADDING | BASE64_URLSAFE);\n    mu_assert(sz == strlen(msg), \"fromBase64 size is wrong\");\n    mu_assert(memcmp(out, msg, sz) == 0, \"fromBase64 urlsafe decoding is wrong\");\n\n    i++;\n  }\n}\n\nMU_TEST(test_nullptr) {\n  s = toBase64(NULL, strlen(message));\n  mu_assert(strcmp(s.c_str(), \"\") == 0, \"toBase64 doesn't handle nullptr properly\");\n\n  sz = fromBase64(b64, NULL, sizeof(out));\n  mu_assert(sz == 0, \"fromBase64 doesn't handle nullptr properly\");\n\n  s = toBase58(NULL, strlen(message));\n  mu_assert(strcmp(s.c_str(), \"\") == 0, \"toBase58 doesn't handle nullptr properly\");\n\n  sz = fromBase58(b58, NULL, sizeof(out));\n  mu_assert(sz == 0, \"fromBase58 doesn't handle nullptr properly\");\n\n  s = toBase58Check(NULL, strlen(message));\n  mu_assert(strcmp(s.c_str(), \"\") == 0, \"toBase58Check doesn't handle nullptr properly\");\n\n  sz = fromBase58Check(b58check, NULL, sizeof(out));\n  mu_assert(sz == 0, \"fromBase58Check doesn't handle nullptr properly\");\n}\n\nMU_TEST_SUITE(test_conversion) {\n  MU_RUN_TEST(test_base58);\n  MU_RUN_TEST(test_base64);\n  MU_RUN_TEST(test_nullptr);\n}\n\nint main(int argc, char *argv[]) {\n  MU_RUN_SUITE(test_conversion);\n  MU_REPORT();\n  return MU_EXIT_CODE;\n}\n\n#endif // UBTC_TEST\n"
  },
  {
    "path": "tests/test_hash.cpp",
    "content": "#ifdef UBTC_TEST // only compile with test flag\n\n#include \"minunit.h\"\n#include \"Hash.h\"  // all single-line hashing algorithms\n#include \"Conversion.h\" // to print byte arrays in hex format\n\nusing namespace std;\n\nchar message[] = \"Hello world!\"; // message to hash\n\nMU_TEST(test_sha256) {\n  uint8_t hash[32];\n  int hashLen = sha256(message, hash);\n  string hexresult = toHex(hash, hashLen);\n  char expected[] = \"c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a\";\n  mu_assert(strcmp(expected, hexresult.c_str()) == 0, \"sha256 with string is invalid\");\n\n  // using bytes\n  uint8_t hash2[32];\n  uint8_t *bytes = (uint8_t *)message;\n  size_t byteslen = strlen(message);\n  \n  sha256(bytes, byteslen, hash2);\n  mu_assert(memcmp(hash, hash2, sizeof(hash)) == 0, \"sha256 with bytes is invalid\");\n\n  // sending data in pieces\n  SHA256 h;\n  h.begin();\n  h.write(bytes, 5); // add first 5 bytes to hash\n  h.write(bytes+5, byteslen-5); // add the rest\n  h.end(hash2); // result will be stored in the hash array\n  mu_assert(memcmp(hash, hash2, sizeof(hash)) == 0, \"sha256 in pieces is invalid\");\n}\n\nMU_TEST(test_ripemd160) {\n  uint8_t hash[20];\n  int hashLen = rmd160(message, hash);\n  string hexresult = toHex(hash, hashLen);\n  mu_assert(strcmp(hexresult.c_str(), \"7f772647d88750add82d8e1a7a3e5c0902a346a3\") == 0, \"ripemd160 is wrong\");\n}\n\nMU_TEST(test_hash160) {\n  uint8_t hash[20];\n  int hashLen = hash160(message, hash);\n  string hexresult = toHex(hash, hashLen);\n  mu_assert(strcmp(hexresult.c_str(), \"621281c15fb62d5c6013ea29007491e8b174e1b9\") == 0, \"hash160 is wrong\");\n}\n\nMU_TEST(test_doublesha256) {\n  uint8_t hash[32];\n  int hashLen = doubleSha(message, hash);\n  string hexresult = toHex(hash, hashLen);\n  mu_assert(strcmp(hexresult.c_str(), \"7982970534e089b839957b7e174725ce1878731ed6d700766e59cb16f1c25e27\") == 0, \"double sha256 is wrong\");\n}\n\nMU_TEST(test_taggedhash) {\n  uint8_t hash[32];\n  int hashLen = tagged_hash(\"some tag\", message, hash);\n  string hexresult = toHex(hash, hashLen);\n  mu_assert(strcmp(hexresult.c_str(), \"5f03803bda8dc3b9ddc0e954d6dbb51543a3517bd84970e64a8825bcaddedbae\") == 0, \"tagged hash is wrong\");\n}\n\nMU_TEST(test_sha512) {\n  uint8_t hash[64];\n  int hashLen = sha512(message, hash);\n  string hexresult = toHex(hash, hashLen);\n  mu_assert(strcmp(hexresult.c_str(), \"f6cde2a0f819314cdde55fc227d8d7dae3d28cc556222a0a8ad66d91ccad4aad6094f517a2182360c9aacf6a3dc323162cb6fd8cdffedb0fe038f55e85ffb5b6\") == 0, \"sha512 is wrong\");\n}\n\nMU_TEST_SUITE(test_hash) {\n  MU_RUN_TEST(test_sha256);\n  MU_RUN_TEST(test_ripemd160);\n  MU_RUN_TEST(test_hash160);\n  MU_RUN_TEST(test_doublesha256);\n  MU_RUN_TEST(test_sha512);\n}\n\nint main(int argc, char *argv[]) {\n  MU_RUN_SUITE(test_hash);\n  MU_REPORT();\n  return MU_EXIT_CODE;\n}\n\n#endif // UBTC_TEST\n"
  },
  {
    "path": "tests/test_mnemonic.cpp",
    "content": "#ifdef UBTC_TEST // only compile with test flag\n\n#include \"minunit.h\"\n#include \"Bitcoin.h\"\n\nusing namespace std;\n\n#define MNEMONIC \"arch volcano urge cradle turn labor skin secret squeeze denial jacket vintage fix glad lemon\"\n#define PASSWORD \"my secret password\"\n\nMU_TEST(test_password) {\n  HDPrivateKey hd(MNEMONIC, PASSWORD);\n  mu_assert(bool(hd), \"hd wallet should be valid\");\n  mu_assert(strcmp(hd.xprv().c_str(), \"xprv9s21ZrQH143K3a5zf698hDA7tWk75bUs2aK5ZUzsSHPxk6MUv2NqUM8NwzFLKqeLeeaH3VGxTcLBgyE9vHYWVnY6JjkuCw9k4HpxHPnodhs\") == 0, \"Root xprv is invalid\");\n}\n\nMU_TEST_SUITE(test_mnemonic) {\n  MU_RUN_TEST(test_password);\n}\n\nint main(int argc, char *argv[]) {\n  MU_RUN_SUITE(test_mnemonic);\n  MU_REPORT();\n  return MU_EXIT_CODE;\n}\n\n#endif // UBTC_TEST\n"
  },
  {
    "path": "tests/test_schnorr.cpp",
    "content": "#ifdef UBTC_TEST // only compile with test flag\n\n#include \"minunit.h\"\n#include \"Bitcoin.h\"\n#include \"Hash.h\"\n#include \"Conversion.h\" // to print byte arrays in hex format\n\nusing namespace std;\n\nchar message[] = \"Hello world!\"; // message to hash\n\nMU_TEST(test_schnorrsign) {\n  uint8_t hash[32];\n  int hashLen = tagged_hash(\"some tag\", message, hash);\n  // check signing (it's also an odd public key)\n  PrivateKey pk(\"KxsLKrFM2X4kK4zkxGtmTaWv2tvyNLdZmuMWhni3DeKDcDFeS3DU\");\n  SchnorrSignature sig = pk.schnorr_sign(hash);\n  string hexsig = string(sig);\n  mu_assert(strcmp(hexsig.c_str(), \"49ece67cead2bd0ec6b926f376e0e17ebb27e744beadbdf4aeed67115470ae2e9ceb0c17f710c3c3c33480b55d8069b81a2894d09d3d759e3bea46f92cd1bd7f\") == 0, \"schnorr signature is wrong\");\n  // check verification\n  PublicKey pub = pk.publicKey();\n  mu_assert(pub.schnorr_verify(sig, hash) == true, \"schnorr verification failed\");\n  // check it also works with 02... key\n  PublicKey pub2;\n  uint8_t arr[32];\n  fromHex(\"6930f46dd0b16d866d59d1054aa63298b357499cd1862ef16f3f55f1cafceb82\", arr, 32);\n  pub2.from_x(arr, 32);\n  mu_assert(pub2.schnorr_verify(sig, hash) == true, \"schnorr verification failed\");\n}\n\n\nMU_TEST_SUITE(test_schnorr) {\n  MU_RUN_TEST(test_schnorrsign);\n}\n\nint main(int argc, char *argv[]) {\n  MU_RUN_SUITE(test_schnorr);\n  MU_REPORT();\n  return MU_EXIT_CODE;\n}\n\n#endif // UBTC_TEST\n"
  }
]