├── LICENSE.txt ├── Makefile ├── Makefile.macosx ├── Makefile.windows ├── README.md ├── VERSION ├── apps └── txmon │ ├── Makefile │ ├── Makefile.macosx │ ├── Makefile.windows │ ├── install.nsi │ ├── ripemd160.c │ ├── txmon.c │ ├── txmon.ico │ └── txmon.rc ├── linux.c ├── main.c ├── port_map.c ├── pseudo_node.c ├── pseudo_node.h ├── release-build.sh ├── sha256.c └── windows.c /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 the copyright holders 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = clang 2 | STRIP = strip 3 | OBJS = pseudo_node.o 4 | CFLAGS = -std=gnu99 -DLINUX -O2 -Wall -Wno-unused-value -fpic 5 | CLIBS = -lpthread -ldl -Wl,-R. 6 | 7 | pseudonode: libpseudonode.so main.o 8 | $(CC) $(CFLAGS) -o pseudonode main.o $(CLIBS) -L. libpseudonode.so 9 | $(STRIP) pseudonode 10 | cp pseudonode pseudonode.linux 11 | 12 | libpseudonode.so: $(OBJS) 13 | $(CC) -shared -o libpseudonode.so $(OBJS) 14 | 15 | clean: 16 | rm -f $(OBJS) main.o 17 | 18 | -------------------------------------------------------------------------------- /Makefile.macosx: -------------------------------------------------------------------------------- 1 | CC = clang 2 | STRIP = strip 3 | OBJS = pseudo_node.o 4 | CFLAGS = -std=gnu99 -DMACOSX -O2 -Wall -Wno-unused-value -fpic 5 | CLIBS = -lpthread -ldl -Wl,-rpath -Wl,. 6 | 7 | pseudonode: libpseudonode.dylib main.o 8 | $(CC) $(CFLAGS) -o pseudonode main.o $(CLIBS) -L. libpseudonode.dylib 9 | $(STRIP) pseudonode 10 | cp pseudonode pseudonode.macosx 11 | 12 | libpseudonode.dylib: $(OBJS) 13 | $(CC) -shared -o libpseudonode.dylib $(OBJS) 14 | 15 | clean: 16 | rm -f $(OBJS) main.o 17 | 18 | -------------------------------------------------------------------------------- /Makefile.windows: -------------------------------------------------------------------------------- 1 | CC = x86_64-w64-mingw32-gcc 2 | STRIP = x86_64-w64-mingw32-strip 3 | OBJS = pseudo_node.o 4 | CFLAGS = -std=gnu99 -DWINDOWS -O2 -Wno-unused-value -mthreads -mconsole -fpic 5 | CLIBS = -lws2_32 -lkernel32 6 | 7 | PseudoNode.exe: PseudoNode.dll main.o 8 | $(CC) $(CFLAGS) -o PseudoNode.exe main.o $(OBJS) $(CLIBS) 9 | $(STRIP) PseudoNode.exe 10 | 11 | PseudoNode.dll: $(OBJS) 12 | $(CC) $(CFLAGS) --shared -o PseudoNode.dll $(OBJS) $(CLIBS) 13 | 14 | pseudo_node.o: pseudo_node.c windows.c 15 | 16 | clean: 17 | rm -f $(OBJS) main.o 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LibPseudoNode 0.7.0 2 | =================== 3 | 4 | PseudoNode is a cryptocurrency full node "emulator". 5 | 6 | To the network, PseudoNode behaves the same way as a full node by relaying 7 | transactions, blocks, addresses, etc. However, unlike a normal full 8 | node, PseudoNode does *not* verify data (txs & blocks) itself. Rather, 9 | PseudoNode relies on neighboring peers (with configurable confidence levels) 10 | to do the verification on PseudoNode's behalf. As a result, PseudoNode is 11 | very lightweight. 12 | 13 | Compared to a normal full node: 14 | 15 | * PseudoNode *does not require the blockchain to be downloaded*. 16 | * PseudoNode can "sync" with the network in seconds. 17 | * PseudoNode supports multiple cryptocurrencies that are Bitcoin derivatives. 18 | * PseudoNode uses no disk space (sans the executable), negligible RAM, and 19 | negligible CPU time. PseudoNode also consumes less network resources 20 | (data usage/bandwidth) than a normal full node. 21 | 22 | PseudoNode can be downloaded from here (the official release): 23 | 24 | * [https://github.com/basil00/PseudoNode/releases](https://github.com/basil00/PseudoNode/releases) 25 | 26 | Usage 27 | ===== 28 | 29 | As of version 0.6.0, PseudoNode is a library (a.k.a. LibPseudoNode). The 30 | PseudoNode library can be used for many applications that would otherwise 31 | require a full node, but without the inconvenience of a large/slow blockchain 32 | download and sync. 33 | 34 | To create a basic Bitcoin PseudoNode using the library, simply call the 35 | function: 36 | 37 | struct PN *node = PN_create(NULL, NULL, NULL, 0); 38 | 39 | See the `pseudo_node.h` file for more detail documentation about the 40 | PseudoNode configuration. Various parameters can be controlled, such 41 | as: 42 | 43 | * Which cryptocurrency PseudoNode connects to (default is Bitcoin). 44 | * Protocol and node configuration (e.g. extra services bits). 45 | * Configuration to intercept various networks events, such as the broadcast 46 | of a new transaction or block. 47 | * Whether or not `PN_create` assumes control of the calling thread. 48 | 49 | The PseudoNode library supports a callbacks for various events. For example, 50 | to intercepting transactions can be achieved via the following pseudo-code: 51 | 52 | struct PN_callbacks CALLBACKS; 53 | memset(&CALLBACKS, 0, sizeof(CALLBACKS)); 54 | CALLBACKS.tx = tx_callback; // Set transaction call-back 55 | struct PN *node = PN_create(NULL, &CALLBACKS, NULL, 0); 56 | 57 | The function `tx_callback` will be called for each transaction broadcast on 58 | the network. See the sample application `apps/txmon` for an example of how 59 | this can be used to build a simple transaction monitor. 60 | 61 | In addition to the above, PseudoNode can broadcast raw transactions using 62 | using the following function call: 63 | 64 | PN_broadcast_tx(node, tx_data, tx_len); 65 | 66 | Reference Program 67 | ================= 68 | 69 | A reference PseudoNode is currently implemented as a command-line tool. 70 | 71 | By default it will connect to the Bitcoin network: 72 | 73 | pseudonode 74 | 75 | You can connect to different networks using the --coin=COIN option, e.g.: 76 | 77 | pseudonode --coin=testnet 78 | pseudonode --coin=litecoin 79 | pseudonode --coin=bitcoin-xt 80 | 81 | The current implementation supports the following cryptocurrencies: bitcoin, 82 | testnet (bitcoin), litecoin and bitcoin XT. 83 | 84 | To identify as a standard full node, add the `--stealth` option to the command 85 | line, e.g.: 86 | 87 | pseudonode --stealth 88 | 89 | By default, PseudoNode considers data (tx or blocks) valid if 2 other nodes 90 | also believe so. This value can be configured via the --threshold=VAL option, 91 | e.g.: 92 | 93 | pseudonode --threshold=3 94 | 95 | Higher values will slow the node down. Lower values make it more likely the 96 | node will relay erroneous data. The default of 2 is a good compromise. 97 | 98 | By default PseudoNode will fetch objects (txs and blocks) only if other nodes 99 | explicitly request for them. It is possible to configure PseudoNode to fetch 100 | objects immediately via the option: 101 | 102 | pseudonode --prefetch 103 | 104 | Note that enabling this option will cause PseudoNode to consume more bandwidth 105 | (on par with a normal full node). 106 | 107 | To run PseudoNode as a background process use the --server option. Currently 108 | only works for Linux: 109 | 110 | pseudonode --server 111 | 112 | Building 113 | ======== 114 | 115 | For Linux simply run make: 116 | 117 | make 118 | 119 | Windows can be built via Linux cross compilation and MinGW. Run the command: 120 | 121 | make -f Makefile.windows 122 | 123 | For MacOSX, run the command: 124 | 125 | make -f Makefile.macosx 126 | 127 | LICENSE 128 | ======= 129 | 130 | PseudoNode has been released under the MIT license: 131 | 132 | Permission is hereby granted, free of charge, to any person obtaining a 133 | copy of this software and associated documentation files (the "Software"), 134 | to deal in the Software without restriction, including without limitation 135 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 136 | and/or sell copies of the Software, and to permit persons to whom the 137 | Software is furnished to do so, subject to the following conditions: 138 | 139 | The above copyright notice and this permission notice shall be included in 140 | all copies or substantial portions of the Software. 141 | 142 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 143 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 144 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 145 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 146 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 147 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 148 | DEALINGS IN THE SOFTWARE. 149 | 150 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.7.0 2 | -------------------------------------------------------------------------------- /apps/txmon/Makefile: -------------------------------------------------------------------------------- 1 | CC = clang 2 | STRIP = strip 3 | OBJS = txmon.o 4 | CFLAGS = -std=gnu99 -DLINUX -I../../ -O2 -Wall -Wno-unused-value -fpic 5 | CLIBS = -L ../../ -lpseudonode -lpthread -ldl -Wl,-R. 6 | 7 | txmon: txmon.o 8 | $(CC) $(CFLAGS) -o txmon $(OBJS) $(CLIBS) 9 | $(STRIP) txmon 10 | cp txmon txmon.linux 11 | 12 | txmon.o: txmon.c 13 | 14 | clean: 15 | rm -f $(OBJS) txmon.o 16 | 17 | -------------------------------------------------------------------------------- /apps/txmon/Makefile.macosx: -------------------------------------------------------------------------------- 1 | CC = clang 2 | STRIP = strip 3 | OBJS = txmon.o 4 | CFLAGS = -std=gnu99 -DLINUX -I../../ -O2 -Wall -Wno-unused-value -fpic 5 | CLIBS = -L ../../ -lpseudonode -lpthread -ldl -Wl,-rpath -Wl,. 6 | 7 | txmon: txmon.o 8 | $(CC) $(CFLAGS) -o txmon $(OBJS) $(CLIBS) 9 | $(STRIP) txmon 10 | cp txmon txmon.macosx 11 | 12 | txmon.o: txmon.c 13 | 14 | clean: 15 | rm -f $(OBJS) txmon.o 16 | 17 | -------------------------------------------------------------------------------- /apps/txmon/Makefile.windows: -------------------------------------------------------------------------------- 1 | CC = x86_64-w64-mingw32-gcc 2 | WINDRES = x86_64-w64-mingw32-windres 3 | STRIP = x86_64-w64-mingw32-strip 4 | OBJS = txmon.o 5 | CFLAGS = -std=gnu99 -DWINDOWS -I../../ -O2 -Wno-unused-value -mthreads \ 6 | -mconsole -fpic 7 | CLIBS = -lws2_32 -lkernel32 -L../../ -lPseudoNode 8 | 9 | TxMon.exe: txmon.o 10 | $(WINDRES) txmon.rc -O coff -o txmon.res 11 | $(CC) $(CFLAGS) -o TxMon.exe $(OBJS) txmon.res $(CLIBS) 12 | $(STRIP) TxMon.exe 13 | 14 | txmon.o: txmon.c 15 | 16 | clean: 17 | rm -f $(OBJS) txmon.o 18 | 19 | -------------------------------------------------------------------------------- /apps/txmon/install.nsi: -------------------------------------------------------------------------------- 1 | ; Bitcoin TX Monitor installer 2 | ; Copyright (c) 2015 the copyright holders 3 | ; 4 | ; Permission is hereby granted, free of charge, to any person obtaining a 5 | ; copy of this software and associated documentation files (the "Software"), 6 | ; to deal in the Software without restriction, including without limitation 7 | ; the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | ; and/or sell copies of the Software, and to permit persons to whom the 9 | ; Software is furnished to do so, subject to the following conditions: 10 | ; 11 | ; The above copyright notice and this permission notice shall be included in 12 | ; all copies or substantial portions of the Software. 13 | ; 14 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | ; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | ; DEALINGS IN THE SOFTWARE. 21 | 22 | !include "MUI2.nsh" 23 | 24 | SetCompressor /SOLID /FINAL lzma 25 | 26 | Name "TxMon" 27 | OutFile "TxMon-install.exe" 28 | 29 | InstallDir "$PROGRAMFILES\TxMon\" 30 | 31 | !insertmacro MUI_PAGE_WELCOME 32 | !insertmacro MUI_PAGE_INSTFILES 33 | 34 | !insertmacro MUI_UNPAGE_CONFIRM 35 | !insertmacro MUI_UNPAGE_INSTFILES 36 | 37 | !insertmacro MUI_LANGUAGE "English" 38 | 39 | Section "" 40 | SetOutPath $INSTDIR 41 | File "TxMon.exe" 42 | File "PseudoNode.dll" 43 | File "miniupnpc.dll" 44 | File "LICENSE.txt" 45 | WriteUninstaller "TallowBundle-uninstall.exe" 46 | CreateShortCut "$DESKTOP\TxMon.lnk" "$INSTDIR\TxMon.exe" "" 47 | SectionEnd 48 | 49 | Section "Uninstall" 50 | Delete "$INSTDIR\TxMon.exe" 51 | Delete "$INSTDIR\PseudoNode.dll" 52 | Delete "$INSTDIR\miniupnpc.dll" 53 | Delete "$INSTDIR\LICENSE.txt" 54 | RMDir "$INSTDIR\" 55 | Delete "$DESKTOP\TxMon.lnk" 56 | SectionEnd 57 | 58 | -------------------------------------------------------------------------------- /apps/txmon/ripemd160.c: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (c) 2014 The Bitcoin Core developers 3 | // Distributed under the MIT software license, see the accompanying 4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 | 6 | #include 7 | #include 8 | 9 | /** Initialize RIPEMD-160 state. */ 10 | static void inline initialize(uint32_t* s) 11 | { 12 | s[0] = 0x67452301ul; 13 | s[1] = 0xEFCDAB89ul; 14 | s[2] = 0x98BADCFEul; 15 | s[3] = 0x10325476ul; 16 | s[4] = 0xC3D2E1F0ul; 17 | } 18 | 19 | static uint32_t inline f1(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; } 20 | static uint32_t inline f2(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); } 21 | static uint32_t inline f3(uint32_t x, uint32_t y, uint32_t z) { return (x | ~y) ^ z; } 22 | static uint32_t inline f4(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); } 23 | static uint32_t inline f5(uint32_t x, uint32_t y, uint32_t z) { return x ^ (y | ~z); } 24 | static uint32_t inline rol(uint32_t x, int i) { return (x << i) | (x >> (32 - i)); } 25 | static void inline round(uint32_t *a, uint32_t b, uint32_t *c, uint32_t d, uint32_t e, uint32_t f, uint32_t x, uint32_t k, int r) 26 | { 27 | *a = rol(*a + f + x + k, r) + e; 28 | *c = rol(*c, 10); 29 | } 30 | 31 | static void inline R11(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f1(b, *c, d), x, 0, r); } 32 | static void inline R21(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f2(b, *c, d), x, 0x5A827999ul, r); } 33 | static void inline R31(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f3(b, *c, d), x, 0x6ED9EBA1ul, r); } 34 | static void inline R41(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f4(b, *c, d), x, 0x8F1BBCDCul, r); } 35 | static void inline R51(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f5(b, *c, d), x, 0xA953FD4Eul, r); } 36 | static void inline R12(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f5(b, *c, d), x, 0x50A28BE6ul, r); } 37 | static void inline R22(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f4(b, *c, d), x, 0x5C4DD124ul, r); } 38 | static void inline R32(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f3(b, *c, d), x, 0x6D703EF3ul, r); } 39 | static void inline R42(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f2(b, *c, d), x, 0x7A6D76E9ul, r); } 40 | static void inline R52(uint32_t* a, uint32_t b, uint32_t* c, uint32_t d, uint32_t e, uint32_t x, int r) { round(a, b, c, d, e, f1(b, *c, d), x, 0, r); } 41 | 42 | #define read32(p) (*((uint32_t *)(p))) 43 | 44 | /** Perform a RIPEMD-160 transformation, processing a 64-byte chunk. */ 45 | static void transform(uint32_t* s, const unsigned char* chunk) 46 | { 47 | uint32_t a1 = s[0], b1 = s[1], c1 = s[2], d1 = s[3], e1 = s[4]; 48 | uint32_t a2 = a1, b2 = b1, c2 = c1, d2 = d1, e2 = e1; 49 | uint32_t w0 = read32(chunk + 0), w1 = read32(chunk + 4), w2 = read32(chunk + 8), w3 = read32(chunk + 12); 50 | uint32_t w4 = read32(chunk + 16), w5 = read32(chunk + 20), w6 = read32(chunk + 24), w7 = read32(chunk + 28); 51 | uint32_t w8 = read32(chunk + 32), w9 = read32(chunk + 36), w10 = read32(chunk + 40), w11 = read32(chunk + 44); 52 | uint32_t w12 = read32(chunk + 48), w13 = read32(chunk + 52), w14 = read32(chunk + 56), w15 = read32(chunk + 60); 53 | 54 | R11(&a1, b1, &c1, d1, e1, w0, 11); 55 | R12(&a2, b2, &c2, d2, e2, w5, 8); 56 | R11(&e1, a1, &b1, c1, d1, w1, 14); 57 | R12(&e2, a2, &b2, c2, d2, w14, 9); 58 | R11(&d1, e1, &a1, b1, c1, w2, 15); 59 | R12(&d2, e2, &a2, b2, c2, w7, 9); 60 | R11(&c1, d1, &e1, a1, b1, w3, 12); 61 | R12(&c2, d2, &e2, a2, b2, w0, 11); 62 | R11(&b1, c1, &d1, e1, a1, w4, 5); 63 | R12(&b2, c2, &d2, e2, a2, w9, 13); 64 | R11(&a1, b1, &c1, d1, e1, w5, 8); 65 | R12(&a2, b2, &c2, d2, e2, w2, 15); 66 | R11(&e1, a1, &b1, c1, d1, w6, 7); 67 | R12(&e2, a2, &b2, c2, d2, w11, 15); 68 | R11(&d1, e1, &a1, b1, c1, w7, 9); 69 | R12(&d2, e2, &a2, b2, c2, w4, 5); 70 | R11(&c1, d1, &e1, a1, b1, w8, 11); 71 | R12(&c2, d2, &e2, a2, b2, w13, 7); 72 | R11(&b1, c1, &d1, e1, a1, w9, 13); 73 | R12(&b2, c2, &d2, e2, a2, w6, 7); 74 | R11(&a1, b1, &c1, d1, e1, w10, 14); 75 | R12(&a2, b2, &c2, d2, e2, w15, 8); 76 | R11(&e1, a1, &b1, c1, d1, w11, 15); 77 | R12(&e2, a2, &b2, c2, d2, w8, 11); 78 | R11(&d1, e1, &a1, b1, c1, w12, 6); 79 | R12(&d2, e2, &a2, b2, c2, w1, 14); 80 | R11(&c1, d1, &e1, a1, b1, w13, 7); 81 | R12(&c2, d2, &e2, a2, b2, w10, 14); 82 | R11(&b1, c1, &d1, e1, a1, w14, 9); 83 | R12(&b2, c2, &d2, e2, a2, w3, 12); 84 | R11(&a1, b1, &c1, d1, e1, w15, 8); 85 | R12(&a2, b2, &c2, d2, e2, w12, 6); 86 | 87 | R21(&e1, a1, &b1, c1, d1, w7, 7); 88 | R22(&e2, a2, &b2, c2, d2, w6, 9); 89 | R21(&d1, e1, &a1, b1, c1, w4, 6); 90 | R22(&d2, e2, &a2, b2, c2, w11, 13); 91 | R21(&c1, d1, &e1, a1, b1, w13, 8); 92 | R22(&c2, d2, &e2, a2, b2, w3, 15); 93 | R21(&b1, c1, &d1, e1, a1, w1, 13); 94 | R22(&b2, c2, &d2, e2, a2, w7, 7); 95 | R21(&a1, b1, &c1, d1, e1, w10, 11); 96 | R22(&a2, b2, &c2, d2, e2, w0, 12); 97 | R21(&e1, a1, &b1, c1, d1, w6, 9); 98 | R22(&e2, a2, &b2, c2, d2, w13, 8); 99 | R21(&d1, e1, &a1, b1, c1, w15, 7); 100 | R22(&d2, e2, &a2, b2, c2, w5, 9); 101 | R21(&c1, d1, &e1, a1, b1, w3, 15); 102 | R22(&c2, d2, &e2, a2, b2, w10, 11); 103 | R21(&b1, c1, &d1, e1, a1, w12, 7); 104 | R22(&b2, c2, &d2, e2, a2, w14, 7); 105 | R21(&a1, b1, &c1, d1, e1, w0, 12); 106 | R22(&a2, b2, &c2, d2, e2, w15, 7); 107 | R21(&e1, a1, &b1, c1, d1, w9, 15); 108 | R22(&e2, a2, &b2, c2, d2, w8, 12); 109 | R21(&d1, e1, &a1, b1, c1, w5, 9); 110 | R22(&d2, e2, &a2, b2, c2, w12, 7); 111 | R21(&c1, d1, &e1, a1, b1, w2, 11); 112 | R22(&c2, d2, &e2, a2, b2, w4, 6); 113 | R21(&b1, c1, &d1, e1, a1, w14, 7); 114 | R22(&b2, c2, &d2, e2, a2, w9, 15); 115 | R21(&a1, b1, &c1, d1, e1, w11, 13); 116 | R22(&a2, b2, &c2, d2, e2, w1, 13); 117 | R21(&e1, a1, &b1, c1, d1, w8, 12); 118 | R22(&e2, a2, &b2, c2, d2, w2, 11); 119 | 120 | R31(&d1, e1, &a1, b1, c1, w3, 11); 121 | R32(&d2, e2, &a2, b2, c2, w15, 9); 122 | R31(&c1, d1, &e1, a1, b1, w10, 13); 123 | R32(&c2, d2, &e2, a2, b2, w5, 7); 124 | R31(&b1, c1, &d1, e1, a1, w14, 6); 125 | R32(&b2, c2, &d2, e2, a2, w1, 15); 126 | R31(&a1, b1, &c1, d1, e1, w4, 7); 127 | R32(&a2, b2, &c2, d2, e2, w3, 11); 128 | R31(&e1, a1, &b1, c1, d1, w9, 14); 129 | R32(&e2, a2, &b2, c2, d2, w7, 8); 130 | R31(&d1, e1, &a1, b1, c1, w15, 9); 131 | R32(&d2, e2, &a2, b2, c2, w14, 6); 132 | R31(&c1, d1, &e1, a1, b1, w8, 13); 133 | R32(&c2, d2, &e2, a2, b2, w6, 6); 134 | R31(&b1, c1, &d1, e1, a1, w1, 15); 135 | R32(&b2, c2, &d2, e2, a2, w9, 14); 136 | R31(&a1, b1, &c1, d1, e1, w2, 14); 137 | R32(&a2, b2, &c2, d2, e2, w11, 12); 138 | R31(&e1, a1, &b1, c1, d1, w7, 8); 139 | R32(&e2, a2, &b2, c2, d2, w8, 13); 140 | R31(&d1, e1, &a1, b1, c1, w0, 13); 141 | R32(&d2, e2, &a2, b2, c2, w12, 5); 142 | R31(&c1, d1, &e1, a1, b1, w6, 6); 143 | R32(&c2, d2, &e2, a2, b2, w2, 14); 144 | R31(&b1, c1, &d1, e1, a1, w13, 5); 145 | R32(&b2, c2, &d2, e2, a2, w10, 13); 146 | R31(&a1, b1, &c1, d1, e1, w11, 12); 147 | R32(&a2, b2, &c2, d2, e2, w0, 13); 148 | R31(&e1, a1, &b1, c1, d1, w5, 7); 149 | R32(&e2, a2, &b2, c2, d2, w4, 7); 150 | R31(&d1, e1, &a1, b1, c1, w12, 5); 151 | R32(&d2, e2, &a2, b2, c2, w13, 5); 152 | 153 | R41(&c1, d1, &e1, a1, b1, w1, 11); 154 | R42(&c2, d2, &e2, a2, b2, w8, 15); 155 | R41(&b1, c1, &d1, e1, a1, w9, 12); 156 | R42(&b2, c2, &d2, e2, a2, w6, 5); 157 | R41(&a1, b1, &c1, d1, e1, w11, 14); 158 | R42(&a2, b2, &c2, d2, e2, w4, 8); 159 | R41(&e1, a1, &b1, c1, d1, w10, 15); 160 | R42(&e2, a2, &b2, c2, d2, w1, 11); 161 | R41(&d1, e1, &a1, b1, c1, w0, 14); 162 | R42(&d2, e2, &a2, b2, c2, w3, 14); 163 | R41(&c1, d1, &e1, a1, b1, w8, 15); 164 | R42(&c2, d2, &e2, a2, b2, w11, 14); 165 | R41(&b1, c1, &d1, e1, a1, w12, 9); 166 | R42(&b2, c2, &d2, e2, a2, w15, 6); 167 | R41(&a1, b1, &c1, d1, e1, w4, 8); 168 | R42(&a2, b2, &c2, d2, e2, w0, 14); 169 | R41(&e1, a1, &b1, c1, d1, w13, 9); 170 | R42(&e2, a2, &b2, c2, d2, w5, 6); 171 | R41(&d1, e1, &a1, b1, c1, w3, 14); 172 | R42(&d2, e2, &a2, b2, c2, w12, 9); 173 | R41(&c1, d1, &e1, a1, b1, w7, 5); 174 | R42(&c2, d2, &e2, a2, b2, w2, 12); 175 | R41(&b1, c1, &d1, e1, a1, w15, 6); 176 | R42(&b2, c2, &d2, e2, a2, w13, 9); 177 | R41(&a1, b1, &c1, d1, e1, w14, 8); 178 | R42(&a2, b2, &c2, d2, e2, w9, 12); 179 | R41(&e1, a1, &b1, c1, d1, w5, 6); 180 | R42(&e2, a2, &b2, c2, d2, w7, 5); 181 | R41(&d1, e1, &a1, b1, c1, w6, 5); 182 | R42(&d2, e2, &a2, b2, c2, w10, 15); 183 | R41(&c1, d1, &e1, a1, b1, w2, 12); 184 | R42(&c2, d2, &e2, a2, b2, w14, 8); 185 | 186 | R51(&b1, c1, &d1, e1, a1, w4, 9); 187 | R52(&b2, c2, &d2, e2, a2, w12, 8); 188 | R51(&a1, b1, &c1, d1, e1, w0, 15); 189 | R52(&a2, b2, &c2, d2, e2, w15, 5); 190 | R51(&e1, a1, &b1, c1, d1, w5, 5); 191 | R52(&e2, a2, &b2, c2, d2, w10, 12); 192 | R51(&d1, e1, &a1, b1, c1, w9, 11); 193 | R52(&d2, e2, &a2, b2, c2, w4, 9); 194 | R51(&c1, d1, &e1, a1, b1, w7, 6); 195 | R52(&c2, d2, &e2, a2, b2, w1, 12); 196 | R51(&b1, c1, &d1, e1, a1, w12, 8); 197 | R52(&b2, c2, &d2, e2, a2, w5, 5); 198 | R51(&a1, b1, &c1, d1, e1, w2, 13); 199 | R52(&a2, b2, &c2, d2, e2, w8, 14); 200 | R51(&e1, a1, &b1, c1, d1, w10, 12); 201 | R52(&e2, a2, &b2, c2, d2, w7, 6); 202 | R51(&d1, e1, &a1, b1, c1, w14, 5); 203 | R52(&d2, e2, &a2, b2, c2, w6, 8); 204 | R51(&c1, d1, &e1, a1, b1, w1, 12); 205 | R52(&c2, d2, &e2, a2, b2, w2, 13); 206 | R51(&b1, c1, &d1, e1, a1, w3, 13); 207 | R52(&b2, c2, &d2, e2, a2, w13, 6); 208 | R51(&a1, b1, &c1, d1, e1, w8, 14); 209 | R52(&a2, b2, &c2, d2, e2, w14, 5); 210 | R51(&e1, a1, &b1, c1, d1, w11, 11); 211 | R52(&e2, a2, &b2, c2, d2, w0, 15); 212 | R51(&d1, e1, &a1, b1, c1, w6, 8); 213 | R52(&d2, e2, &a2, b2, c2, w3, 13); 214 | R51(&c1, d1, &e1, a1, b1, w15, 5); 215 | R52(&c2, d2, &e2, a2, b2, w9, 11); 216 | R51(&b1, c1, &d1, e1, a1, w13, 6); 217 | R52(&b2, c2, &d2, e2, a2, w11, 11); 218 | 219 | uint32_t t = s[0]; 220 | s[0] = s[1] + c1 + d2; 221 | s[1] = s[2] + d1 + e2; 222 | s[2] = s[3] + e1 + a2; 223 | s[3] = s[4] + a1 + b2; 224 | s[4] = t + b1 + c2; 225 | } 226 | 227 | ////// RIPEMD160 228 | 229 | typedef struct 230 | { 231 | uint32_t s[5]; 232 | unsigned char buf[64]; 233 | size_t bytes; 234 | } RIPEMD160_CTX; 235 | 236 | static void ripemd160_init(RIPEMD160_CTX *cxt) 237 | { 238 | cxt->bytes = 0; 239 | initialize(cxt->s); 240 | } 241 | 242 | static void ripemd160_update(RIPEMD160_CTX *cxt, const unsigned char* data, 243 | size_t len) 244 | { 245 | const unsigned char* end = data + len; 246 | size_t bufsize = cxt->bytes % 64; 247 | if (bufsize && bufsize + len >= 64) 248 | { 249 | // Fill the buffer, and process it. 250 | memcpy(cxt->buf + bufsize, data, 64 - bufsize); 251 | cxt->bytes += 64 - bufsize; 252 | data += 64 - bufsize; 253 | transform(cxt->s, cxt->buf); 254 | bufsize = 0; 255 | } 256 | while (end >= data + 64) 257 | { 258 | // Process full chunks directly from the source. 259 | transform(cxt->s, data); 260 | cxt->bytes += 64; 261 | data += 64; 262 | } 263 | if (end > data) 264 | { 265 | // Fill the buffer with what remains. 266 | memcpy(cxt->buf + bufsize, data, end - data); 267 | cxt->bytes += end - data; 268 | } 269 | } 270 | 271 | #define write64(p, v) (*((uint64_t *)(p)) = (v)) 272 | #define write32(p, v) (*((uint32_t *)(p)) = (v)) 273 | 274 | static void ripemd160_final(RIPEMD160_CTX *cxt, unsigned char *hash) 275 | { 276 | static const unsigned char pad[64] = {0x80}; 277 | unsigned char sizedesc[8]; 278 | write64(sizedesc, cxt->bytes << 3); 279 | ripemd160_update(cxt, pad, 1 + ((119 - (cxt->bytes % 64)) % 64)); 280 | ripemd160_update(cxt, sizedesc, 8); 281 | write32(hash, cxt->s[0]); 282 | write32(hash + 4, cxt->s[1]); 283 | write32(hash + 8, cxt->s[2]); 284 | write32(hash + 12, cxt->s[3]); 285 | write32(hash + 16, cxt->s[4]); 286 | } 287 | 288 | extern void ripemd160(const void *data, size_t len, void *res) 289 | { 290 | RIPEMD160_CTX cxt; 291 | ripemd160_init(&cxt); 292 | ripemd160_update(&cxt, data, len); 293 | ripemd160_final(&cxt, res); 294 | } 295 | 296 | -------------------------------------------------------------------------------- /apps/txmon/txmon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Bitcoin TX Monitor 3 | * Copyright (c) 2015 the copyright holders 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "pseudo_node.h" 34 | 35 | #include "ripemd160.c" 36 | 37 | typedef struct 38 | { 39 | uint8_t i8[32]; 40 | } hash256_t; 41 | 42 | static bool option_color = true; 43 | 44 | #define MAX(a, b) ((a) < (b)? (b): (a)) 45 | #define GET_BTC(x) ((double)(x) * 0.00000001) 46 | #define PERCENT(x, y) (((double)(x) / (double)(y)) * 100.0) 47 | 48 | static void hash160(const void *data, size_t len, uint8_t *hsh160) 49 | { 50 | uint8_t hsh256[32]; 51 | PN_sha256(data, len, hsh256); 52 | ripemd160(hsh256, sizeof(hsh256), hsh160); 53 | } 54 | 55 | /***************************************************************************/ 56 | /* CRUFT: */ 57 | /***************************************************************************/ 58 | 59 | #ifdef LINUX 60 | 61 | #include 62 | #include 63 | #include 64 | 65 | #define color_clear() if (option_color) fputs("\33[0m", stdout) 66 | #define color_value() if (option_color) fputs("\33[31m", stdout) 67 | #define color_input() if (option_color) fputs("\33[33m", stdout) 68 | #define color_output() if (option_color) fputs("\33[32m", stdout) 69 | #define color_hash() if (option_color) fputs("\33[34m", stdout) 70 | #define color_warning() if (option_color) fputs("\33[35m", stdout) 71 | 72 | typedef pthread_mutex_t mutex; 73 | 74 | static inline void mutex_init(mutex *m) 75 | { 76 | int res = pthread_mutex_init(m, NULL); 77 | assert(res == 0); 78 | } 79 | 80 | static inline void mutex_lock(mutex *m) 81 | { 82 | int res = pthread_mutex_lock(m); 83 | assert(res == 0); 84 | } 85 | 86 | static inline void mutex_unlock(mutex *m) 87 | { 88 | int res = pthread_mutex_unlock(m); 89 | assert(res == 0); 90 | } 91 | 92 | #endif /* LINUX */ 93 | 94 | #ifdef WINDOWS 95 | 96 | #include 97 | #include 98 | #include 99 | 100 | #define STDERR GetStdHandle(STD_ERROR_HANDLE) 101 | #define color_clear(_) SetConsoleTextAttribute(STDERR, FOREGROUND_RED | \ 102 | FOREGROUND_GREEN | FOREGROUND_BLUE) 103 | #define color_value(_) SetConsoleTextAttribute(STDERR, FOREGROUND_RED) 104 | #define color_input(_) SetConsoleTextAttribute(STDERR, FOREGROUND_RED | \ 105 | FOREGROUND_GREEN) 106 | #define color_output(_) SetConsoleTextAttribute(STDERR, FOREGROUND_GREEN) 107 | #define color_hash(_) SetConsoleTextAttribute(STDERR, FOREGROUND_BLUE) 108 | #define color_warning(_) SetConsoleTextAttribute(STDERR, FOREGROUND_RED | \ 109 | FOREGROUND_BLUE) 110 | 111 | extern const char *inet_ntop(int af, const void *src, char *dst, 112 | socklen_t size); 113 | 114 | typedef HANDLE mutex; 115 | 116 | static inline void mutex_init(mutex *m) 117 | { 118 | *m = CreateMutex(NULL, FALSE, NULL); 119 | assert(*m != NULL); 120 | } 121 | 122 | static inline void mutex_lock(mutex *m) 123 | { 124 | DWORD res = WaitForSingleObject(*m, INFINITE); 125 | assert(res == WAIT_OBJECT_0); 126 | } 127 | 128 | static inline void mutex_unlock(mutex *m) 129 | { 130 | BOOL res = ReleaseMutex(*m); 131 | assert(res); 132 | } 133 | 134 | #endif /* WINDOWS */ 135 | 136 | // Print mutex 137 | static mutex lock; 138 | 139 | /****************************************************************************/ 140 | /* RATES */ 141 | /****************************************************************************/ 142 | 143 | struct rate_info 144 | { 145 | time_t time; 146 | uint64_t value; 147 | size_t size; 148 | struct rate_info *next; 149 | }; 150 | 151 | static bool rate_init = false; 152 | static time_t rate_time0 = 0; 153 | static struct rate_info *rates; 154 | 155 | #define MIN(a, b) ((a) > (b)? (b): (a)) 156 | 157 | static void get_rate_info(time_t t, uint64_t v, size_t s, double *vps, 158 | double *sps, double *txps) 159 | { 160 | if (!rate_init) 161 | { 162 | rate_time0 = t; 163 | rate_init = true; 164 | } 165 | 166 | struct rate_info *info = 167 | (struct rate_info *)malloc(sizeof(struct rate_info)); 168 | assert(info != NULL); 169 | info->time = t; 170 | info->value = v; 171 | info->size = s; 172 | info->next = rates; 173 | rates = info; 174 | 175 | uint64_t total_v = 0; 176 | size_t total_tx = 0, total_s = 0; 177 | struct rate_info *prev = NULL; 178 | for (info = rates; info != NULL; info = info->next) 179 | { 180 | if (info->time + 60 < t) 181 | { 182 | // Old data: 183 | if (prev == NULL) 184 | rates = NULL; 185 | else 186 | prev->next = NULL; 187 | while (info != NULL) 188 | { 189 | prev = info; 190 | info = info->next; 191 | free(prev); 192 | } 193 | break; 194 | } 195 | total_v += info->value; 196 | total_tx++; 197 | total_s += info->size; 198 | prev = info; 199 | } 200 | double span = MIN(60.0, (double)(t - rate_time0)); 201 | span = (span == 0.0? 0.5: span); 202 | *vps = (total_v / span); 203 | *sps = (total_s / span); 204 | *txps = (total_tx / span); 205 | } 206 | 207 | /****************************************************************************/ 208 | /* STATS */ 209 | /****************************************************************************/ 210 | 211 | static size_t num_tx = 0; 212 | static size_t num_blocks = 0; 213 | static size_t num_tx_bytes = 0; 214 | static uint64_t total_val = 0; 215 | static bool option_verbose = false; 216 | static bool prev_msg = false; 217 | 218 | static size_t num_dice = 0; 219 | static size_t num_data = 0; 220 | static size_t num_dust = 0; 221 | static size_t num_spam = 0; 222 | 223 | /****************************************************************************/ 224 | /* TX PARSING */ 225 | /****************************************************************************/ 226 | 227 | // Data buffer. 228 | struct buf 229 | { 230 | const uint8_t *data; 231 | size_t ptr; 232 | size_t len; 233 | jmp_buf *env; 234 | }; 235 | 236 | // Pop data of `type' from the buffer. 237 | #define pop(buf, type) \ 238 | (((buf)->ptr + sizeof(type) <= (buf)->len? 0: \ 239 | longjmp(*(buf)->env, 1)), \ 240 | (buf)->ptr += sizeof(type), \ 241 | *(type *)((buf->data + (buf)->ptr - sizeof(type)))) 242 | 243 | // Pop a varint from the buffer. 244 | static uint64_t pop_varint(struct buf *buf) 245 | { 246 | uint8_t v8 = pop(buf, uint8_t); 247 | if (v8 < 0xFD) 248 | return (uint64_t)v8; 249 | else if (v8 == 0xFD) 250 | return (uint64_t)pop(buf, uint16_t); 251 | else if (v8 == 0xFE) 252 | return (uint64_t)pop(buf, uint32_t); 253 | else 254 | return pop(buf, uint64_t); 255 | } 256 | 257 | #define MAX_INPUTS 2500 258 | #define MAX_OUTPUTS 12000 259 | 260 | #define OP_PUSHDATA1 76 261 | #define OP_PUSHDATA2 77 262 | #define OP_DUP 118 263 | #define OP_HASH160 169 264 | #define OP_EQUAL 135 265 | #define OP_EQUALVERIFY 136 266 | #define OP_CHECKSIG 172 267 | #define OP_RETURN 106 268 | 269 | // Parse a transaction. 270 | static bool parse_tx(struct buf *buf, const uint8_t **ins, size_t *inlens, 271 | size_t *num_ins, const uint8_t **outs, size_t *outlens, uint64_t *outvals, 272 | size_t *num_outs) 273 | { 274 | pop(buf, uint32_t); // Version. 275 | size_t num_inputs = pop_varint(buf); // #inputs. 276 | if (num_ins != NULL) 277 | *num_ins = num_inputs; 278 | if (num_inputs == 0 || num_inputs >= MAX_INPUTS) 279 | return false; 280 | for (size_t i = 0; i < num_inputs; i++) 281 | { 282 | pop(buf, hash256_t); // UTXO hash. 283 | pop(buf, uint32_t); // UTXO index. 284 | size_t slen = pop_varint(buf); // scriptSig length. 285 | if (ins != NULL) 286 | ins[i] = buf->data + buf->ptr; 287 | if (inlens != NULL) 288 | inlens[i] = slen; 289 | for (size_t j = 0; j < slen; j++) 290 | pop(buf, uint8_t); 291 | pop(buf, uint32_t); // Sequence. 292 | } 293 | 294 | size_t num_outputs = pop_varint(buf); // #outputs. 295 | if (num_outs != NULL) 296 | *num_outs = num_outputs; 297 | if (num_outputs == 0 || num_outputs >= MAX_OUTPUTS) 298 | return false; 299 | for (size_t i = 0; i < num_outputs; i++) 300 | { 301 | uint64_t val = pop(buf, uint64_t); // Value. 302 | if (outvals != NULL) 303 | outvals[i] = val; 304 | size_t slen = pop_varint(buf); // scriptPubKey length. 305 | if (outs != NULL) 306 | outs[i] = buf->data + buf->ptr; 307 | if (outlens != NULL) 308 | outlens[i] = slen; 309 | for (size_t j = 0; j < slen; j++) 310 | pop(buf, uint8_t); 311 | } 312 | 313 | pop(buf, uint32_t); // nLockTime. 314 | return true; 315 | } 316 | 317 | // Test if a scriptSig is a P2PKH input: 318 | static bool script_is_p2pkh_input(const uint8_t *script, size_t slen, 319 | uint8_t *pub_key) 320 | { 321 | if (slen == 0) 322 | return false; 323 | size_t i = 0; 324 | if (script[i] < 0x09 || script[i] > 73) 325 | return false; 326 | i += script[i] + 1; 327 | if (i >= slen) 328 | return false; 329 | size_t len = script[i]; 330 | if (len != 33 && len != 65) 331 | return false; 332 | i++; 333 | if (i + len != slen) 334 | return false; 335 | for (size_t j = 0; j < len; j++) 336 | pub_key[j] = script[i + j]; 337 | return true; 338 | } 339 | 340 | // Test if a scriptSig is a P2SH input: 341 | static bool script_is_p2sh_input(const uint8_t *script, size_t slen, 342 | uint8_t *redeem, size_t *rlen) 343 | { 344 | ssize_t found = -1, len = 0; 345 | for (size_t i = 0; i < slen; ) 346 | { 347 | uint8_t op = script[i]; 348 | if (op < 76) 349 | { 350 | i++; 351 | len = op; 352 | } 353 | else if (op == OP_PUSHDATA1) 354 | { 355 | i++; 356 | if (i >= slen) 357 | return false; 358 | len = script[i]; 359 | i++; 360 | } 361 | else if (op == OP_PUSHDATA2) 362 | { 363 | i++; 364 | if (i + 1 >= slen) 365 | return false; 366 | len = *(uint16_t *)(script + i); 367 | i += 2; 368 | } 369 | else 370 | return false; 371 | if (i + len > slen) 372 | return false; 373 | if (i + len == slen) 374 | { 375 | found = i; 376 | break; 377 | } 378 | i += len; 379 | } 380 | if (found < 0) 381 | return false; 382 | if (len > 520) 383 | return false; 384 | for (size_t i = 0; i < len; i++) 385 | redeem[i] = script[found+i]; 386 | *rlen = (size_t)len; 387 | return true; 388 | } 389 | 390 | // Test if a scriptPubKey is a P2PKH output: 391 | static bool script_is_p2pkh_output(const uint8_t *script, size_t slen, 392 | uint8_t *pub_key_hash) 393 | { 394 | if (slen != 25) 395 | return false; 396 | if (script[0] != OP_DUP || script[1] != OP_HASH160 || script[2] != 0x14 || 397 | script[23] != OP_EQUALVERIFY || script[24] != OP_CHECKSIG) 398 | return false; 399 | for (int i = 0; i < 20; i++) 400 | pub_key_hash[i] = script[i + 3]; 401 | return true; 402 | } 403 | 404 | // Test if a scripePubKey is a legacy P2PK output: 405 | static bool script_is_p2pk_output(const uint8_t *script, size_t slen, 406 | uint8_t *pub_key_hash) 407 | { 408 | if (slen != 35 && slen != 67) 409 | return false; 410 | if (script[slen-1] != OP_CHECKSIG) 411 | return false; 412 | switch (script[0]) 413 | { 414 | case 33: 415 | hash160(script+1, 33, pub_key_hash); 416 | return true; 417 | case 65: 418 | hash160(script+1, 65, pub_key_hash); 419 | return true; 420 | default: 421 | return false; 422 | } 423 | } 424 | 425 | // Test if a scriptPubKey is a P2SH output: 426 | static bool script_is_p2sh_output(const uint8_t *script, size_t slen, 427 | uint8_t *script_hash) 428 | { 429 | if (slen != 23) 430 | return false; 431 | if (script[0] != OP_HASH160 || script[1] != 0x14 || script[22] != OP_EQUAL) 432 | return false; 433 | for (int i = 0; i < 20; i++) 434 | script_hash[i] = script[i + 2]; 435 | return true; 436 | } 437 | 438 | // Test if a scriptPubKey is data: 439 | static bool script_is_data_output(const uint8_t *script, size_t slen, 440 | uint8_t *data, size_t *dlen) 441 | { 442 | if (slen == 0) 443 | return false; 444 | if (script[0] != OP_RETURN) 445 | return false; 446 | if (slen == 1) 447 | goto strange; 448 | uint8_t op = script[1]; 449 | if (op > 0 && op < 76) 450 | { 451 | if (1 + op + 1 != slen) 452 | goto strange; 453 | for (size_t i = 0; i < op; i++) 454 | data[i] = script[1 + 1 + i]; 455 | *dlen = op; 456 | return true; 457 | } 458 | 459 | strange: 460 | *dlen = 0; 461 | return true; 462 | } 463 | 464 | /***************************************************************************/ 465 | /* TESTS */ 466 | /***************************************************************************/ 467 | 468 | static bool test_is_dice(const char *addr) 469 | { 470 | const char *prefixes[] = 471 | { 472 | "1Lucky", 473 | "1bones", 474 | "1change", 475 | "1dice", 476 | "1bank" 477 | }; 478 | for (size_t i = 0; i < sizeof(prefixes) / sizeof(prefixes[0]); i++) 479 | { 480 | if (strncmp(addr, prefixes[i], strlen(prefixes[i])) == 0) 481 | return true; 482 | } 483 | return false; 484 | } 485 | 486 | static bool test_is_dust(uint64_t val) 487 | { 488 | return GET_BTC(val) <= 0.00005; /* = USD$0.01 */ 489 | } 490 | 491 | /***************************************************************************/ 492 | /* OUTPUT */ 493 | /***************************************************************************/ 494 | 495 | /* 496 | * Base58 encode 497 | */ 498 | static const char* base58str = 499 | "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 500 | static bool base58_encode(char *str, size_t slen, const uint8_t *data, 501 | size_t dlen) 502 | { 503 | size_t i = 0; 504 | for (; i < dlen && data[i] == 0x0; i++) 505 | ; 506 | size_t zeroes = i; // Retained zeroes. 507 | char b58[(dlen - i) * 138 / 100 + 1]; 508 | memset(b58, 0, sizeof(b58)); 509 | for (; i < dlen; i++) 510 | { 511 | int carry = (int)data[i]; 512 | for (ssize_t j = sizeof(b58)-1; j >= 0; j--) 513 | { 514 | carry += 256 * b58[j]; 515 | b58[j] = carry % 58; 516 | carry /= 58; 517 | } 518 | assert(carry == 0); 519 | } 520 | for (i = 0; i < sizeof(b58) && b58[i] == 0; i++) 521 | ; 522 | size_t zeroes2 = i; // Dropped zeroes. 523 | if (zeroes + sizeof(b58) - zeroes2 + 1 > slen) 524 | return false; 525 | memset(str, '1', zeroes); 526 | size_t j; 527 | for (j = zeroes; i < sizeof(b58); i++, j++) 528 | str[j] = base58str[(size_t)b58[i]]; 529 | str[j] = '\0'; 530 | return true; 531 | } 532 | 533 | /* 534 | * Base58check encode. 535 | */ 536 | static bool base58check_encode(char *str, size_t slen, const uint8_t *data, 537 | size_t dlen) 538 | { 539 | uint8_t res[32]; 540 | PN_sha256d(data, dlen, res); 541 | uint8_t tmp[dlen + 4]; 542 | memcpy(tmp, data, dlen); 543 | tmp[dlen+0] = res[0]; 544 | tmp[dlen+1] = res[1]; 545 | tmp[dlen+2] = res[2]; 546 | tmp[dlen+3] = res[3]; 547 | return base58_encode(str, slen, tmp, sizeof(tmp)); 548 | } 549 | 550 | /* 551 | * Create an output address. 552 | */ 553 | static void make_output_addr(uint8_t *hsh160, uint8_t prefix, char *addr) 554 | { 555 | uint8_t tmp[1 + 20]; 556 | tmp[0] = prefix; 557 | memcpy(tmp+1, hsh160, 20); 558 | base58check_encode(addr, 35, tmp, sizeof(tmp)); 559 | } 560 | 561 | /* 562 | * Create an input address. 563 | */ 564 | static void make_input_addr(uint8_t *object, size_t olen, uint8_t prefix, 565 | char *addr) 566 | { 567 | uint8_t hsh160[20]; 568 | hash160(object, olen, hsh160); 569 | make_output_addr(hsh160, prefix, addr); 570 | } 571 | 572 | /* 573 | * Print a transaction. 574 | */ 575 | static void print_tx(struct PN *node, const uint8_t *tx, size_t len) 576 | { 577 | const uint8_t *ins[MAX_INPUTS]; 578 | size_t inlens[MAX_INPUTS]; 579 | const uint8_t *outs[MAX_OUTPUTS]; 580 | size_t outlens[MAX_OUTPUTS]; 581 | uint64_t outvals[MAX_OUTPUTS]; 582 | 583 | jmp_buf env; 584 | struct buf buf0 = {tx, 0, len, &env}; 585 | struct buf *buf = &buf0; 586 | if (setjmp(env)) 587 | { 588 | parse_error: 589 | fprintf(stderr, "error: unable to parse transaction\n"); 590 | return; 591 | } 592 | 593 | size_t num_ins, num_outs; 594 | if (!parse_tx(buf, ins, inlens, &num_ins, outs, outlens, outvals, 595 | &num_outs)) 596 | goto parse_error; 597 | 598 | // Formatting constraints: 599 | size_t lines = MAX(num_ins, num_outs); 600 | size_t in_d = lines - num_ins; 601 | size_t out_d = lines - num_outs; 602 | size_t in_s = 0 + in_d / 2; 603 | size_t in_e = lines - (in_d + 1) / 2; 604 | size_t out_s = 0 + out_d / 2; 605 | size_t out_e = lines - (out_d + 1) / 2; 606 | 607 | time_t t = time(NULL); 608 | 609 | bool is_dice = false; 610 | bool is_data = false; 611 | size_t num_dust_outputs = 0; 612 | size_t num_outputs = 0; 613 | uint64_t tx_val = 0; 614 | 615 | mutex_lock(&lock); 616 | 617 | putchar('\n'); 618 | num_tx++; 619 | num_tx_bytes += len; 620 | for (size_t i = 0; i < lines; i++) 621 | { 622 | if (i >= in_s && i < in_e) 623 | { 624 | size_t idx = i - in_s; 625 | uint8_t pub_key[65]; 626 | uint8_t script[520]; 627 | size_t script_len; 628 | char addr[35]; 629 | addr[0] = '\0'; 630 | if (script_is_p2pkh_input(ins[idx], inlens[idx], pub_key)) 631 | { 632 | size_t pub_key_len = (pub_key[0] == 0x04? 65: 33); 633 | make_input_addr(pub_key, pub_key_len, 0x00, addr); 634 | } 635 | else if (script_is_p2sh_input(ins[idx], inlens[idx], script, 636 | &script_len)) 637 | make_input_addr(script, script_len, 0x05, addr); 638 | 639 | if (addr[0] != '\0') 640 | { 641 | is_dice = is_dice || test_is_dice(addr); 642 | color_input(); 643 | printf("%s", addr); 644 | color_clear(); 645 | size_t len = strlen(addr); 646 | for (size_t j = 0; j < 34 - len; j++) 647 | putchar(' '); 648 | } 649 | else 650 | printf("[UNKNOWN] "); 651 | } 652 | else 653 | { 654 | for (size_t i = 0; i < 34; i++) 655 | putchar(' '); 656 | } 657 | putchar(' '); 658 | 659 | if (i >= out_s && i < out_e) 660 | { 661 | size_t idx = i - out_s; 662 | uint8_t hsh160[20]; 663 | char addr[35]; 664 | uint8_t data[80]; 665 | size_t dlen; 666 | bool is_data_out = false; 667 | addr[0] = '\0'; 668 | if (script_is_p2pkh_output(outs[idx], outlens[idx], hsh160)) 669 | make_output_addr(hsh160, 0x00, addr); 670 | else if (script_is_p2pk_output(outs[idx], outlens[idx], hsh160)) 671 | make_output_addr(hsh160, 0x00, addr); 672 | else if (script_is_p2sh_output(outs[idx], outlens[idx], hsh160)) 673 | make_output_addr(hsh160, 0x05, addr); 674 | else if (script_is_data_output(outs[idx], outlens[idx], data, 675 | &dlen)) 676 | is_data_out = true; 677 | 678 | if (addr[0] != '\0') 679 | { 680 | is_dice = is_dice || test_is_dice(addr); 681 | num_outputs++; 682 | num_dust_outputs += test_is_dust(outvals[idx]); 683 | color_output(); 684 | printf("%s", addr); 685 | color_clear(); 686 | size_t len = strlen(addr); 687 | for (size_t j = 0; j < 34 - len; j++) 688 | putchar(' '); 689 | } 690 | else if (is_data_out) 691 | { 692 | is_data = true; 693 | color_output(); 694 | printf("[DATA] \""); 695 | size_t space = 26, j; 696 | for (j = 0; j < dlen && j < 22; j++) 697 | { 698 | if (isprint(data[j])) 699 | putchar(data[j]); 700 | else 701 | putchar('?'); 702 | space--; 703 | } 704 | if (j < dlen) 705 | { 706 | printf("..."); 707 | space -= 3; 708 | } 709 | putchar('\"'); 710 | space--; 711 | for (j = 0; j < space; j++) 712 | putchar(' '); 713 | color_clear(); 714 | } 715 | else 716 | printf("[UNKNOWN] "); 717 | 718 | // The following is complicated way to ensure the number fits: 719 | color_value(); 720 | tx_val += outvals[idx]; 721 | double val = GET_BTC(outvals[idx]); 722 | double btc_val = (double)(unsigned)(val); 723 | char buf[32]; 724 | size_t len = snprintf(buf, sizeof(buf)-1, "%u", (unsigned)btc_val); 725 | if (len > 8) 726 | { 727 | printf("UNKNOWN\n"); 728 | color_clear(); 729 | continue; 730 | } 731 | printf(" %s", buf); 732 | double mant = val - btc_val; 733 | if (mant == 0.0) 734 | { 735 | color_clear(); 736 | putchar('\n'); 737 | continue; 738 | } 739 | size_t prec = 8 - len; 740 | switch (prec) 741 | { 742 | case 1: 743 | len = snprintf(buf, sizeof(buf)-1, "%.1f", mant); 744 | break; 745 | case 2: 746 | len = snprintf(buf, sizeof(buf)-1, "%.2f", mant); 747 | break; 748 | case 3: 749 | len = snprintf(buf, sizeof(buf)-1, "%.3f", mant); 750 | break; 751 | case 4: 752 | len = snprintf(buf, sizeof(buf)-1, "%.4f", mant); 753 | break; 754 | case 5: 755 | len = snprintf(buf, sizeof(buf)-1, "%.5f", mant); 756 | break; 757 | case 6: 758 | len = snprintf(buf, sizeof(buf)-1, "%.6f", mant); 759 | break; 760 | case 7: 761 | len = snprintf(buf, sizeof(buf)-1, "%.7f", mant); 762 | break; 763 | case 8: 764 | len = snprintf(buf, sizeof(buf)-1, "%.8f", mant); 765 | break; 766 | default: 767 | buf[1] = '\0'; 768 | len = 0; 769 | break; 770 | } 771 | while (len >= 2 && buf[len-1] == '0') 772 | { 773 | buf[len-1] = '\0'; 774 | len--; 775 | } 776 | printf("%s", buf+1); 777 | color_clear(); 778 | } 779 | putchar('\n'); 780 | } 781 | num_dice += is_dice; 782 | num_data += is_data; 783 | bool is_spam = false; 784 | if (num_dust_outputs > 0 && num_dust_outputs >= num_outputs-1) 785 | { 786 | num_dust++; 787 | if (num_outputs >= 8) 788 | is_spam = true; // Tx creating lots of dust outputs. 789 | } 790 | if (test_is_dust((tx_val * 1000) / (double)len)) 791 | is_spam = true; // Big tx for small value. 792 | num_spam += is_spam; 793 | 794 | if (option_verbose) 795 | { 796 | printf("NODE : height=%u in=%u out=%u sent=%.2gMB recv=%.2gMB\n", 797 | PN_get_info(node, PN_HEIGHT), 798 | PN_get_info(node, PN_NUM_IN_PEERS), 799 | PN_get_info(node, PN_NUM_OUT_PEERS), 800 | (double)PN_get_info(node, PN_NUM_SEND_BYTES) / 1000000.0, 801 | (double)PN_get_info(node, PN_NUM_RECV_BYTES) / 1000000.0); 802 | printf("TX : hash="); 803 | hash256_t hash; 804 | PN_sha256d(tx, len, &hash); 805 | for (size_t i = 0; i < sizeof(hash); i++) 806 | printf("%.2x", hash.i8[32 - i - 1]); 807 | total_val += tx_val; 808 | printf("\n size=%uB inputs=%u outputs=%u val=%gBTC\n", 809 | (unsigned)len, (unsigned)num_ins, (unsigned)num_outs, 810 | GET_BTC(tx_val)); 811 | unsigned time_passed = time(NULL) - rate_time0; 812 | printf("TOTAL: #block=%u size=%uB val=%gBTC time=%us\n", 813 | (unsigned)num_blocks, (unsigned)num_tx_bytes, GET_BTC(total_val), 814 | time_passed); 815 | printf(" : #tx=%u #dice=%u %.2g%% #data=%u %.2g%% " 816 | "#dust=%u %.2g%% #spam=%u %.2g%%\n", (unsigned)num_tx, 817 | (unsigned)num_dice, PERCENT(num_dice, num_tx), 818 | (unsigned)num_data, PERCENT(num_data, num_tx), 819 | (unsigned)num_dust, PERCENT(num_dust, num_tx), 820 | (unsigned)num_spam, PERCENT(num_spam, num_tx)); 821 | double vps, sps, txps; 822 | get_rate_info(t, tx_val, len, &vps, &sps, &txps); 823 | printf("RATES: tx/s=%.3g bytes/s=%g BTC/s=%g\n", 824 | txps, sps, GET_BTC(vps)); 825 | } 826 | prev_msg = false; 827 | mutex_unlock(&lock); 828 | } 829 | 830 | #define MAX_BLOCK_TXS 50000 831 | 832 | /* 833 | * Print a block. 834 | */ 835 | static void print_block(struct PN *node, const uint8_t *block, size_t len) 836 | { 837 | const size_t hdrlen = 80; 838 | jmp_buf env; 839 | struct buf buf0 = {block + hdrlen, 0, len - hdrlen, &env}; 840 | struct buf *buf = &buf0; 841 | if (len <= hdrlen || setjmp(env)) 842 | { 843 | parse_error: 844 | fprintf(stderr, "error: unable to parse block\n"); 845 | return; 846 | } 847 | 848 | size_t num_tx = pop_varint(buf); 849 | if (num_tx >= MAX_BLOCK_TXS) 850 | goto parse_error; 851 | 852 | hash256_t hashes[num_tx]; 853 | for (size_t i = 0; i < num_tx; i++) 854 | { 855 | size_t start = buf->ptr; 856 | if (!parse_tx(buf, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) 857 | goto parse_error; 858 | size_t end = buf->ptr; 859 | PN_sha256d(buf->data + start, end - start, hashes + i); 860 | } 861 | 862 | mutex_lock(&lock); 863 | num_blocks++; 864 | putchar('\n'); 865 | printf(" " 866 | "+----------------------------------------------------------------+\n"); 867 | for (size_t i = 0; i < num_tx; i++) 868 | { 869 | printf(" |"); 870 | color_hash(); 871 | for (size_t j = 0; j < 32; j++) 872 | printf("%.2x", hashes[i].i8[32 - j - 1]); 873 | color_clear(); 874 | printf("|\n"); 875 | } 876 | printf(" " 877 | "+----------------------------------------------------------------+\n"); 878 | if (option_verbose) 879 | { 880 | printf("NODE : height=%u in=%u out=%u sent=%.2gMB recv=%.2gMB\n", 881 | PN_get_info(node, PN_HEIGHT), 882 | PN_get_info(node, PN_NUM_IN_PEERS), 883 | PN_get_info(node, PN_NUM_OUT_PEERS), 884 | (double)PN_get_info(node, PN_NUM_SEND_BYTES) / 1000000.0, 885 | (double)PN_get_info(node, PN_NUM_RECV_BYTES) / 1000000.0); 886 | printf("BLOCK: hash="); 887 | hash256_t hash; 888 | PN_sha256d(block, 80, &hash); 889 | for (size_t i = 0; i < sizeof(hash); i++) 890 | printf("%.2x", hash.i8[32 - i - 1]); 891 | printf("\n size=%uB #tx=%u\n", (unsigned)len, (unsigned)num_tx); 892 | printf("TOTAL: #tx=%u #block=%u size=%uB val=%gBTC\n", 893 | (unsigned)num_tx, (unsigned)num_blocks, (unsigned)num_tx_bytes, 894 | GET_BTC(total_val)); 895 | } 896 | prev_msg = false; 897 | mutex_unlock(&lock); 898 | } 899 | 900 | /* 901 | * Print a message. 902 | */ 903 | static void print_msg(struct in6_addr addr, const char *msg) 904 | { 905 | char name[INET6_ADDRSTRLEN+1]; 906 | inet_ntop(AF_INET6, &addr, name, sizeof(name)); 907 | mutex_lock(&lock); 908 | if (!prev_msg) 909 | putchar('\n'); 910 | color_warning(); 911 | printf("warning"); 912 | color_clear(); 913 | printf(": [%s] %s\n", name, msg); 914 | prev_msg = true; 915 | mutex_unlock(&lock); 916 | } 917 | 918 | // Transaction callback 919 | static unsigned char *tx_callback(struct PN *node, int type, 920 | struct in6_addr addr, unsigned char *data, unsigned *len) 921 | { 922 | print_tx(node, (uint8_t *)data, (size_t)*len); 923 | return data; 924 | } 925 | 926 | // Block callback 927 | static unsigned char *block_callback(struct PN *node, int type, 928 | struct in6_addr addr, unsigned char *data, unsigned *len) 929 | { 930 | print_block(node, (uint8_t *)data, (size_t)*len); 931 | return data; 932 | } 933 | 934 | // Message callback 935 | static unsigned char *msg_callback(struct PN *node, int type, 936 | struct in6_addr addr, unsigned char *data, unsigned *len) 937 | { 938 | print_msg(addr, (const char *)data); 939 | return data; 940 | } 941 | 942 | #include 943 | #define OPTION_HELP 1 944 | #define OPTION_STEALTH 2 945 | #define OPTION_VERBOSE 3 946 | 947 | // Main: 948 | int main(int argc, char **argv) 949 | { 950 | mutex_init(&lock); 951 | 952 | static const struct option long_options[] = 953 | { 954 | {"help", 0, 0, OPTION_HELP}, 955 | {"stealth", 0, 0, OPTION_STEALTH}, 956 | {"verbose", 0, 0, OPTION_VERBOSE}, 957 | {NULL, 0, 0, 0} 958 | }; 959 | bool option_stealth = false; 960 | while (true) 961 | { 962 | int idx; 963 | int opt = getopt_long(argc, argv, "", long_options, &idx); 964 | if (opt < 0) 965 | break; 966 | switch (opt) 967 | { 968 | case OPTION_STEALTH: 969 | option_stealth = true; 970 | break; 971 | case OPTION_VERBOSE: 972 | option_verbose = true; 973 | break; 974 | case OPTION_HELP: 975 | default: 976 | fprintf(stderr, "usage: %s [--help] [--stealth] " 977 | "[--verbose]\n", argv[0]); 978 | fprintf(stderr, "WHERE:\n"); 979 | fprintf(stderr, "\t--stealth\n"); 980 | fprintf(stderr, "\t\tIdentify as a normal client " 981 | "(default=false).\n"); 982 | fprintf(stderr, "\t--verbose\n"); 983 | fprintf(stderr, "\t\tPrint more detailed information " 984 | "(default=false).\n"); 985 | return 0; 986 | } 987 | } 988 | if (!isatty(1)) 989 | option_color = false; 990 | 991 | struct PN_callbacks CALLBACKS; 992 | memset(&CALLBACKS, 0, sizeof(CALLBACKS)); 993 | CALLBACKS.tx = tx_callback; 994 | CALLBACKS.block = block_callback; 995 | if (option_verbose) 996 | CALLBACKS.warning = msg_callback; 997 | 998 | struct PN_config CONFIG; 999 | memset(&CONFIG, 0, sizeof(CONFIG)); 1000 | if (option_stealth) 1001 | CONFIG.user_agent = "/Satoshi:0.11.0/"; 1002 | else 1003 | CONFIG.user_agent = "/TXMON:0.1.0/PseudoNode:0.6.0/"; 1004 | CONFIG.prefetch = true; 1005 | 1006 | unsigned ret = 0; // Don't return. 1007 | PN_create(NULL, &CALLBACKS, &CONFIG, ret); 1008 | 1009 | return 0; 1010 | } 1011 | 1012 | -------------------------------------------------------------------------------- /apps/txmon/txmon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basil00/PseudoNode/ba8d329d154e639f0a767fc25a2a3576cc2895b8/apps/txmon/txmon.ico -------------------------------------------------------------------------------- /apps/txmon/txmon.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * Bitcoin TX Monitor 3 | * Copyright (c) 2015 the copyright holders 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "winuser.h" 25 | 26 | IDI_APPLICATION ICON "txmon.ico" 27 | 28 | -------------------------------------------------------------------------------- /linux.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PseudoNode 3 | * Copyright (c) 2015 the copyright holders 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | // Linux cruft: 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #ifdef MACOSX 40 | #define s6_addr16 __u6_addr.__u6_addr16 41 | #define MSG_NOSIGNAL 0 42 | #define MAP_ANONYMOUS MAP_ANON 43 | #endif 44 | 45 | #define get_error() strerror(errno) 46 | 47 | static bool system_init(void) 48 | { 49 | return true; 50 | } 51 | 52 | static bool rand_init(uint64_t *r) 53 | { 54 | FILE *stream = fopen("/dev/urandom", "r"); 55 | if (stream == NULL) 56 | return false; 57 | bool ok = (fread(r, sizeof(uint64_t), 2, stream) == 2); 58 | fclose(stream); 59 | return ok; 60 | } 61 | 62 | typedef pthread_mutex_t mutex; 63 | 64 | static inline void mutex_init(mutex *m) 65 | { 66 | int res = pthread_mutex_init(m, NULL); 67 | assert(res == 0); 68 | } 69 | 70 | static inline void mutex_free(mutex *m) 71 | { 72 | int res = pthread_mutex_destroy(m); 73 | assert(res == 0); 74 | } 75 | 76 | static inline void mutex_lock(mutex *m) 77 | { 78 | int res = pthread_mutex_lock(m); 79 | assert(res == 0); 80 | } 81 | 82 | static inline void mutex_unlock(mutex *m) 83 | { 84 | int res = pthread_mutex_unlock(m); 85 | assert(res == 0); 86 | } 87 | 88 | static inline void msleep(size_t ms) 89 | { 90 | usleep(ms * 1000); 91 | } 92 | 93 | // Implementation of Windows-style events in pthreads: 94 | struct event 95 | { 96 | pthread_mutex_t mutex; 97 | pthread_cond_t cond; 98 | bool set; 99 | }; 100 | typedef struct event event; 101 | 102 | static void event_init(event *e) 103 | { 104 | mutex_init(&e->mutex); 105 | int res; 106 | pthread_condattr_t attr; 107 | pthread_condattr_init(&attr); 108 | #ifndef MACOSX 109 | res = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 110 | assert(res == 0); 111 | #endif 112 | res = pthread_cond_init(&e->cond, &attr); 113 | assert(res == 0); 114 | e->set = false; 115 | } 116 | 117 | static bool event_wait(event *e) 118 | { 119 | struct timespec ts; 120 | #ifndef MACOSX 121 | clock_gettime(CLOCK_MONOTONIC, &ts); 122 | #else 123 | struct timeval tv; 124 | int res = gettimeofday(&tv, NULL); 125 | assert(res == 0); 126 | ts.tv_sec = tv.tv_sec; 127 | ts.tv_nsec = 1000 * tv.tv_usec; 128 | #endif 129 | ts.tv_sec += 2; 130 | mutex_lock(&e->mutex); 131 | while (!e->set) 132 | { 133 | int res = pthread_cond_timedwait(&e->cond, &e->mutex, &ts); 134 | if (res == ETIMEDOUT) 135 | { 136 | mutex_unlock(&e->mutex); 137 | return false; 138 | } 139 | } 140 | e->set = false; 141 | mutex_unlock(&e->mutex); 142 | return true; 143 | } 144 | 145 | static void event_set(event *e) 146 | { 147 | mutex_lock(&e->mutex); 148 | e->set = true; 149 | mutex_unlock(&e->mutex); 150 | int res = pthread_cond_signal(&e->cond); 151 | assert(res == 0); 152 | } 153 | 154 | static inline void event_free(event *e) 155 | { 156 | mutex_free(&e->mutex); 157 | int res = pthread_cond_destroy(&e->cond); 158 | assert(res == 0); 159 | } 160 | 161 | static bool spawn_thread(void *(f)(void *), void *arg) 162 | { 163 | pthread_t thread; 164 | int res = pthread_create(&thread, NULL, f, (void *)arg); 165 | if (res != 0) 166 | return false; 167 | res = pthread_detach(thread); 168 | assert(res == 0); 169 | return true; 170 | } 171 | 172 | typedef int sock; 173 | #define INVALID_SOCKET (-1) 174 | 175 | static sock socket_open(void) 176 | { 177 | sock s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 178 | if (s < 0) 179 | return INVALID_SOCKET; 180 | int on = 1; 181 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); 182 | setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&on, sizeof(on)); 183 | struct timeval tv; 184 | tv.tv_sec = 120; // 2 minutes 185 | tv.tv_usec = 0; 186 | setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); 187 | return s; 188 | } 189 | 190 | static bool socket_bind(sock s, uint16_t port) 191 | { 192 | struct sockaddr_in6 sockaddr; 193 | memset(&sockaddr, 0, sizeof(sockaddr)); 194 | sockaddr.sin6_family = AF_INET6; 195 | sockaddr.sin6_port = port; 196 | if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0) 197 | return false; 198 | return true; 199 | } 200 | 201 | static bool socket_listen(sock s) 202 | { 203 | return (listen(s, 4) == 0); 204 | } 205 | 206 | static sock socket_accept(sock s, struct in6_addr *addr) 207 | { 208 | socklen_t len = sizeof(struct sockaddr_in6); 209 | struct sockaddr_in6 sockaddr; 210 | int s1 = accept(s, (struct sockaddr *)&sockaddr, &len); 211 | if (s1 < 0) 212 | return s1; 213 | *addr = sockaddr.sin6_addr; 214 | return s1; 215 | } 216 | 217 | static bool socket_connect(sock s, struct in6_addr addr, uint16_t port) 218 | { 219 | struct sockaddr_in6 sockaddr; 220 | memset(&sockaddr, 0, sizeof(sockaddr)); 221 | sockaddr.sin6_family = AF_INET6; 222 | sockaddr.sin6_port = port; 223 | sockaddr.sin6_addr = addr; 224 | int flags = fcntl(s, F_GETFL, 0); 225 | if (flags < 0 || fcntl(s, F_SETFL, (flags | O_NONBLOCK)) != 0) 226 | return false; 227 | if (connect(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0 && 228 | errno != EINPROGRESS) 229 | return false; 230 | if (fcntl(s, F_SETFL, flags) != 0) 231 | return false; 232 | struct timeval tv; 233 | tv.tv_sec = 6; 234 | tv.tv_usec = 0; 235 | fd_set fds; 236 | FD_ZERO(&fds); 237 | FD_SET(s, &fds); 238 | int r = select(s+1, NULL, &fds, NULL, &tv); 239 | if (r == 0) 240 | errno = ETIMEDOUT; 241 | return (r > 0); 242 | } 243 | 244 | static ssize_t socket_recv(sock s, void *buf, size_t len, bool *timeout) 245 | { 246 | *timeout = false; 247 | struct timeval tv; 248 | tv.tv_sec = 2; 249 | tv.tv_usec = 0; 250 | fd_set fds; 251 | FD_ZERO(&fds); 252 | FD_SET(s, &fds); 253 | int r = select(s+1, &fds, NULL, &fds, &tv); 254 | if (r > 0) 255 | return recv(s, buf, len, MSG_DONTWAIT); 256 | if (r == 0) 257 | { 258 | *timeout = true; 259 | return 0; 260 | } 261 | return -1; 262 | } 263 | 264 | static ssize_t socket_send(sock s, void *buf, size_t len) 265 | { 266 | for (size_t i = 0; i < len; ) 267 | { 268 | int r = send(s, buf+i, len-i, MSG_NOSIGNAL); 269 | if (r <= 0) 270 | return r; 271 | i += r; 272 | } 273 | return len; 274 | } 275 | 276 | static void socket_close(sock s, bool err) 277 | { 278 | if (!err) 279 | shutdown(s, SHUT_RDWR); 280 | close(s); 281 | } 282 | 283 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PseudoNode 3 | * Copyright (c) 2015 the copyright holders 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | /* 25 | * PseudoNode (classic) 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #ifdef MACOSX 43 | #define LINUX 44 | #endif 45 | 46 | #ifdef LINUX 47 | #include 48 | #include 49 | 50 | #ifdef MACOSX 51 | #define s6_addr16 __u6_addr.__u6_addr16 52 | #endif 53 | 54 | #endif /* LINUX */ 55 | 56 | #ifdef WINDOWS 57 | #include 58 | #include 59 | #include 60 | #define s6_addr16 u.Word 61 | extern int inet_pton(int af, const char *src, void *dst); 62 | #endif /* WINDOWS */ 63 | 64 | #include "pseudo_node.h" 65 | 66 | static const char *bitcoin_dns_seeds[] = 67 | { 68 | "seed.bitcoin.sipa.be", 69 | "dnsseed.bluematt.me", 70 | "dnsseed.bitcoin.dashjr.org", 71 | "seed.bitcoinstats.com", 72 | "bitseed.xf2.org", 73 | "seed.bitcoin.jonasschnelli.ch", 74 | NULL 75 | }; 76 | static const struct PN_coin bitcoin_xt = 77 | { 78 | "bitcoin-xt", bitcoin_dns_seeds, 79 | 8333, 70010, 0xD9B4BEF9, 390000, true 80 | }; 81 | const struct PN_coin * const BITCOIN_XT = &bitcoin_xt; 82 | static const struct PN_coin bitcoin_classic = 83 | { 84 | "bitcoin-classic", bitcoin_dns_seeds, 85 | 8333, 70002, 0xD9B4BEF9, 390000, true 86 | }; 87 | const struct PN_coin * const BITCOIN_CLASSIC = &bitcoin_classic; 88 | 89 | #define OPTION_CLIENT 1 90 | #define OPTION_COIN 2 91 | #define OPTION_HELP 3 92 | #define OPTION_NUM_PEERS 4 93 | #define OPTION_PEER 5 94 | #define OPTION_PREFETCH 6 95 | #define OPTION_SERVER 7 96 | #define OPTION_STEALTH 8 97 | #define OPTION_THRESHOLD 9 98 | 99 | static unsigned char *print_log_message(struct PN *node, unsigned type, 100 | struct in6_addr addr, unsigned char *message, unsigned *len) 101 | { 102 | if (type == PN_CALLBACK_WARNING) 103 | printf("warning: "); 104 | char name[INET6_ADDRSTRLEN+1]; 105 | inet_ntop(AF_INET6, &addr, name, sizeof(name)); 106 | printf("[%s] %s\n", name, message); 107 | return message; 108 | } 109 | 110 | // main: 111 | int main(int argc, char **argv) 112 | { 113 | static struct option long_options[] = 114 | { 115 | {"client", 1, 0, OPTION_CLIENT}, 116 | {"coin", 1, 0, OPTION_COIN}, 117 | {"help", 0, 0, OPTION_HELP}, 118 | {"num-peers", 1, 0, OPTION_NUM_PEERS}, 119 | {"peer", 1, 0, OPTION_PEER}, 120 | {"prefetch", 0, 0, OPTION_PREFETCH}, 121 | {"server", 0, 0, OPTION_SERVER}, 122 | {"stealth", 0, 0, OPTION_STEALTH}, 123 | {"threshold", 1, 0, OPTION_THRESHOLD}, 124 | {NULL, 0, 0, 0} 125 | }; 126 | const struct PN_coin *COIN = BITCOIN; 127 | unsigned MAX_OUTBOUND_PEERS = 8; 128 | bool SERVER = false; 129 | bool STEALTH = false; 130 | bool PREFETCH = false; 131 | unsigned THRESHOLD = 2; 132 | const char *USER_AGENT = NULL; 133 | unsigned long long SERVICES = NODE_NETWORK; 134 | struct in6_addr peers[32]; 135 | size_t peers_idx = 0; 136 | memset(peers, 0, sizeof(peers)); 137 | while (true) 138 | { 139 | int idx; 140 | int opt = getopt_long(argc, argv, "", long_options, &idx); 141 | if (opt < 0) 142 | break; 143 | switch (opt) 144 | { 145 | case OPTION_CLIENT: 146 | USER_AGENT = optarg; 147 | break; 148 | case OPTION_COIN: 149 | if (strcmp(optarg, "bitcoin") == 0) 150 | COIN = BITCOIN; 151 | else if (strcmp(optarg, "testnet") == 0) 152 | COIN = TESTNET; 153 | else if (strcmp(optarg, "litecoin") == 0) 154 | COIN = LITECOIN; 155 | else if (strcmp(optarg, "bitcoin-xt") == 0) 156 | COIN = BITCOIN_XT; 157 | else if (strcmp(optarg, "bitcoin-classic") == 0) 158 | COIN = BITCOIN_CLASSIC; 159 | else 160 | { 161 | fprintf(stderr, "fatal: unknown coin \"%s\"\n", optarg); 162 | return EXIT_FAILURE; 163 | } 164 | break; 165 | case OPTION_PEER: 166 | { 167 | if (peers_idx >= sizeof(peers) / sizeof(peers[0]) - 1) 168 | break; 169 | struct in6_addr addr; 170 | if (inet_pton(AF_INET6, optarg, &addr) != 1) 171 | { 172 | uint32_t addr32; 173 | if (inet_pton(AF_INET, optarg, &addr32) != 1) 174 | { 175 | fprintf(stderr, "fatal: failed to parse IP address " 176 | "\"%s\"", optarg); 177 | return EXIT_FAILURE; 178 | } 179 | memset(&addr, 0, sizeof(addr)); 180 | addr.s6_addr16[5] = 0xFFFF; 181 | memcpy(addr.s6_addr16+6, &addr32, sizeof(addr32)); 182 | } 183 | peers[peers_idx++] = addr; 184 | break; 185 | } 186 | case OPTION_NUM_PEERS: 187 | MAX_OUTBOUND_PEERS = atoi(optarg); 188 | if (MAX_OUTBOUND_PEERS < 1 || MAX_OUTBOUND_PEERS > 64) 189 | { 190 | fprintf(stderr, "fatal: number-of-peers is out of " 191 | "range\n"); 192 | return EXIT_FAILURE; 193 | } 194 | break; 195 | case OPTION_SERVER: 196 | SERVER = true; 197 | break; 198 | case OPTION_STEALTH: 199 | STEALTH = true; 200 | break; 201 | case OPTION_PREFETCH: 202 | PREFETCH = true; 203 | break; 204 | case OPTION_THRESHOLD: 205 | THRESHOLD = atoi(optarg); 206 | break; 207 | case OPTION_HELP: 208 | default: 209 | fprintf(stderr, "usage: %s [--help] [--client=NAME] " 210 | "[--threshold=VAL] [--server] [--stealth] [--peer=PEER] " 211 | "[--prefetch] [--num-peers=NUM_PEERS] [--coin=COIN]\n\n", 212 | argv[0]); 213 | fprintf(stderr, "WHERE:\n"); 214 | fprintf(stderr, "\t--client=CLIENT\n"); 215 | fprintf(stderr, "\t\tUse CLIENT as the client name " 216 | "(default=PseudoNode).\n"); 217 | fprintf(stderr, "\t--threshold=VAL\n"); 218 | fprintf(stderr, "\t\tData (blocks, tx) is considered valid " 219 | "if VAL peers agree\n"); 220 | fprintf(stderr, "\t\t(default=2).\n"); 221 | fprintf(stderr, "\t--peer=PEER\n"); 222 | fprintf(stderr, "\t\tAdd PEER (ipv6 address) to the list of " 223 | "potential peers.\n"); 224 | fprintf(stderr, "\t--num-peers=NUM_PEERS\n"); 225 | fprintf(stderr, "\t\tMaximum number of outbound connections " 226 | "(default=8).\n"); 227 | fprintf(stderr, "\t--server\n"); 228 | fprintf(stderr, "\t\tRun as a server (default=false).\n"); 229 | fprintf(stderr, "\t--stealth\n"); 230 | fprintf(stderr, "\t\tIdentify as a normal client " 231 | "(default=false).\n"); 232 | fprintf(stderr, "\t--prefetch\n"); 233 | fprintf(stderr, "\t\tPrefetch tx and block data " 234 | "(default=false).\n"); 235 | fprintf(stderr, "\t--coin=COIN\n"); 236 | fprintf(stderr, "\t\tAttach to COIN network " 237 | "(default=bitcoin). Supported coins are:\n"); 238 | fprintf(stderr, "\t\tbitcoin, testnet, litecoin, " 239 | "bitcoin-xt\n"); 240 | return 0; 241 | } 242 | } 243 | 244 | if (SERVER) 245 | { 246 | #ifdef LINUX 247 | daemon(1, 0); 248 | struct passwd *entry = getpwnam("nobody"); 249 | if (entry == NULL) 250 | { 251 | fprintf(stderr, "fatal: failed to change user/group to nobody\n"); 252 | return EXIT_FAILURE; 253 | } 254 | setgid(entry->pw_gid); 255 | setuid(entry->pw_uid); 256 | #endif 257 | } 258 | if (STEALTH) 259 | { 260 | if (COIN == BITCOIN) 261 | USER_AGENT = "/Satoshi:0.11.2/"; 262 | else if (COIN == TESTNET) 263 | USER_AGENT = "/Satoshi:0.11.2/"; 264 | else if (COIN == LITECOIN) 265 | USER_AGENT = "/Satoshi:0.8.7.5/"; 266 | else if (COIN == BITCOIN_XT) 267 | { 268 | SERVICES |= NODE_GETUTXOS; 269 | USER_AGENT = "/Bitcoin XT:0.11.0C/"; 270 | } 271 | else if (COIN == BITCOIN_CLASSIC) 272 | USER_AGENT = "/Classic:0.11.2/"; 273 | } 274 | if (THRESHOLD < 1 || THRESHOLD > MAX_OUTBOUND_PEERS) 275 | { 276 | fprintf(stderr, "fatal: threshold must be within the range " 277 | "1..max_peers\n"); 278 | return EXIT_FAILURE; 279 | } 280 | 281 | #ifdef LINUX 282 | signal(SIGPIPE, SIG_IGN); 283 | #endif 284 | 285 | struct PN_config CONFIG; 286 | memset(&CONFIG, 0, sizeof(CONFIG)); 287 | CONFIG.services = SERVICES; 288 | CONFIG.user_agent = USER_AGENT; 289 | CONFIG.threshold = THRESHOLD; 290 | CONFIG.prefetch = PREFETCH; 291 | CONFIG.num_peers = MAX_OUTBOUND_PEERS; 292 | struct PN_callbacks CALLBACKS; 293 | memset(&CALLBACKS, 0, sizeof(CALLBACKS)); 294 | CALLBACKS.log = print_log_message; 295 | CALLBACKS.warning = print_log_message; 296 | unsigned ret = 0; 297 | struct PN *node = PN_create(COIN, &CALLBACKS, &CONFIG, ret); 298 | 299 | return 0; 300 | } 301 | 302 | -------------------------------------------------------------------------------- /port_map.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PseudoNode 3 | * Copyright (c) 2015 the copyright holders 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifdef WINDOWS 25 | #define LIB_NAME "miniupnpc.dll" 26 | #endif 27 | 28 | #ifdef LINUX 29 | #include 30 | #ifdef MACOSX 31 | #define LIB_NAME "libminiupnpc.dylib" 32 | #else 33 | #define LIB_NAME "libminiupnpc.so" 34 | #endif 35 | #endif 36 | 37 | struct UPNPDev; 38 | struct UPNPUrls 39 | { 40 | char *controlURL; 41 | char *ipcondescURL; 42 | char *controlURL_CIF; 43 | char *controlURL_6FC; 44 | char *rootdescURL; 45 | }; 46 | #define MINIUPNPC_URL_MAXSIZE 128 47 | struct IGDdatas_service 48 | { 49 | char controlurl[MINIUPNPC_URL_MAXSIZE]; 50 | char eventsuburl[MINIUPNPC_URL_MAXSIZE]; 51 | char scpdurl[MINIUPNPC_URL_MAXSIZE]; 52 | char servicetype[MINIUPNPC_URL_MAXSIZE]; 53 | }; 54 | struct IGDdatas 55 | { 56 | char cureltname[MINIUPNPC_URL_MAXSIZE]; 57 | char urlbase[MINIUPNPC_URL_MAXSIZE]; 58 | char presentationurl[MINIUPNPC_URL_MAXSIZE]; 59 | int level; 60 | struct IGDdatas_service CIF; 61 | struct IGDdatas_service first; 62 | struct IGDdatas_service second; 63 | struct IGDdatas_service IPv6FC; 64 | struct IGDdatas_service tmp; 65 | }; 66 | struct UPNPDev *(*upnpDiscover)(int, const char *, const char *, int, int, 67 | int *); 68 | int (*UPNP_GetValidIGD)(struct UPNPDev *, struct UPNPUrls *, struct IGDdatas *, 69 | char *, int); 70 | int (*UPNP_GetExternalIPAddress)(const char *, const char *, char *); 71 | int (*UPNP_AddPortMapping)(const char *, const char *, const char *, 72 | const char *, const char *, const char *, const char *, const char *, 73 | const char *); 74 | 75 | // Load the library. 76 | static bool load_library(void) 77 | { 78 | #ifdef LINUX 79 | void *lib = dlopen(LIB_NAME, RTLD_LOCAL | RTLD_NOW); 80 | if (lib == NULL) 81 | return false; 82 | upnpDiscover = dlsym(lib, "upnpDiscover"); 83 | UPNP_GetValidIGD = dlsym(lib, "UPNP_GetValidIGD"); 84 | UPNP_GetExternalIPAddress = dlsym(lib, "UPNP_GetExternalIPAddress"); 85 | UPNP_AddPortMapping = dlsym(lib, "UPNP_AddPortMapping"); 86 | #endif 87 | 88 | #ifdef WINDOWS 89 | HMODULE lib = LoadLibrary(LIB_NAME); 90 | if (lib == NULL) 91 | return false; 92 | upnpDiscover = (void *)GetProcAddress(lib, "upnpDiscover"); 93 | UPNP_GetValidIGD = (void *)GetProcAddress(lib, "UPNP_GetValidIGD"); 94 | UPNP_GetExternalIPAddress = 95 | (void *)GetProcAddress(lib, "UPNP_GetExternalIPAddress"); 96 | UPNP_AddPortMapping = (void *)GetProcAddress(lib, "UPNP_AddPortMapping"); 97 | #endif 98 | 99 | return true; 100 | } 101 | 102 | // Attempt to add port mapping. 103 | static void *port_map(void *arg) 104 | { 105 | struct state *S = (struct state *)arg; 106 | const char *reason = "no reason"; 107 | 108 | if (!load_library()) 109 | { 110 | reason = "libminiupnpc not found"; 111 | goto port_map_failed; 112 | } 113 | if (upnpDiscover == NULL || UPNP_GetValidIGD == NULL || 114 | UPNP_GetExternalIPAddress == NULL || UPNP_AddPortMapping == NULL) 115 | { 116 | reason = "incompatible libminiupnpc"; 117 | goto port_map_failed; 118 | } 119 | 120 | char port_str[8]; 121 | int r = snprintf(port_str, sizeof(port_str)-1, "%u", ntohs(S->port)); 122 | if (r <= 0 || r >= sizeof(port_str)-1) 123 | fatal("snprintf failed"); 124 | 125 | int err = 0; 126 | struct UPNPDev *dev = upnpDiscover(2000, NULL, NULL, 0, 0, &err); 127 | 128 | char lan_address[64]; 129 | struct UPNPUrls urls; 130 | struct IGDdatas data; 131 | err = UPNP_GetValidIGD(dev, &urls, &data, lan_address, sizeof(lan_address)); 132 | if (err != 1) 133 | { 134 | reason = "failed to get IGD"; 135 | goto port_map_failed; 136 | } 137 | char wan_address[64]; 138 | err = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, 139 | wan_address); 140 | if (err) 141 | { 142 | reason = "failed to get IP address"; 143 | goto port_map_failed; 144 | } 145 | while (true) 146 | { 147 | err = UPNP_AddPortMapping(urls.controlURL, 148 | data.first.servicetype, port_str, port_str, lan_address, 149 | "PseudoNode", "TCP", NULL, "0"); 150 | if (err) 151 | { 152 | reason = "failed to add port map"; 153 | goto port_map_failed; 154 | } 155 | struct in6_addr addr; 156 | memset(&addr, 0, sizeof(addr)); 157 | action(S, addr, "add: port map for %s", port_str); 158 | msleep(1000*60*20); // 20 Minutes 159 | } 160 | 161 | return NULL; 162 | 163 | port_map_failed: {} 164 | struct in6_addr addr; 165 | memset(&addr, 0, sizeof(addr)); 166 | warning(S, addr, "automatic port mapping failed (%s); open port %u for " 167 | "inbound connections", reason, ntohs(S->port)); 168 | return NULL; 169 | } 170 | -------------------------------------------------------------------------------- /pseudo_node.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PseudoNode 3 | * Copyright (c) 2015 the copyright holders 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef PSEUDONODE_H 25 | #define PSEUDONODE_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /* 32 | * TL;DR 33 | * 34 | * The call: 35 | * 36 | * struct PN *node = PN_create(NULL, NULL, NULL, 1); 37 | * 38 | * creates a basic Bitcoin PseudoNode using all the default settings. See the 39 | * documentation below for more advanced usage. 40 | * 41 | */ 42 | 43 | /* 44 | * A PseudoNode 45 | */ 46 | struct PN; 47 | 48 | /****************************************************************************/ 49 | /* 50 | * COIN CONFIGUATION. 51 | */ 52 | 53 | // PseudoNode supports multiple cryptocurrencies provided they are 54 | // based on the Bitcoin network protocol. The PN_coin structure lets you 55 | // specify new currency configurations. Note that some altcoins (e.g. 56 | // Dogecoin, Peercoin, etc.) have introduced subtle incompatibilities with the 57 | // Bitcoin protocol. 58 | 59 | struct PN_coin 60 | { 61 | const char *name; // Coin name, e.g. "bitcoin" 62 | const char **seeds; // NULL-terminated array of DNS seeds. 63 | unsigned port; // Protocol port. 64 | unsigned version; // Protocol version (70002 supported). 65 | unsigned magic; // Protocol magic number. 66 | unsigned height; // Block height guess (<= real height). 67 | unsigned relay; // Non-zero if the protocol version 68 | // message should the relay flag. 69 | }; 70 | 71 | // Pre-defined coins. 72 | extern const struct PN_coin * const BITCOIN; // Bitcoin (the default). 73 | extern const struct PN_coin * const TESTNET; // Bitcoin testnet. 74 | extern const struct PN_coin * const LITECOIN; // Litecoin. 75 | 76 | /****************************************************************************/ 77 | /* 78 | * CALLBACK CONFIGURATION. 79 | */ 80 | 81 | // Callback function type. 82 | // - node: The PseudoNode instance. 83 | // - type: Callback type (one of the PN_CALLBACK_* values). 84 | // - addr: The address of the peer for which the message concerns. Otherwise 85 | // will be an all-zero address. 86 | // - data: The data (e.g. message, tx, block, etc.). The data may be modified 87 | // by the callback, left unchanged, or blocked. The memory will be malloc() 88 | // allocated. 89 | // - len: The length of `data'. 90 | // - return value: return NULL if the message should be blocked or ignored. 91 | // Otherwise return the original `data', or a modified `data' using 92 | // (re)malloc()'ed memory. If the length has changed then update `len'. If 93 | // the data is changed, then the old data should be free()'ed. 94 | typedef unsigned char *(*PN_callback)(struct PN *node, int type, 95 | struct in6_addr addr, unsigned char *data, unsigned *len); 96 | 97 | #define PN_CALLBACK_BLOCK 1 98 | #define PN_CALLBACK_TX 2 99 | #define PN_CALLBACK_INV 3 100 | #define PN_CALLBACK_VERSION 4 101 | #define PN_CALLBACK_RAW 5 102 | #define PN_CALLBACK_LOG 6 103 | #define PN_CALLBACK_WARNING 7 104 | 105 | // NOTE: each field may be NULL. 106 | struct PN_callbacks 107 | { 108 | // HIGH-LEVEL: 109 | PN_callback block; // Called for each new BLOCK message. 110 | PN_callback tx; // Called for each TX message. 111 | PN_callback inv; // Called for each INV message. 112 | // The data will be an inventory vector of 113 | // length 1. 114 | PN_callback version; // Called for each VERSION message. 115 | 116 | // LOW-LEVEL: 117 | PN_callback raw; // Called for each inbound raw protocol 118 | // message. Each message contains the message 119 | // header. If modified, it is not necessary 120 | // to recalculate the checksum. 121 | 122 | // LOGGING: 123 | PN_callback log; // Log message (as a string). 124 | PN_callback warning; // Warning message (as a string). 125 | }; 126 | 127 | /****************************************************************************/ 128 | /* 129 | * NODE CONFIGURATION. 130 | */ 131 | 132 | #define NODE_NETWORK 1 133 | #define NODE_GETUTXOS 2 // NOTE: functionality not implemented. 134 | #define NODE_REPLACE_BY_FEE 0x04000000 135 | #define NODE_PSEUDO 0x80000000 // Not enabled by default. 136 | 137 | struct PN_config 138 | { 139 | const char *user_agent; // The user agent to use (default: PseudoNode). 140 | unsigned long long services;// Extra services flags beyond NODE_NETWORK 141 | // (default: 0). 142 | unsigned threshold; // Data validation threshold (default: 2). 143 | unsigned prefetch; // Prefetch data? (default: 0). 144 | unsigned num_peers; // Number of outbound peers (default: 8). 145 | unsigned num_addrs; // Size of the peer address queue 146 | // (default: 4096). 147 | const struct in6_addr *peers; 148 | // Optional list of peers to connect to. 149 | // Zero-address terminated. 150 | // (default: NULL=empty). 151 | }; 152 | 153 | /*****************************************************************************/ 154 | /* 155 | * PseudoNode API. 156 | */ 157 | 158 | /* 159 | * Create a PseudoNode. 160 | * - coin: Coin configuration. Pass NULL to default to BITCOIN. 161 | * - callbacks: Callback configuration. Pass NULL for no callbacks. 162 | * - config: Node configuration. Pass NULL to use the defaults. 163 | * - ret: Return from this call if non-zero. Otherwise this function will 164 | * assume control over the current thread and never return. 165 | */ 166 | extern struct PN *PN_create( 167 | const struct PN_coin *_coin, 168 | const struct PN_callbacks *_callbacks, 169 | const struct PN_config *_config, 170 | int _ret 171 | ); 172 | 173 | /* 174 | * Broadcast a transaction to the network. Note that it is up to the caller 175 | * to ensure that `tx' is valid, as PseudoNode does no validation. 176 | * Broadcasting an invalid transaction may cause your node to be DoS banned. 177 | * Returns 0 on success, non-zero otherwise. 178 | * 179 | * WARNING: this functionality has never been tested... 180 | */ 181 | extern int PN_broadcast_tx( 182 | struct PN *_node, 183 | const unsigned char *_tx, 184 | unsigned _len); 185 | 186 | /* 187 | * Not-yet-implemented functions: 188 | */ 189 | #if 0 190 | extern int PN_broadcast_block( 191 | struct PN *_node, 192 | const unsigned char *_block, 193 | unsigned len); 194 | 195 | void PN_destroy(struct PN *node); 196 | #endif 197 | 198 | /*****************************************************************************/ 199 | /* 200 | * PseudoNode helper API. 201 | */ 202 | 203 | /* 204 | * SHA256 205 | */ 206 | extern void PN_sha256( 207 | const void *_data, 208 | unsigned _len, 209 | void *_res); 210 | 211 | /* 212 | * SHA256d 213 | */ 214 | extern void PN_sha256d( 215 | const void *_data, 216 | unsigned _len, 217 | void *_res); 218 | 219 | /* 220 | * Get information (as defined by the constants below). 221 | */ 222 | #define PN_HEIGHT 1001 // Block height. 223 | #define PN_NUM_IN_PEERS 1002 // # inbound connections. 224 | #define PN_NUM_OUT_PEERS 1003 // # outbound connections. 225 | #define PN_NUM_SEND_BYTES 1004 // # sent bytes. 226 | #define PN_NUM_RECV_BYTES 1005 // # recv bytes. 227 | extern int PN_get_info( 228 | struct PN *_node, 229 | int _what); 230 | 231 | #ifdef __cplusplus 232 | } 233 | #endif 234 | 235 | #endif 236 | -------------------------------------------------------------------------------- /release-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | VERSION=`cat ./VERSION` 6 | NAME=PseudoNode-$VERSION 7 | 8 | if [ -e pseudonode.linux ] 9 | then 10 | echo "BUILD $NAME-Linux" 11 | INSTALL=$NAME-Linux 12 | PACKAGE=$NAME-Linux.zip 13 | echo "\tdelete $PACKAGE..." 14 | rm -f $PACKAGE 15 | echo "\tmake $INSTALL..." 16 | mkdir -p $INSTALL 17 | echo "\tcopy $INSTALL/LICENSE.txt..." 18 | cp LICENSE.txt $INSTALL 19 | echo "\tcopy $INSTALL/README.md..." 20 | cp README.md $INSTALL 21 | echo "\tcopy $INSTALL/pseudonode..." 22 | cp pseudonode.linux $INSTALL/pseudonode 23 | echo "\tcopy $INSTALL/libpseudonode.so..." 24 | cp libpseudonode.so $INSTALL 25 | echo "\tcopy $INSTALL/libminiupnpc.so..." 26 | cp libminiupnpc.so $INSTALL 27 | echo "\tbuilding $PACKAGE..." 28 | zip -r $PACKAGE $INSTALL > /dev/null 29 | echo -n "\tclean $INSTALL..." 30 | rm -rf $INSTALL 31 | echo "DONE" 32 | fi 33 | 34 | if [ -e pseudonode.macosx ] 35 | then 36 | echo "BUILD $NAME-MacOSX" 37 | INSTALL=$NAME-MacOSX 38 | PACKAGE=$NAME-MacOSX.zip 39 | echo "\tdelete $PACKAGE..." 40 | rm -f $PACKAGE 41 | echo "\tmake $INSTALL..." 42 | mkdir -p $INSTALL 43 | echo "\tcopy $INSTALL/LICENSE.txt..." 44 | cp LICENSE.txt $INSTALL 45 | echo "\tcopy $INSTALL/README.md..." 46 | cp README.md $INSTALL 47 | echo "\tcopy $INSTALL/pseudonode..." 48 | cp pseudonode.macosx $INSTALL/pseudonode 49 | echo "\tcopy $INSTALL/libpseudonode.dylib..." 50 | cp libpseudonode.dylib $INSTALL 51 | echo "\tcopy $INSTALL/libminiupnpc.dylib..." 52 | cp libminiupnpc.dylib $INSTALL 53 | echo "\tbuilding $PACKAGE..." 54 | zip -r $PACKAGE $INSTALL > /dev/null 55 | echo -n "\tclean $INSTALL..." 56 | rm -rf $INSTALL 57 | echo "DONE" 58 | fi 59 | 60 | if [ -e PseudoNode.exe ] 61 | then 62 | echo "BUILD $NAME-Windows" 63 | INSTALL=$NAME-Windows 64 | PACKAGE=$NAME-Windows.zip 65 | echo "\tdelete $PACKAGE..." 66 | rm -f $PACKAGE 67 | echo "\tmake $INSTALL..." 68 | mkdir -p $INSTALL 69 | echo "\tcopy $INSTALL/LICENSE.txt..." 70 | cp LICENSE.txt $INSTALL 71 | echo "\tcopy $INSTALL/README.md..." 72 | cp README.md $INSTALL 73 | echo "\tcopy $INSTALL/PseudoNode.exe..." 74 | cp PseudoNode.exe $INSTALL 75 | echo "\tcopy $INSTALL/miniupnpc.dll..." 76 | cp miniupnpc.dll $INSTALL 77 | echo "\tbuilding $PACKAGE..." 78 | zip -r $PACKAGE $INSTALL > /dev/null 79 | echo -n "\tclean $INSTALL..." 80 | rm -rf $INSTALL 81 | echo "DONE" 82 | fi 83 | 84 | VERSION=0.1 85 | NAME=TxMon-$VERSION 86 | 87 | if [ -e apps/txmon/txmon.linux ] 88 | then 89 | echo "BUILD $NAME-Linux" 90 | INSTALL=$NAME-Linux 91 | PACKAGE=$NAME-Linux.zip 92 | echo "\tdelete $PACKAGE..." 93 | rm -f $PACKAGE 94 | echo "\tmake $INSTALL..." 95 | mkdir -p $INSTALL 96 | echo "\tcopy $INSTALL/LICENSE.txt..." 97 | cp LICENSE.txt $INSTALL 98 | echo "\tcopy $INSTALL/txmon..." 99 | cp apps/txmon/txmon.linux $INSTALL/txmon 100 | echo "\tcopy $INSTALL/libpseudonode.so..." 101 | cp libpseudonode.so $INSTALL 102 | echo "\tcopy $INSTALL/libminiupnpc.so..." 103 | cp libminiupnpc.so $INSTALL 104 | echo "\tbuilding $PACKAGE..." 105 | zip -r $PACKAGE $INSTALL > /dev/null 106 | echo -n "\tclean $INSTALL..." 107 | rm -rf $INSTALL 108 | echo "DONE" 109 | fi 110 | 111 | if [ -e apps/txmon/txmon.macosx ] 112 | then 113 | echo "BUILD $NAME-MacOSX" 114 | INSTALL=$NAME-MacOSX 115 | PACKAGE=$NAME-MacOSX.zip 116 | echo "\tdelete $PACKAGE..." 117 | rm -f $PACKAGE 118 | echo "\tmake $INSTALL..." 119 | mkdir -p $INSTALL 120 | echo "\tcopy $INSTALL/LICENSE.txt..." 121 | cp LICENSE.txt $INSTALL 122 | echo "\tcopy $INSTALL/txmon..." 123 | cp apps/txmon/txmon.macosx $INSTALL/txmon 124 | echo "\tcopy $INSTALL/libpseudonode.dynlib..." 125 | cp libpseudonode.dynlib $INSTALL 126 | echo "\tcopy $INSTALL/libminiupnpc.dynlib..." 127 | cp libminiupnpc.dynlib $INSTALL 128 | echo "\tbuilding $PACKAGE..." 129 | zip -r $PACKAGE $INSTALL > /dev/null 130 | echo -n "\tclean $INSTALL..." 131 | rm -rf $INSTALL 132 | echo "DONE" 133 | fi 134 | 135 | if [ -e apps/txmon/TxMon.exe ] 136 | then 137 | echo "BUILD $NAME-Windows" 138 | INSTALL=$NAME-Windows 139 | PACKAGE=$NAME-Windows.zip 140 | echo "\tdelete $PACKAGE..." 141 | rm -f $PACKAGE 142 | echo "\tmake $INSTALL..." 143 | mkdir -p $INSTALL 144 | echo "\tcopy $INSTALL/LICENSE.txt..." 145 | cp LICENSE.txt $INSTALL 146 | echo "\tcopy $INSTALL/TxMon.exe..." 147 | cp apps/txmon/TxMon.exe $INSTALL 148 | echo "\tcopy $INSTALL/PseudoNode.dll..." 149 | cp PseudoNode.dll $INSTALL 150 | echo "\tcopy $INSTALL/miniupnpc.dll..." 151 | cp miniupnpc.dll $INSTALL 152 | echo "\tbuilding $PACKAGE..." 153 | zip -r $PACKAGE $INSTALL > /dev/null 154 | echo -n "\tclean $INSTALL..." 155 | rm -rf $INSTALL 156 | echo "DONE" 157 | fi 158 | 159 | if [ -e apps/txmon/TxMon.exe ] 160 | then 161 | echo "BUILD $NAME-Windows" 162 | INSTALL=$NAME-Windows 163 | PACKAGE=$NAME-Install.exe 164 | echo "\tdelete $PACKAGE..." 165 | rm -f $PACKAGE 166 | echo "\tmake $INSTALL..." 167 | mkdir -p $INSTALL 168 | echo "\tcopy $INSTALL/LICENSE.txt..." 169 | cp LICENSE.txt $INSTALL 170 | echo "\tcopy $INSTALL/TxMon.exe..." 171 | cp apps/txmon/TxMon.exe $INSTALL 172 | echo "\tcopy $INSTALL/PseudoNode.dll..." 173 | cp PseudoNode.dll $INSTALL 174 | echo "\tcopy $INSTALL/miniupnpc.dll..." 175 | cp miniupnpc.dll $INSTALL 176 | echo "\tbuilding $PACKAGE..." 177 | cd $INSTALL 178 | cp ../apps/txmon/install.nsi . 179 | makensis install.nsi 180 | mv TxMon-install.exe ../$PACKAGE 181 | echo -n "\tclean $INSTALL..." 182 | rm -rf $INSTALL 183 | echo "DONE" 184 | fi 185 | 186 | -------------------------------------------------------------------------------- /sha256.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SHA256 3 | * 4 | * The author (Brad Conte) has released this file "into the public domain free 5 | * of any restrictions". This file is unchanged except for some style 6 | * clean-up. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | // DBL_INT_ADD treats two unsigned ints a and b as one 64-bit integer and adds 14 | // c to it 15 | #define DBL_INT_ADD(a,b,c) if (a > 0xffffffff - (c)) ++b; a += c; 16 | #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) 17 | #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) 18 | 19 | #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) 20 | #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 21 | #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) 22 | #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) 23 | #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) 24 | #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) 25 | 26 | typedef struct 27 | { 28 | uint8_t data[64]; 29 | uint32_t datalen; 30 | uint32_t bitlen[2]; 31 | uint32_t state[8]; 32 | } SHA256_CTX; 33 | 34 | uint32_t k[64] = 35 | { 36 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 37 | 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 38 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 39 | 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 40 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 41 | 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 42 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 43 | 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 44 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 45 | 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 46 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 47 | }; 48 | 49 | static void sha256_transform(SHA256_CTX *ctx, uint8_t *data) 50 | { 51 | uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; 52 | 53 | for (i = 0, j = 0; i < 16; ++i, j += 4) 54 | m[i] = (data[j] << 24) | (data[j+1] << 16) | (data[j+2] << 8) | 55 | (data[j+3]); 56 | for (; i < 64; ++i) 57 | m[i] = SIG1(m[i-2]) + m[i-7] + SIG0(m[i-15]) + m[i-16]; 58 | 59 | a = ctx->state[0]; 60 | b = ctx->state[1]; 61 | c = ctx->state[2]; 62 | d = ctx->state[3]; 63 | e = ctx->state[4]; 64 | f = ctx->state[5]; 65 | g = ctx->state[6]; 66 | h = ctx->state[7]; 67 | 68 | for (i = 0; i < 64; ++i) 69 | { 70 | t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; 71 | t2 = EP0(a) + MAJ(a,b,c); 72 | h = g; 73 | g = f; 74 | f = e; 75 | e = d + t1; 76 | d = c; 77 | c = b; 78 | b = a; 79 | a = t1 + t2; 80 | } 81 | 82 | ctx->state[0] += a; 83 | ctx->state[1] += b; 84 | ctx->state[2] += c; 85 | ctx->state[3] += d; 86 | ctx->state[4] += e; 87 | ctx->state[5] += f; 88 | ctx->state[6] += g; 89 | ctx->state[7] += h; 90 | } 91 | 92 | static void sha256_init(SHA256_CTX *ctx) 93 | { 94 | ctx->datalen = 0; 95 | ctx->bitlen[0] = 0; 96 | ctx->bitlen[1] = 0; 97 | ctx->state[0] = 0x6a09e667; 98 | ctx->state[1] = 0xbb67ae85; 99 | ctx->state[2] = 0x3c6ef372; 100 | ctx->state[3] = 0xa54ff53a; 101 | ctx->state[4] = 0x510e527f; 102 | ctx->state[5] = 0x9b05688c; 103 | ctx->state[6] = 0x1f83d9ab; 104 | ctx->state[7] = 0x5be0cd19; 105 | } 106 | 107 | static void sha256_update(SHA256_CTX *ctx, uint8_t *data, uint32_t len) 108 | { 109 | uint32_t i; 110 | 111 | for (i=0; i < len; ++i) 112 | { 113 | ctx->data[ctx->datalen] = data[i]; 114 | ctx->datalen++; 115 | if (ctx->datalen == 64) 116 | { 117 | sha256_transform(ctx,ctx->data); 118 | DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],512); 119 | ctx->datalen = 0; 120 | } 121 | } 122 | } 123 | 124 | static void sha256_final(SHA256_CTX *ctx, uint8_t *hash) 125 | { 126 | uint32_t i; 127 | 128 | i = ctx->datalen; 129 | 130 | // Pad whatever data is left in the buffer. 131 | if (ctx->datalen < 56) 132 | { 133 | ctx->data[i++] = 0x80; 134 | while (i < 56) 135 | ctx->data[i++] = 0x00; 136 | } 137 | else 138 | { 139 | ctx->data[i++] = 0x80; 140 | while (i < 64) 141 | ctx->data[i++] = 0x00; 142 | sha256_transform(ctx,ctx->data); 143 | memset(ctx->data,0,56); 144 | } 145 | 146 | // Append to the padding the total message's length in bits and transform. 147 | DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],ctx->datalen * 8); 148 | ctx->data[63] = ctx->bitlen[0]; 149 | ctx->data[62] = ctx->bitlen[0] >> 8; 150 | ctx->data[61] = ctx->bitlen[0] >> 16; 151 | ctx->data[60] = ctx->bitlen[0] >> 24; 152 | ctx->data[59] = ctx->bitlen[1]; 153 | ctx->data[58] = ctx->bitlen[1] >> 8; 154 | ctx->data[57] = ctx->bitlen[1] >> 16; 155 | ctx->data[56] = ctx->bitlen[1] >> 24; 156 | sha256_transform(ctx,ctx->data); 157 | 158 | // Since this implementation uses little endian byte ordering and SHA uses 159 | // big endian, reverse all the bytes when copying the final state to the 160 | // output hash. 161 | for (i=0; i < 4; ++i) 162 | { 163 | hash[i] = (ctx->state[0] >> (24-i*8)) & 0x000000ff; 164 | hash[i+4] = (ctx->state[1] >> (24-i*8)) & 0x000000ff; 165 | hash[i+8] = (ctx->state[2] >> (24-i*8)) & 0x000000ff; 166 | hash[i+12] = (ctx->state[3] >> (24-i*8)) & 0x000000ff; 167 | hash[i+16] = (ctx->state[4] >> (24-i*8)) & 0x000000ff; 168 | hash[i+20] = (ctx->state[5] >> (24-i*8)) & 0x000000ff; 169 | hash[i+24] = (ctx->state[6] >> (24-i*8)) & 0x000000ff; 170 | hash[i+28] = (ctx->state[7] >> (24-i*8)) & 0x000000ff; 171 | } 172 | } 173 | 174 | extern void sha256_hash(const char *data, size_t len, char *res) 175 | { 176 | SHA256_CTX cxt; 177 | sha256_init(&cxt); 178 | sha256_update(&cxt, (uint8_t *)data, (int)len); 179 | sha256_final(&cxt, (uint8_t *)res); 180 | } 181 | 182 | -------------------------------------------------------------------------------- /windows.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PseudoNode 3 | * Copyright (c) 2015 the copyright holders 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | // Windows cruft: 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | extern const char *inet_ntop(int af, const void *src, char *dst, 31 | socklen_t size); 32 | extern int inet_pton(int af, const char *src, void *dst); 33 | extern errno_t rand_s(unsigned int* r); 34 | 35 | #define IPV6_V6ONLY 27 // Missing def for MinGW. 36 | 37 | static DWORD err_idx; 38 | #define MAX_ERROR BUFSIZ 39 | 40 | static bool system_init(void) 41 | { 42 | static bool init = true; 43 | if (!init) 44 | return true; 45 | init = false; 46 | static WSADATA wsa_data; 47 | WSAStartup(MAKEWORD(2, 2), &wsa_data); 48 | err_idx = TlsAlloc(); 49 | if (err_idx == TLS_OUT_OF_INDEXES) 50 | return false; 51 | return true; 52 | } 53 | 54 | static const char *get_error(void) 55 | { 56 | DWORD err = GetLastError(); 57 | if (err == 0) 58 | err = WSAGetLastError(); 59 | char *err_str = (char *)TlsGetValue(err_idx); 60 | if (err_str == NULL) 61 | { 62 | err_str = (char *)malloc((MAX_ERROR+1)*sizeof(char)); 63 | assert(err_str != NULL); 64 | BOOL ok = TlsSetValue(err_idx, err_str); 65 | assert(ok); 66 | } 67 | DWORD len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, err, 0, err_str, 68 | MAX_ERROR, 0); 69 | if (len == 0 || len > MAX_ERROR-1) 70 | return "(failed to format error message)"; 71 | err_str[len-1] = '\0'; 72 | SetLastError(0); 73 | WSASetLastError(0); 74 | return err_str; 75 | } 76 | 77 | static bool rand_init(uint64_t *r) 78 | { 79 | uint32_t r32[4]; 80 | if (rand_s(r32) != 0 || rand_s(r32+1) != 0 || rand_s(r32+2) != 0 || 81 | rand_s(r32+3) != 0) 82 | return false; 83 | memcpy(r, r32, sizeof(r32)); 84 | return true; 85 | } 86 | 87 | typedef HANDLE mutex; 88 | 89 | static inline void mutex_init(mutex *m) 90 | { 91 | *m = CreateMutex(NULL, FALSE, NULL); 92 | assert(*m != NULL); 93 | } 94 | 95 | static inline void mutex_free(mutex *m) 96 | { 97 | BOOL res = CloseHandle(*m); 98 | assert(res); 99 | } 100 | 101 | static inline void mutex_lock(mutex *m) 102 | { 103 | DWORD res = WaitForSingleObject(*m, INFINITE); 104 | assert(res == WAIT_OBJECT_0); 105 | } 106 | 107 | static inline void mutex_unlock(mutex *m) 108 | { 109 | BOOL res = ReleaseMutex(*m); 110 | assert(res); 111 | } 112 | 113 | static inline void msleep(size_t ms) 114 | { 115 | Sleep(ms); 116 | } 117 | 118 | typedef HANDLE event; 119 | 120 | static inline void event_init(event *e) 121 | { 122 | *e = CreateEvent(NULL, FALSE, FALSE, NULL); 123 | assert(*e != NULL); 124 | } 125 | 126 | static bool event_wait(event *e) 127 | { 128 | DWORD i = WaitForSingleObject(*e, 2000); 129 | if (i == WAIT_TIMEOUT) 130 | return false; 131 | assert(i == WAIT_OBJECT_0); 132 | return true; 133 | } 134 | 135 | static inline void event_set(event *e) 136 | { 137 | BOOL res = SetEvent(*e); 138 | assert(res); 139 | } 140 | 141 | static inline void event_free(event *e) 142 | { 143 | CloseHandle(*e); 144 | } 145 | 146 | static bool spawn_thread(void *(f)(void *), void *arg) 147 | { 148 | HANDLE thread = CreateThread(NULL, 1, (LPTHREAD_START_ROUTINE)f, 149 | (LPVOID)arg, 0, NULL); 150 | if (thread == NULL) 151 | return false; 152 | CloseHandle(thread); 153 | return true; 154 | } 155 | 156 | typedef SOCKET sock; 157 | typedef uint16_t in_port_t; 158 | 159 | static sock socket_open(void) 160 | { 161 | sock s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 162 | if (s == INVALID_SOCKET) 163 | return INVALID_SOCKET; 164 | unsigned off = 0; 165 | if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, 166 | sizeof(off)) != 0) 167 | { 168 | closesocket(s); 169 | return INVALID_SOCKET; 170 | } 171 | unsigned on = 1; 172 | setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); 173 | setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&on, sizeof(on)); 174 | DWORD timeout = 120000; // 2min 175 | setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); 176 | return s; 177 | } 178 | 179 | static bool socket_bind(sock s, uint16_t port) 180 | { 181 | struct sockaddr_in6 sockaddr; 182 | memset(&sockaddr, 0, sizeof(sockaddr)); 183 | sockaddr.sin6_family = AF_INET6; 184 | sockaddr.sin6_port = port; 185 | if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0) 186 | return false; 187 | return true; 188 | } 189 | 190 | static bool socket_listen(sock s) 191 | { 192 | return (listen(s, 4) == 0); 193 | } 194 | 195 | static sock socket_accept(sock s, struct in6_addr *addr) 196 | { 197 | socklen_t len = sizeof(struct sockaddr_in6); 198 | struct sockaddr_in6 sockaddr; 199 | int s1 = accept(s, (struct sockaddr *)&sockaddr, &len); 200 | if (s1 < 0) 201 | return s1; 202 | *addr = sockaddr.sin6_addr; 203 | return s1; 204 | } 205 | 206 | static bool socket_connect(sock s, struct in6_addr addr, uint16_t port) 207 | { 208 | struct sockaddr_in6 sockaddr; 209 | memset(&sockaddr, 0, sizeof(sockaddr)); 210 | sockaddr.sin6_family = AF_INET6; 211 | sockaddr.sin6_port = port; 212 | sockaddr.sin6_addr = addr; 213 | unsigned long on = 1; 214 | if (ioctlsocket(s, FIONBIO, &on) != 0) 215 | return false; 216 | if (connect(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0 && 217 | WSAGetLastError() != WSAEWOULDBLOCK) 218 | return false; 219 | unsigned long off = 0; 220 | if (ioctlsocket(s, FIONBIO, &off) != 0) 221 | return false; 222 | 223 | struct timeval tv; 224 | tv.tv_sec = 6; 225 | tv.tv_usec = 0; 226 | fd_set fds; 227 | FD_ZERO(&fds); 228 | FD_SET(s, &fds); 229 | int r = select(s+1, NULL, &fds, NULL, &tv); 230 | if (r == 0) 231 | WSASetLastError(WSAETIMEDOUT); 232 | return (r > 0); 233 | } 234 | 235 | static ssize_t socket_recv(sock s, void *buf, size_t len, bool *timeout) 236 | { 237 | *timeout = false; 238 | struct timeval tv; 239 | tv.tv_sec = 2; 240 | tv.tv_usec = 0; 241 | fd_set fds; 242 | FD_ZERO(&fds); 243 | FD_SET(s, &fds); 244 | int r = select(s+1, &fds, NULL, &fds, &tv); 245 | if (r > 0) 246 | return recv(s, buf, len, 0); 247 | if (r == 0) 248 | { 249 | *timeout = true; 250 | return 0; 251 | } 252 | return -1; 253 | } 254 | 255 | static ssize_t socket_send(sock s, void *buf, size_t len) 256 | { 257 | for (size_t i = 0; i < len; ) 258 | { 259 | int r = send(s, buf+i, len-i, 0); 260 | if (r <= 0) 261 | return r; 262 | i += r; 263 | } 264 | return len; 265 | } 266 | 267 | static void socket_close(sock s, bool err) 268 | { 269 | if (!err) 270 | shutdown(s, SD_BOTH); 271 | closesocket(s); 272 | } 273 | 274 | #define s6_addr16 u.Word 275 | 276 | --------------------------------------------------------------------------------