Initial commit
This commit is contained in:
		
						commit
						3a9c1dc4bf
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| build | ||||
| tags | ||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| [submodule "secp256k1"] | ||||
| 	path = secp256k1 | ||||
| 	url = https://github.com/bitcoin-core/secp256k1 | ||||
							
								
								
									
										24
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| This is free and unencumbered software released into the public domain. | ||||
| 
 | ||||
| Anyone is free to copy, modify, publish, use, compile, sell, or | ||||
| distribute this software, either in source code form or as a compiled | ||||
| binary, for any purpose, commercial or non-commercial, and by any | ||||
| means. | ||||
| 
 | ||||
| In jurisdictions that recognize copyright laws, the author or authors | ||||
| of this software dedicate any and all copyright interest in the | ||||
| software to the public domain. We make this dedication for the benefit | ||||
| of the public at large and to the detriment of our heirs and | ||||
| successors. We intend this dedication to be an overt act of | ||||
| relinquishment in perpetuity of all present and future rights to this | ||||
| software under copyright law. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
| IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||||
| OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||||
| ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||||
| OTHER DEALINGS IN THE SOFTWARE. | ||||
| 
 | ||||
| For more information, please refer to <http://unlicense.org> | ||||
							
								
								
									
										57
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| # Blockchain Tools - secp256k1 (bt\_secp256k1) | ||||
| 
 | ||||
| A code-generated single file header for bitcoin-core/secp256k1, an optimized | ||||
| C library for ECDSA signatures and secret/public key operations on curve | ||||
| secp256k1. | ||||
| 
 | ||||
| ## Using bt\_secp256k1 | ||||
| 
 | ||||
| The header files are generated from a metaprogram that is included in this | ||||
| repository. To use the library you only need 1 header file of which, 3 variants | ||||
| are provided, | ||||
| 
 | ||||
| - bt\_secp256k1\_i64.h (USE\_FORCE\_WIDEMUL\_INT64 is defined) | ||||
| - bt\_secp256k1\_i128.h (USE\_FORCE\_WIDEMUL\_IN128 is defined) | ||||
| - bt\_secp256k1\_i128\_x86\_64\_asm.h (USE\_FORCE\_WIDEMUL\_IN128 & USE\_ASM\_X86\_64 is defined) | ||||
| 
 | ||||
| Given the 3 variants, for optimal performance choose the most featureful variant | ||||
| that your platform supports. | ||||
| 
 | ||||
| In exactly one `.c` or `.cpp` file that includes `bt_secp256k1.h` define | ||||
| `BT_SECP256K1_IMPLEMENTATION` as per follows (with additional options to | ||||
| configure the library via macros, see the single file headers for more | ||||
| definitive explanations). | ||||
| 
 | ||||
| ```cpp | ||||
| #define BT_SECP256K1_IMPLEMENTATION | ||||
| // NOTE: The 2 following defines are optional! We provide a default value if | ||||
| // these are not defined before the implementation | ||||
| #define ECMULT_GEN_PREC_BITS 4 | ||||
| #define ECMULT_WINDOW_SIZE 15 | ||||
| #include "bt_secp256k1_i64.h" | ||||
| #include <stdio.h> | ||||
| ``` | ||||
| 
 | ||||
| ## Details | ||||
| 
 | ||||
| The metaprogram provided in `bt_secp256k1_metaprogam.cpp` is responsible for | ||||
| collating code files and patching source files to ensure the project can be | ||||
| combined into a single header file, generating the output files. | ||||
| 
 | ||||
| The code generated header files vendored in the repository correspond to the | ||||
| current commit hash checked out from the secp256k1 submodule. | ||||
| 
 | ||||
| The single file header code-generator metaprogram is provided under the | ||||
| Unlicense license. | ||||
| 
 | ||||
| An example program `bt_secp256k1_example.c` is provided that implements a basic | ||||
| secp256k1 keypair generator for reference and testing the single header file | ||||
| compilation. | ||||
| 
 | ||||
| ## License | ||||
| 
 | ||||
| This is free and unencumbered software released into the public domain. | ||||
| 
 | ||||
| Anyone is free to copy, modify, publish, use, compile, sell, or distribute this | ||||
| software, either in source code form or as a compiled binary, for any purpose, | ||||
| commercial or non-commercial, and by any means. | ||||
							
								
								
									
										37
									
								
								_clang-format
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								_clang-format
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| { | ||||
|     AccessModifierOffset: -4, # 1 tab | ||||
|     AlignAfterOpenBracket: true, | ||||
|     AlignConsecutiveAssignments: true, | ||||
|     AlignConsecutiveDeclarations: true, | ||||
|     AlignTrailingComments: true, | ||||
|     AllowAllParametersOfDeclarationOnNextLine: true, | ||||
|     AllowShortBlocksOnASingleLine: false, | ||||
|     AllowShortIfStatementsOnASingleLine: true, | ||||
|     AllowShortLoopsOnASingleLine: false, | ||||
|     AllowShortCaseLabelsOnASingleLine: true, | ||||
|     AlwaysBreakAfterDefinitionReturnType: false, | ||||
|     AlwaysBreakBeforeMultilineStrings: true, | ||||
|     AlwaysBreakTemplateDeclarations: true, | ||||
|     BinPackArguments: false, | ||||
|     BinPackParameters: false, | ||||
|     BreakBeforeBraces: Allman, | ||||
|     BreakConstructorInitializersBeforeComma: true, | ||||
|     ColumnLimit: 120, | ||||
|     ConstructorInitializerIndentWidth: 0, | ||||
|     Cpp11BracedListStyle: true, | ||||
|     IndentCaseLabels: true, | ||||
|     IndentFunctionDeclarationAfterType: false, | ||||
|     IndentWidth: 4, # 1 tab | ||||
|     MaxEmptyLinesToKeep: 1, | ||||
|     NamespaceIndentation: None, | ||||
|     PointerBindsToType: false, | ||||
|     SpaceBeforeAssignmentOperators: true, | ||||
|     SpaceInEmptyParentheses: false, | ||||
|     SpacesBeforeTrailingComments: 1, | ||||
|     SpacesInAngles: false, | ||||
|     SpacesInCStyleCastParentheses: false, | ||||
|     SpacesInParentheses: false, | ||||
|     SpacesInSquareBrackets: false, | ||||
|     Standard: Cpp11, | ||||
|     TabWidth: 4, | ||||
| } | ||||
							
								
								
									
										114
									
								
								bt_secp256k1_example.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								bt_secp256k1_example.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,114 @@ | ||||
| // A simple program that generates a secp256k1 cryptographic keypair
 | ||||
| // and dumps it to standard out.
 | ||||
| 
 | ||||
| #define BT_SECP256K1_IMPLEMENTATION | ||||
| // NOTE: The 2 following defines are optional! We provide a default value if
 | ||||
| // these are not defined before the implementation
 | ||||
| #define ECMULT_GEN_PREC_BITS 4 | ||||
| #define ECMULT_WINDOW_SIZE 15 | ||||
| 
 | ||||
| #if defined(EXAMPLE_BUILD_I128) | ||||
|     #include "bt_secp256k1_i128.h" | ||||
| #elif defined(EXAMPLE_BUILD_I128_X86_64_ASM) | ||||
|     #include "bt_secp256k1_i128_x86_64_asm.h" | ||||
| #else | ||||
|     #include "bt_secp256k1_i64.h" | ||||
| #endif | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #if defined(_WIN32) | ||||
|     #if defined(__cplusplus) | ||||
|     extern "C" { | ||||
|     #endif | ||||
|     #define BCRYPT_RNG_ALGORITHM L"RNG" | ||||
|     /*NTSTATUS*/ long __stdcall BCryptOpenAlgorithmProvider(void *phAlgorithm, wchar_t const *pszAlgId, wchar_t const *pszImplementation, unsigned long dwFlags); | ||||
|     /*NTSTATUS*/ long __stdcall BCryptGenRandom            (void *hAlgorithm, unsigned char *pbBuffer, unsigned long cbBuffer, unsigned long dwFlags); | ||||
|     #pragma comment(lib, "bcrypt") | ||||
|     #if defined(__cplusplus) | ||||
|     } | ||||
|     #endif | ||||
| #else | ||||
|     #include <sys/random.h> | ||||
| #endif | ||||
| 
 | ||||
| static int Random32Bytes(void *buffer) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
|     static void *bcrypt_handle = NULL; | ||||
|     if (!bcrypt_handle) | ||||
|     { | ||||
|         long init_status = BCryptOpenAlgorithmProvider(&bcrypt_handle, BCRYPT_RNG_ALGORITHM, NULL /*implementation*/, 0 /*flags*/); | ||||
|         if (!bcrypt_handle || init_status != 0) | ||||
|         { | ||||
|             fprintf(stderr, "Failed to initialise random number generator [error=%ld]\n", init_status); | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     long gen_status = BCryptGenRandom(bcrypt_handle, (unsigned char *)buffer, 32 /*size*/, 0 /*flags*/); | ||||
|     if (gen_status != 0) | ||||
|     { | ||||
|         fprintf(stderr, "Failed to generate random bytes [error=%ld]\n", gen_status); | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
| #else | ||||
|     int read_bytes = 0; | ||||
|     do | ||||
|     { | ||||
|         read_bytes = getrandom(buffer, 32 /*size*/, 0); | ||||
|     } while (read_bytes != size || errno == EAGAIN); // NOTE: EINTR can not be triggered if size <= 32 bytes
 | ||||
| #endif | ||||
| 
 | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     (void)argc; (void)argv; | ||||
| 
 | ||||
|     // NOTE: Initialise the library
 | ||||
|     secp256k1_context *lib_context = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); | ||||
| 
 | ||||
|     // NOTE: Generate a public key
 | ||||
|     unsigned char skey[32]; | ||||
|     if (!Random32Bytes(skey)) | ||||
|     { | ||||
|         fprintf(stderr, "Failed to generate secret key\n"); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     secp256k1_pubkey pkey; | ||||
|     if (secp256k1_ec_pubkey_create(lib_context, &pkey, skey) == 1) | ||||
|     { | ||||
|         // NOTE: Serialize the key
 | ||||
|         unsigned char pkey_serialized[33]; | ||||
|         size_t pkey_serialized_size = sizeof(pkey_serialized); | ||||
|         secp256k1_ec_pubkey_serialize(lib_context, pkey_serialized, &pkey_serialized_size, &pkey, SECP256K1_EC_COMPRESSED); | ||||
| 
 | ||||
|         // NOTE: Dump the secret key to stdout
 | ||||
|         fprintf(stdout, "Secret Key [key=0x"); | ||||
|         for (size_t index = 0; index < sizeof(skey); index++) | ||||
|         { | ||||
|             fprintf(stdout, "%x", (skey[index] >> 4) & 0xF); | ||||
|             fprintf(stdout, "%x", (skey[index] >> 0) & 0xF); | ||||
|         } | ||||
|         fprintf(stdout, "]\n"); | ||||
| 
 | ||||
|         // NOTE: Dump the serialized public key to stdout
 | ||||
|         fprintf(stdout, "Public Key [key=0x"); | ||||
|         for (size_t index = 0; index < pkey_serialized_size; index++) | ||||
|         { | ||||
|             fprintf(stdout, "%x", (pkey_serialized[index] >> 4) & 0xF); | ||||
|             fprintf(stdout, "%x", (pkey_serialized[index] >> 0) & 0xF); | ||||
|         } | ||||
|         fprintf(stdout, "]\n"); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         fprintf(stderr, "Failed to generate public key"); | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										35516
									
								
								bt_secp256k1_i128.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35516
									
								
								bt_secp256k1_i128.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35744
									
								
								bt_secp256k1_i128_x86_64_asm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35744
									
								
								bt_secp256k1_i128_x86_64_asm.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35136
									
								
								bt_secp256k1_i64.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35136
									
								
								bt_secp256k1_i64.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										636
									
								
								bt_secp256k1_metaprogram.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										636
									
								
								bt_secp256k1_metaprogram.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,636 @@ | ||||
| #define _CRT_SECURE_NO_WARNINGS | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #define FILE_SCOPE static | ||||
| 
 | ||||
| FILE_SCOPE char *ReadEntireFile(char const *file_path, int *file_size) | ||||
| { | ||||
|     char *result      = nullptr; | ||||
|     FILE *file_handle = fopen(file_path, "rb"); | ||||
|     if (file_handle) | ||||
|     { | ||||
|         fseek(file_handle, 0, SEEK_END); | ||||
|         *file_size = ftell(file_handle); | ||||
|         rewind(file_handle); | ||||
| 
 | ||||
|         result             = (char *)malloc(*file_size + 1); | ||||
|         result[*file_size] = 0; | ||||
|         if (result) | ||||
|         { | ||||
|             if (fread(result, (size_t)(*file_size), 1, file_handle) != 1) | ||||
|             { | ||||
|                 free(result); | ||||
|                 result = nullptr; | ||||
|             } | ||||
|         } | ||||
|         fclose(file_handle); | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| enum FileFlag | ||||
| { | ||||
|     FileFlag_Normal        = 1 << 0, | ||||
|     FileFlag_Mul64Support  = 1 << 1, | ||||
|     FileFlag_Mul128Support = 1 << 2, | ||||
|     FileFlag_AsmX86_64     = 1 << 3, | ||||
|     FileFlag_AsmInt128     = 1 << 4, | ||||
| }; | ||||
| 
 | ||||
| struct String     { char *str; int size; }; | ||||
| struct StringList { String string; StringList *next; }; | ||||
| #define STRING(string) {string, sizeof(string) - 1} | ||||
| 
 | ||||
| struct LoadedFile | ||||
| { | ||||
|     unsigned  flag; | ||||
|     char     *buffer; | ||||
|     int       size; | ||||
|     String    sub_dir; | ||||
|     String    name; | ||||
| }; | ||||
| 
 | ||||
| FILE_SCOPE bool LoadFiles(LoadedFile *files, int file_count, char const *root_dir) | ||||
| { | ||||
|     bool result = true; | ||||
|     for (int file_index = 0; file_index < file_count; file_index++) | ||||
|     { | ||||
|         LoadedFile *file = files + file_index; | ||||
|         char file_path[2048]; | ||||
|         if (file->sub_dir.size) | ||||
|         { | ||||
|             snprintf(file_path, sizeof(file_path), "%s/%.*s/%.*s", root_dir, file->sub_dir.size, file->sub_dir.str, file->name.size, file->name.str); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             snprintf(file_path, sizeof(file_path), "%s/%.*s", root_dir, file->name.size, file->name.str); | ||||
|         } | ||||
| 
 | ||||
|         file->buffer = ReadEntireFile(file_path, &file->size); | ||||
|         if (!file->buffer || file->size == 0) | ||||
|         { | ||||
|             fprintf(stderr, "Failed to load file [file=%s]\n", file_path); | ||||
|             result = false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| FILE_SCOPE String StringCopy(String src) | ||||
| { | ||||
|     String result = String{(char *)malloc(src.size + 1), src.size}; | ||||
|     memcpy(result.str, src.str, src.size); | ||||
|     result.str[src.size] = 0; | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| FILE_SCOPE StringList *StringListAppendRef(StringList *list, String string) | ||||
| { | ||||
|     StringList *result = list; | ||||
|     if (string.str && string.size) | ||||
|     { | ||||
|         if (list->string.str) | ||||
|         { | ||||
|             list->next = (StringList *)malloc(sizeof(StringList)); | ||||
|             result     = list->next; | ||||
|             *result    = {}; | ||||
|         } | ||||
|         result->string = string; | ||||
|     } | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| FILE_SCOPE String StringListBuild(StringList *list) | ||||
| { | ||||
|     int total_size = 0; | ||||
|     for (StringList *entry = list; entry; entry = entry->next) | ||||
|         total_size += entry->string.size; | ||||
| 
 | ||||
|     char *string = (char *)malloc(total_size + 1); | ||||
|     char *writer = string; | ||||
|     for (StringList *entry = list; entry; entry = entry->next) | ||||
|     { | ||||
|         memcpy(writer, entry->string.str, entry->string.size); | ||||
|         writer += entry->string.size; | ||||
|     } | ||||
| 
 | ||||
|     writer[0] = 0; | ||||
| 
 | ||||
|     String result = {string, total_size}; | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| FILE_SCOPE bool StringEquals(String lhs, String rhs) | ||||
| { | ||||
|     bool result = lhs.size == rhs.size && (memcmp(lhs.str, rhs.str, lhs.size) == 0); | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| FILE_SCOPE String StringFindThenInsert(String src, String find, String insert) | ||||
| { | ||||
|     // NOTE: We leak the string list memory but don't care because this is
 | ||||
|     // a meta tool that lives for a couple of seconds and kills itself.
 | ||||
| 
 | ||||
|     StringList  list_head = {}; | ||||
|     StringList *list_tail = &list_head; | ||||
| 
 | ||||
|     int        src_end     = src.size - find.size; | ||||
|     int        head        = 0; | ||||
|     for (int tail = head; tail <= src_end; tail++) | ||||
|     { | ||||
|         String check = String{src.str + tail, find.size}; | ||||
|         if (!StringEquals(check, find)) | ||||
|             continue; | ||||
| 
 | ||||
|         String range = String{src.str + head, (tail - head)}; | ||||
|         list_tail    = StringListAppendRef(list_tail, range); | ||||
|         list_tail    = StringListAppendRef(list_tail, insert); | ||||
|         list_tail    = StringListAppendRef(list_tail, check); | ||||
|         head         = tail + find.size; | ||||
|         tail         = head - 1; ; // NOTE: -1 because for loop post increment
 | ||||
|     } | ||||
| 
 | ||||
|     String result = {}; | ||||
|     if (list_head.string.size == 0) | ||||
|     { | ||||
|         // NOTE: No insertment possible, so we just do a full-copy
 | ||||
|         result = StringCopy(src); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         String remainder = String{src.str + head, src.size - head}; | ||||
|         list_tail        = StringListAppendRef(list_tail, remainder); | ||||
|         result           = StringListBuild(&list_head); | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| FILE_SCOPE String StringReplace(String src, String find, String replace) | ||||
| { | ||||
|     // NOTE: We leak the string list memory but don't care because this is
 | ||||
|     // a meta tool that lives for a couple of seconds and kills itself.
 | ||||
| 
 | ||||
|     StringList  list_head = {}; | ||||
|     StringList *list_tail = &list_head; | ||||
| 
 | ||||
|     int        src_end     = src.size - find.size; | ||||
|     int        head        = 0; | ||||
|     for (int tail = head; tail <= src_end; tail++) | ||||
|     { | ||||
|         String check = String{src.str + tail, find.size}; | ||||
|         if (!StringEquals(check, find)) | ||||
|             continue; | ||||
| 
 | ||||
|         String range = String{src.str + head, (tail - head)}; | ||||
|         list_tail    = StringListAppendRef(list_tail, range); | ||||
|         list_tail    = StringListAppendRef(list_tail, replace); | ||||
|         head         = tail + find.size; | ||||
|         tail         = head - 1; ; // NOTE: -1 because for loop post increment
 | ||||
|     } | ||||
| 
 | ||||
|     String result = {}; | ||||
|     if (list_head.string.size == 0) | ||||
|     { | ||||
|         // NOTE: No insertment possible, so we just do a full-copy
 | ||||
|         result = StringCopy(src); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         String remainder = String{src.str + head, src.size - head}; | ||||
|         list_tail        = StringListAppendRef(list_tail, remainder); | ||||
|         result           = StringListBuild(&list_head); | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| StringList *AddSourceFileComment(StringList *tail, LoadedFile const *file) | ||||
| { | ||||
|     StringList *result = StringListAppendRef(tail, STRING("\n// File: ")); | ||||
|     if (file->sub_dir.size) | ||||
|     { | ||||
|         result = StringListAppendRef(result, file->sub_dir); | ||||
|         result = StringListAppendRef(result, STRING("/")); | ||||
|     } | ||||
| 
 | ||||
|     result = StringListAppendRef(result, file->name); | ||||
|     result = StringListAppendRef(result, STRING("\n")); | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
|     if (argc != 2) | ||||
|     { | ||||
|         printf("Usage: bt_secp256k1_metaprogram <path/to/secp256k1/directory>\n"); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     LoadedFile intro_files[] = { | ||||
|         {FileFlag_Normal, nullptr, 0, STRING(""), STRING("COPYING")}, | ||||
|     }; | ||||
| 
 | ||||
|     LoadedFile header_files[] = { | ||||
|         {FileFlag_Normal, nullptr, 0, STRING("include"), STRING("secp256k1.h")}, | ||||
|         {FileFlag_Normal, nullptr, 0, STRING("include"), STRING("secp256k1_preallocated.h")}, | ||||
|     }; | ||||
| 
 | ||||
|     LoadedFile private_header_files[] = { | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("util.h")}, | ||||
|         {FileFlag_Mul64Support,  nullptr, 0, STRING("src"), STRING("field_10x26.h")}, | ||||
|         {FileFlag_Mul64Support,  nullptr, 0, STRING("src"), STRING("scalar_8x32.h")}, | ||||
|         {FileFlag_Mul128Support, nullptr, 0, STRING("src"), STRING("field_5x52.h")}, | ||||
|         {FileFlag_Mul128Support, nullptr, 0, STRING("src"), STRING("scalar_4x64.h")}, | ||||
|         {FileFlag_Mul128Support, nullptr, 0, STRING("src"), STRING("modinv64.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("hash.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("modinv32.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("assumptions.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("scalar.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("field.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("group.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("ecmult_const.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("ecmult_gen.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("scratch.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("ecmult.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("precomputed_ecmult.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("precomputed_ecmult_gen.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("ecdsa.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("eckey.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("selftest.h")}, | ||||
|     }; | ||||
| 
 | ||||
|     LoadedFile private_impl_files[] = { | ||||
|         {FileFlag_Mul64Support,  nullptr, 0, STRING("src"), STRING("field_10x26_impl.h")}, | ||||
|         {FileFlag_Mul64Support,  nullptr, 0, STRING("src"), STRING("scalar_8x32_impl.h")}, | ||||
|         {FileFlag_AsmInt128,     nullptr, 0, STRING("src"), STRING("field_5x52_int128_impl.h")}, | ||||
|         {FileFlag_AsmX86_64,     nullptr, 0, STRING("src"), STRING("field_5x52_asm_impl.h")}, | ||||
|         {FileFlag_Mul128Support, nullptr, 0, STRING("src"), STRING("field_5x52_impl.h")}, | ||||
|         {FileFlag_Mul128Support, nullptr, 0, STRING("src"), STRING("scalar_4x64_impl.h")}, | ||||
|         {FileFlag_Mul128Support, nullptr, 0, STRING("src"), STRING("modinv64_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("ecdsa_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("eckey_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("group_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("field_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("scalar_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("ecmult_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("ecmult_const_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("ecmult_gen_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("precomputed_ecmult.c")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("precomputed_ecmult_gen.c")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("hash_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("modinv32_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("scratch_impl.h")}, | ||||
|         {FileFlag_Normal,        nullptr, 0, STRING("src"), STRING("secp256k1.c")}, | ||||
|     }; | ||||
| 
 | ||||
|     #define ARRAY_COUNT(array) sizeof(array)/sizeof((array)[0]) | ||||
|     char const *root_dir     = argv[1]; | ||||
|     bool        files_loaded = true; | ||||
|     files_loaded &= LoadFiles(intro_files, ARRAY_COUNT(intro_files), root_dir); | ||||
|     files_loaded &= LoadFiles(header_files, ARRAY_COUNT(header_files), root_dir); | ||||
|     files_loaded &= LoadFiles(private_header_files, ARRAY_COUNT(private_header_files), root_dir); | ||||
|     files_loaded &= LoadFiles(private_impl_files, ARRAY_COUNT(private_impl_files), root_dir); | ||||
| 
 | ||||
|     if (!files_loaded) | ||||
|         return -1; | ||||
| 
 | ||||
|     unsigned const BUILD_FLAGS[] = { | ||||
|         FileFlag_Normal | FileFlag_Mul64Support, | ||||
|         FileFlag_Normal | FileFlag_Mul128Support | FileFlag_AsmInt128, | ||||
|         FileFlag_Normal | FileFlag_Mul128Support | FileFlag_AsmX86_64, | ||||
|     }; | ||||
| 
 | ||||
|     for (int build_index = 0; build_index < ARRAY_COUNT(BUILD_FLAGS); build_index++) | ||||
|     { | ||||
|         unsigned const build_flags = BUILD_FLAGS[build_index]; | ||||
| 
 | ||||
|         char build_name_buf[1024]; | ||||
|         String build_name = {}; | ||||
|         build_name.str    = build_name_buf; | ||||
|         build_name.size   = snprintf(build_name_buf, | ||||
|                                      sizeof(build_name_buf), | ||||
|                                      "bt_secp256k1_i%s%s.h", | ||||
|                                      (build_flags & FileFlag_Mul64Support) ? "64" : "128", | ||||
|                                      (build_flags & FileFlag_AsmX86_64)    ? "_x86_64_asm" : ""); | ||||
| 
 | ||||
|         // NOTE: Append all the files into one contiguous buffer
 | ||||
|         String buffer = {}; | ||||
|         { | ||||
|             StringList  list_head = {}; | ||||
|             StringList *list_tail = &list_head; | ||||
| 
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             // Intro files
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             // TODO(doyle): Add no precomputed table macro
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING( | ||||
|             "// -----------------------------------------------------------------------------\n" | ||||
|             "// NOTE: Overview\n" | ||||
|             "// -----------------------------------------------------------------------------\n" | ||||
|             "// A machine generated single-header file of bitcoin-core/libsecp256k1 that is\n" | ||||
|             "// compilable in C/C++ with minimal effort.\n" | ||||
|             "//\n" | ||||
|             "// - By default ECMULT_WINDOW_SIZE is set to 15. This is the default\n" | ||||
|             "// recommended value you'd get from building the library with \"auto\" settings.\n" | ||||
|             "// You may override this by defining this macro before defining the\n" | ||||
|             "// IMPLEMENTATION macro for this file.\n" | ||||
|             "//\n" | ||||
|             "// - By default ECMULT_GEN_PREC_BITS is set to 4. This is the default\n" | ||||
|             "// recommended value you'd get from building the library with \"auto\" settings.\n" | ||||
|             "// You may override this by defining this macro before defining the\n" | ||||
|             "// IMPLEMENTATION macro for this file.\n" | ||||
|             "//\n" | ||||
|             "// - Define BT_SECP256K1_DISABLE_WARNING_PRAGMAS to disable the extra pragmas in\n" | ||||
|             "// this file that suppress some compiler warnings- since this is not really the\n" | ||||
|             "// concern of a machine generated single header file library, fixes should be sent\n" | ||||
|             "// upstream.\n" | ||||
|             "//\n" | ||||
|             "// - Define BT_SECP256K1_NO_PRECOMPUTED_TABLE to disable the precomputed table\n" | ||||
|             "// that was generated by building and running gen_context.c\n" | ||||
|             "// -----------------------------------------------------------------------------\n" | ||||
|             "// NOTE: License\n" | ||||
|             "// -----------------------------------------------------------------------------\n" | ||||
|             )); | ||||
| 
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("/*\n")); | ||||
|             for (LoadedFile const &file : intro_files) | ||||
|             { | ||||
|                 if (build_flags & file.flag) | ||||
|                     list_tail = StringListAppendRef(list_tail, String{file.buffer, file.size}); | ||||
|             } | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("*/\n")); | ||||
| 
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING( | ||||
|             "// -----------------------------------------------------------------------------\n" | ||||
|             "// NOTE: Example\n" | ||||
|             "// -----------------------------------------------------------------------------\n" | ||||
|             "#if 0\n" | ||||
|             "#define BT_SECP256K1_IMPLEMENTATION\n" | ||||
|             "// NOTE: The 2 following defines are optional! We provide a default value if\n" | ||||
|             "// these are not defined before the implementation\n" | ||||
|             "#define ECMULT_GEN_PREC_BITS 4\n" | ||||
|             "#define ECMULT_WINDOW_SIZE 15\n" | ||||
|             "#include \"" | ||||
|             )); | ||||
| 
 | ||||
|             list_tail = StringListAppendRef(list_tail, build_name); | ||||
| 
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("\"\n" | ||||
|             "#include <stdio.h>\n" | ||||
|             "\n" | ||||
|             "int main(int argc, char **argv)\n" | ||||
|             "{\n" | ||||
|             "    (void)argc; (void)argv;\n" | ||||
|             "\n" | ||||
|             "    // NOTE: Initialise the library\n" | ||||
|             "    secp256k1_context *lib_context = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);\n" | ||||
|             "\n" | ||||
|             "    // NOTE: Generate a public key from a hard-coded secret key\n" | ||||
|             "    unsigned char const skey[32 + 1] = \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n" | ||||
|             "                                       \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n" | ||||
|             "                                       \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n" | ||||
|             "                                       \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\";\n" | ||||
|             "    secp256k1_pubkey pkey;\n" | ||||
|             "\n" | ||||
|             "    if (secp256k1_ec_pubkey_create(lib_context, &pkey, skey) == 1)\n" | ||||
|             "    {\n" | ||||
|             "\n" | ||||
|             "        // NOTE: Serialize the key\n" | ||||
|             "        unsigned char pkey_serialized[33];\n" | ||||
|             "        size_t pkey_serialized_size = sizeof(pkey_serialized);\n" | ||||
|             "        secp256k1_ec_pubkey_serialize(lib_context, pkey_serialized, &pkey_serialized_size, &pkey, SECP256K1_EC_COMPRESSED);\n" | ||||
|             "\n" | ||||
|             "        // NOTE: Dump the secret key to stdout\n" | ||||
|             "        fprintf(stdout, \"Secret Key [key=0x\");\n" | ||||
|             "        for (size_t index = 0; index < sizeof(skey); index++)\n" | ||||
|             "        {\n" | ||||
|             "            fprintf(stdout, \"%x\", (skey[index] >> 4) & 0xF);\n" | ||||
|             "            fprintf(stdout, \"%x\", (skey[index] >> 0) & 0xF);\n" | ||||
|             "        }\n" | ||||
|             "        fprintf(stdout, \"]\\n\");\n" | ||||
|             "\n" | ||||
|             "        // NOTE: Dump the serialized public key to stdout\n" | ||||
|             "        fprintf(stdout, \"Public Key [key=0x\");\n" | ||||
|             "        for (size_t index = 0; index < pkey_serialized_size; index++)\n" | ||||
|             "        {\n" | ||||
|             "            fprintf(stdout, \"%x\", (pkey_serialized[index] >> 4) & 0xF);\n" | ||||
|             "            fprintf(stdout, \"%x\", (pkey_serialized[index] >> 0) & 0xF);\n" | ||||
|             "        }\n" | ||||
|             "        fprintf(stdout, \"]\\n\");\n" | ||||
|             "    }\n" | ||||
|             "    else\n" | ||||
|             "    {\n" | ||||
|             "        fprintf(stderr, \"Failed to generate public key\");\n" | ||||
|             "    }\n" | ||||
|             "\n" | ||||
|             "    return 0;\n" | ||||
|             "}\n" | ||||
|             "#endif\n" | ||||
|             "\n" | ||||
|             "// -----------------------------------------------------------------------------\n" | ||||
|             "// NOTE: Single Header Start\n" | ||||
|             "// -----------------------------------------------------------------------------\n" | ||||
|             )); | ||||
| 
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             // Header defines
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("#if !defined(BT_SECP256K1_H)\n")); | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("#define BT_SECP256K1_H\n\n")); | ||||
| 
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("#if !defined(SECP256K1_BUILD)\n")); | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("    #define SECP256K1_BUILD\n")); | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("#endif\n\n")); | ||||
| 
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             // Header files
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             for (LoadedFile const &file : header_files) | ||||
|             { | ||||
|                 if (build_flags & file.flag) | ||||
|                 { | ||||
|                     list_tail = AddSourceFileComment(list_tail, &file); | ||||
|                     list_tail = StringListAppendRef(list_tail, String{file.buffer, file.size}); | ||||
|                 } | ||||
|             } | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("#endif // BT_SECP256K1_H\n")); | ||||
| 
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             // Add implementation defines
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING("#if defined(BT_SECP256K1_IMPLEMENTATION)\n")); | ||||
| 
 | ||||
|             { | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#if !defined(ECMULT_GEN_PREC_BITS)\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("    #define ECMULT_GEN_PREC_BITS 4\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#endif\n\n")); | ||||
|             } | ||||
| 
 | ||||
|             { | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#if !defined(ECMULT_WINDOW_SIZE)\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("    #define ECMULT_WINDOW_SIZE 15\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#endif\n\n")); | ||||
|             } | ||||
| 
 | ||||
|             if (build_flags & FileFlag_Mul64Support) | ||||
|             { | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#if !defined(USE_FORCE_WIDEMUL_INT64)\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("    #define USE_FORCE_WIDEMUL_INT64\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#endif\n\n")); | ||||
|             } | ||||
| 
 | ||||
|             if (build_flags & FileFlag_Mul128Support) | ||||
|             { | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#if !defined(USE_FORCE_WIDEMUL_INT128)\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("    #define USE_FORCE_WIDEMUL_INT128\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#endif\n\n")); | ||||
|             } | ||||
| 
 | ||||
|             if (build_flags & FileFlag_AsmX86_64) | ||||
|             { | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#if !defined(USE_ASM_X86_64)\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("    #define USE_ASM_X86_64\n")); | ||||
|                 list_tail = StringListAppendRef(list_tail, STRING("#endif\n\n")); | ||||
|             } | ||||
| 
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING( | ||||
|                 "#if !defined(BT_SECP256K1_DISABLE_WARNING_PRAGMAS)\n" | ||||
|                 "    #if defined(__clang__)\n" | ||||
|                 "        #pragma clang diagnostic push\n" | ||||
|                 "        #pragma clang diagnostic ignored \"-Wunused-function\"\n" | ||||
|                 "        #pragma clang diagnostic ignored \"-Wmissing-field-initializers\"\n" | ||||
|                 "    #elif defined(_MSC_VER)\n" | ||||
|                 "        #pragma warning(push)\n" | ||||
|                 "        #pragma warning(disable: 4146)\n" | ||||
|                 "        #pragma warning(disable: 4310)\n" | ||||
|                 "        #pragma warning(disable: 4244)\n" | ||||
|                 "        #pragma warning(disable: 4319)\n" | ||||
|                 "        #pragma warning(disable: 4267)\n" | ||||
|                 "        #pragma warning(disable: 4334)\n" | ||||
|                 "        #pragma warning(disable: 4127)\n" | ||||
|                 "        #pragma warning(disable: 4505)\n" | ||||
|                 "        #pragma warning(disable: 4706)\n" | ||||
|                 "    #endif\n" | ||||
|                 "#endif // !defined(BT_SECP256K1_DISABLE_WARNING_PRAGMAS)\n" | ||||
|                 "\n" | ||||
|             )); | ||||
| 
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             // Append implementation Files
 | ||||
|             // -------------------------------------------------------------------------------------
 | ||||
|             for (LoadedFile const &file : private_header_files) | ||||
|             { | ||||
|                 if (build_flags & file.flag) | ||||
|                 { | ||||
|                     list_tail = AddSourceFileComment(list_tail, &file); | ||||
|                     list_tail = StringListAppendRef(list_tail, String{file.buffer, file.size}); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             for (LoadedFile const &file : private_impl_files) | ||||
|             { | ||||
|                 if (build_flags & file.flag) | ||||
|                 { | ||||
|                     list_tail = AddSourceFileComment(list_tail, &file); | ||||
|                     list_tail = StringListAppendRef(list_tail, String{file.buffer, file.size}); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             list_tail = StringListAppendRef(list_tail, STRING( | ||||
|                 "\n" | ||||
|                 "#if !defined(BT_SECP256K1_DISABLE_WARNING_PRAGMAS)\n" | ||||
|                 "    #if defined(__clang__)\n" | ||||
|                 "        #pragma clang diagnostic pop\n" | ||||
|                 "    #elif defined(_MSC_VER)\n" | ||||
|                 "        #pragma warning(pop)\n" | ||||
|                 "    #endif\n" | ||||
|                 "#endif // !defined(BT_SECP256K1_DISABLE_WARNING_PRAGMAS)\n" | ||||
|                 "\n" | ||||
|                 "#endif // BT_SECP256K1_IMPLEMENTATION\n" | ||||
|             )); | ||||
| 
 | ||||
|             buffer = StringListBuild(&list_head); | ||||
|         } | ||||
| 
 | ||||
|         // NOTE: Do string inserts and comment out header include directives
 | ||||
|         { | ||||
|             char   old_directive_buf[1024]; | ||||
|             char   new_directive_buf[1024]; | ||||
|             String old_directive = String{old_directive_buf, 0}; | ||||
|             String new_directive = String{new_directive_buf, 0}; | ||||
| 
 | ||||
|             struct LoadedFileList | ||||
|             { | ||||
|                 LoadedFile *data; | ||||
|                 int         size; | ||||
|             }; | ||||
| 
 | ||||
|             LoadedFileList file_list[] = { | ||||
|                 {header_files, ARRAY_COUNT(header_files)}, | ||||
|                 {private_header_files, ARRAY_COUNT(private_header_files)}, | ||||
|                 {private_impl_files, ARRAY_COUNT(private_impl_files)}, | ||||
|             }; | ||||
| 
 | ||||
|             for (LoadedFileList const &list : file_list) | ||||
|             { | ||||
|                 for (int file_index = 0; file_index < list.size; file_index++) | ||||
|                 { | ||||
|                     LoadedFile const &file = list.data[file_index]; | ||||
|                     if (build_flags & file.flag) | ||||
|                     { | ||||
|                         // NOTE: Comment out the #includes for the file since
 | ||||
|                         // we're producing a single header file.
 | ||||
|                         old_directive.size = snprintf(old_directive_buf, sizeof(old_directive_buf), "#include \"%.*s\"", file.name.size, file.name.str); | ||||
|                         buffer = StringFindThenInsert(buffer, old_directive, STRING("// ")); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // NOTE: secp256k1 uses relative headers, so patch them out
 | ||||
|             buffer = StringFindThenInsert(buffer, STRING("#include \"../include/secp256k1"), STRING("// ")); | ||||
| 
 | ||||
|             // NOTE: Allow adding a static context ontop of the single file
 | ||||
|             // header library by commenting the #include directive in the source
 | ||||
|             // code out. This allows the user to #include their own generated
 | ||||
|             // static context before including this library.
 | ||||
|             buffer = StringFindThenInsert(buffer, STRING("#include \"ecmult_static_context.h\""), STRING("// ")); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         // NOTE: Misc patches to source code
 | ||||
|         { | ||||
|             // NOTE: Patch one problematic line that causes a compile failure in
 | ||||
|             // C++ (but not C, since this a C library).
 | ||||
|             buffer = StringReplace( | ||||
|                 buffer, | ||||
|                 STRING("const unsigned char *p1 = s1, *p2 = s2;"), | ||||
|                 STRING("const unsigned char *p1 = (const unsigned char *)s1, *p2 = (const unsigned char *)s2;")); | ||||
| 
 | ||||
|             // NOTE: Delete any Windows style new-lines if there were any
 | ||||
|             buffer = StringReplace(buffer, STRING("\r"), STRING("")); | ||||
|         } | ||||
| 
 | ||||
|         // NOTE: Output file
 | ||||
|         { | ||||
|             FILE *file_handle = fopen(build_name.str, "w+b"); | ||||
|             if (!file_handle) | ||||
|             { | ||||
|                 fprintf(stderr, "Failed to write to file, unable to run metaprogram [file=%s]\n", build_name.str); | ||||
|                 return -1; | ||||
|             } | ||||
| 
 | ||||
|             fwrite(buffer.str, buffer.size, 1, file_handle); | ||||
|             fclose(file_handle); | ||||
| 
 | ||||
|             printf("File generated to %s\n", build_name.str); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										49
									
								
								build.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								build.bat
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| @echo off | ||||
| setlocal EnableDelayedExpansion | ||||
| 
 | ||||
| where /q cl || ( | ||||
|   echo MSVC's cl is not found - please run this from the MSVC x64 native tools command prompt | ||||
|   exit /b 1 | ||||
| ) | ||||
| 
 | ||||
| set code_dir=%~dp0 | ||||
| set build_dir=!code_dir!\build | ||||
| if not exist !build_dir! mkdir !build_dir! | ||||
| 
 | ||||
| set common_compile_flags=-W4 -O2 | ||||
| set common_linker_flags=-link -nologo | ||||
| 
 | ||||
| REM Build the metaprogram | ||||
| pushd !build_dir! | ||||
|     cl !common_compiler_flags! !code_dir!\bt_secp256k1_metaprogram.cpp !common_linker_flags! || ( | ||||
|         echo Build script failed because the metaprogram failed to build successfully | ||||
|         exit | ||||
|     ) | ||||
| popd | ||||
| 
 | ||||
| REM Code generate the single file header | ||||
| !build_dir!\bt_secp256k1_metaprogram.exe !code_dir!\secp256k1 || ( | ||||
|     echo Build script failed because the metaprogram did not run successfully | ||||
|     exit | ||||
| ) | ||||
| 
 | ||||
| REM Build the test program to sanity check the single file header | ||||
| pushd !build_dir! | ||||
|     set common_source_files=!code_dir!\bt_secp256k1_example.c | ||||
| 
 | ||||
|     REM Build a C/C++ i64 version | ||||
|     cl !common_compile_flags! -Tc !common_source_files! !common_linker_flags! -out:bt_secp256k1_i64_example_c.exe | ||||
|     cl !common_compile_flags! -Tp !common_source_files! !common_linker_flags! -out:bt_secp256k1_i64_example_cpp.exe | ||||
| 
 | ||||
|     where /q clang-cl || ( | ||||
|       exit | ||||
|     ) | ||||
| 
 | ||||
|     REM (Optional) Build a C/C++ {i128, i128 x86_64 ASM} version | ||||
|     REM This requires clang-cl because MSVC does not expose a uint128_t type | ||||
|     clang-cl !common_compile_flags! -D EXAMPLE_BUILD_I128            -Tc !common_source_files! !common_linker_flags! -out:bt_secp256k1_i128_example_c.exe | ||||
|     clang-cl !common_compile_flags! -D EXAMPLE_BUILD_I128_X86_64_ASM -Tc !common_source_files! !common_linker_flags! -out:bt_secp256k1_i128_x86_64_asm_example_c.exe | ||||
| 
 | ||||
|     clang-cl !common_compile_flags! -D EXAMPLE_BUILD_I128            -Tp !common_source_files! !common_linker_flags! -out:bt_secp256k1_i128_example_cpp.exe | ||||
|     clang-cl !common_compile_flags! -D EXAMPLE_BUILD_I128_X86_64_ASM -Tp !common_source_files! !common_linker_flags! -out:bt_secp256k1_i128_x86_64_asm_example_cpp.exe | ||||
| popd | ||||
							
								
								
									
										1
									
								
								secp256k1
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								secp256k1
									
									
									
									
									
										Submodule
									
								
							| @ -0,0 +1 @@ | ||||
| Subproject commit c8aa516b57ab951e26a1ff5fa283d6f5612ca809 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user