├── .gitignore ├── Makefile ├── README.md ├── bitcoin ├── attributes.h ├── compat │ ├── byteswap.h │ └── endian.h ├── crypto │ └── common.h ├── prevector.h ├── script │ ├── script.cpp │ └── script.h ├── serialize.h ├── span.h ├── tinyformat.h └── util │ ├── strencodings.cpp │ └── strencodings.h ├── main.cpp └── tests ├── run.sh ├── test.asm ├── test.hex ├── test2.asm └── test2.hex /.gitignore: -------------------------------------------------------------------------------- 1 | btcscript 2 | 3 | # Emacs 4 | *~ 5 | \#* 6 | .\#*\# -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS=-Wall -Werror -I./bitcoin # -H -MM (for deptree) 2 | LDFLAGS= 3 | 4 | FILES=main.cpp \ 5 | bitcoin/script/script.cpp \ 6 | bitcoin/util/strencodings.cpp 7 | 8 | btcscript: $(FILES) 9 | $(CXX) $(CXXFLAGS) -o btcscript $(FILES) $(LDFLAGS) 10 | 11 | check: btcscript 12 | @echo "[Integration Tests]" 13 | @tests/run.sh 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # btcscript 2 | 3 | Command-line Bitcoin Script diassembler. 4 | 5 | ## Usage 6 | 7 | Give a file with Script bytecode as a single line hex string `test.hex`: 8 | 9 | ``` 10 | 4730440220210d105c07282560683fc11591a22ca1494664d427643dede7d4a58101047569022077c8cdb8f0964a35cdcecc3149169d9e9fb2313c9aca026e17f60b43f0f4ef82012103921d49f08ee95b41454543e7356bd8631cf80b00c3a2b9c156cacf97524827d6eric 11 | ``` 12 | 13 | We can print the disassembly by running: 14 | 15 | ``` 16 | btcscript test.hex 17 | ``` 18 | 19 | The output should be: 20 | 21 | ``` 22 | OP_PUSHBYTES_71 30440220210d105c07282560683fc11591a22ca1494664d427643dede7d4a58101047569022077c8cdb8f0964a35cdcecc3149169d9e9fb2313c9aca026e17f60b43f0f4ef8201 OP_PUSHBYTES_33 03921d49f08ee95b41454543e7356bd8631cf80b00c3a2b9c156cacf97524827d6 23 | ``` 24 | 25 | ## Compiling 26 | 27 | ``` 28 | make 29 | ``` 30 | 31 | ## Testing 32 | 33 | ``` 34 | make check 35 | ``` 36 | -------------------------------------------------------------------------------- /bitcoin/attributes.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto 2 | // Copyright (c) 2009-2018 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 | #ifndef BITCOIN_ATTRIBUTES_H 7 | #define BITCOIN_ATTRIBUTES_H 8 | 9 | #if defined(__has_cpp_attribute) 10 | # if __has_cpp_attribute(nodiscard) 11 | # define NODISCARD [[nodiscard]] 12 | # endif 13 | #endif 14 | #ifndef NODISCARD 15 | # if defined(_MSC_VER) && _MSC_VER >= 1700 16 | # define NODISCARD _Check_return_ 17 | # else 18 | # define NODISCARD __attribute__((warn_unused_result)) 19 | # endif 20 | #endif 21 | 22 | #endif // BITCOIN_ATTRIBUTES_H 23 | -------------------------------------------------------------------------------- /bitcoin/compat/byteswap.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2018 The Bitcoin Core developers 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #ifndef BITCOIN_COMPAT_BYTESWAP_H 6 | #define BITCOIN_COMPAT_BYTESWAP_H 7 | 8 | #if defined(HAVE_CONFIG_H) 9 | #include 10 | #endif 11 | 12 | #include 13 | 14 | #if defined(HAVE_BYTESWAP_H) 15 | #include 16 | #endif 17 | 18 | #if defined(MAC_OSX) 19 | 20 | #if !defined(bswap_16) 21 | 22 | // Mac OS X / Darwin features; we include a check for bswap_16 because if it is already defined, protobuf has 23 | // defined these macros for us already; if it isn't, we do it ourselves. In either case, we get the exact same 24 | // result regardless which path was taken 25 | #include 26 | #define bswap_16(x) OSSwapInt16(x) 27 | #define bswap_32(x) OSSwapInt32(x) 28 | #define bswap_64(x) OSSwapInt64(x) 29 | 30 | #endif // !defined(bswap_16) 31 | 32 | #else 33 | // Non-Mac OS X / non-Darwin 34 | 35 | #if HAVE_DECL_BSWAP_16 == 0 36 | inline uint16_t bswap_16(uint16_t x) 37 | { 38 | return (x >> 8) | (x << 8); 39 | } 40 | #endif // HAVE_DECL_BSWAP16 == 0 41 | 42 | #if HAVE_DECL_BSWAP_32 == 0 43 | inline uint32_t bswap_32(uint32_t x) 44 | { 45 | return (((x & 0xff000000U) >> 24) | ((x & 0x00ff0000U) >> 8) | 46 | ((x & 0x0000ff00U) << 8) | ((x & 0x000000ffU) << 24)); 47 | } 48 | #endif // HAVE_DECL_BSWAP32 == 0 49 | 50 | #if HAVE_DECL_BSWAP_64 == 0 51 | inline uint64_t bswap_64(uint64_t x) 52 | { 53 | return (((x & 0xff00000000000000ull) >> 56) 54 | | ((x & 0x00ff000000000000ull) >> 40) 55 | | ((x & 0x0000ff0000000000ull) >> 24) 56 | | ((x & 0x000000ff00000000ull) >> 8) 57 | | ((x & 0x00000000ff000000ull) << 8) 58 | | ((x & 0x0000000000ff0000ull) << 24) 59 | | ((x & 0x000000000000ff00ull) << 40) 60 | | ((x & 0x00000000000000ffull) << 56)); 61 | } 62 | #endif // HAVE_DECL_BSWAP64 == 0 63 | 64 | #endif // defined(MAC_OSX) 65 | 66 | #endif // BITCOIN_COMPAT_BYTESWAP_H 67 | -------------------------------------------------------------------------------- /bitcoin/compat/endian.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2018 The Bitcoin Core developers 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #ifndef BITCOIN_COMPAT_ENDIAN_H 6 | #define BITCOIN_COMPAT_ENDIAN_H 7 | 8 | #if defined(HAVE_CONFIG_H) 9 | #include 10 | #endif 11 | 12 | #include 13 | 14 | #include 15 | 16 | #if defined(HAVE_ENDIAN_H) 17 | #include 18 | #elif defined(HAVE_SYS_ENDIAN_H) 19 | #include 20 | #endif 21 | 22 | #ifndef HAVE_CONFIG_H 23 | // While not technically a supported configuration, defaulting to defining these 24 | // DECLs when we were compiled without autotools makes it easier for other build 25 | // systems to build things like libbitcoinconsensus for strange targets. 26 | #ifdef htobe16 27 | #define HAVE_DECL_HTOBE16 1 28 | #endif 29 | #ifdef htole16 30 | #define HAVE_DECL_HTOLE16 1 31 | #endif 32 | #ifdef be16toh 33 | #define HAVE_DECL_BE16TOH 1 34 | #endif 35 | #ifdef le16toh 36 | #define HAVE_DECL_LE16TOH 1 37 | #endif 38 | 39 | #ifdef htobe32 40 | #define HAVE_DECL_HTOBE32 1 41 | #endif 42 | #ifdef htole32 43 | #define HAVE_DECL_HTOLE32 1 44 | #endif 45 | #ifdef be32toh 46 | #define HAVE_DECL_BE32TOH 1 47 | #endif 48 | #ifdef le32toh 49 | #define HAVE_DECL_LE32TOH 1 50 | #endif 51 | 52 | #ifdef htobe64 53 | #define HAVE_DECL_HTOBE64 1 54 | #endif 55 | #ifdef htole64 56 | #define HAVE_DECL_HTOLE64 1 57 | #endif 58 | #ifdef be64toh 59 | #define HAVE_DECL_BE64TOH 1 60 | #endif 61 | #ifdef le64toh 62 | #define HAVE_DECL_LE64TOH 1 63 | #endif 64 | 65 | #endif // HAVE_CONFIG_H 66 | 67 | #if defined(WORDS_BIGENDIAN) 68 | 69 | #if HAVE_DECL_HTOBE16 == 0 70 | inline uint16_t htobe16(uint16_t host_16bits) 71 | { 72 | return host_16bits; 73 | } 74 | #endif // HAVE_DECL_HTOBE16 75 | 76 | #if HAVE_DECL_HTOLE16 == 0 77 | inline uint16_t htole16(uint16_t host_16bits) 78 | { 79 | return bswap_16(host_16bits); 80 | } 81 | #endif // HAVE_DECL_HTOLE16 82 | 83 | #if HAVE_DECL_BE16TOH == 0 84 | inline uint16_t be16toh(uint16_t big_endian_16bits) 85 | { 86 | return big_endian_16bits; 87 | } 88 | #endif // HAVE_DECL_BE16TOH 89 | 90 | #if HAVE_DECL_LE16TOH == 0 91 | inline uint16_t le16toh(uint16_t little_endian_16bits) 92 | { 93 | return bswap_16(little_endian_16bits); 94 | } 95 | #endif // HAVE_DECL_LE16TOH 96 | 97 | #if HAVE_DECL_HTOBE32 == 0 98 | inline uint32_t htobe32(uint32_t host_32bits) 99 | { 100 | return host_32bits; 101 | } 102 | #endif // HAVE_DECL_HTOBE32 103 | 104 | #if HAVE_DECL_HTOLE32 == 0 105 | inline uint32_t htole32(uint32_t host_32bits) 106 | { 107 | return bswap_32(host_32bits); 108 | } 109 | #endif // HAVE_DECL_HTOLE32 110 | 111 | #if HAVE_DECL_BE32TOH == 0 112 | inline uint32_t be32toh(uint32_t big_endian_32bits) 113 | { 114 | return big_endian_32bits; 115 | } 116 | #endif // HAVE_DECL_BE32TOH 117 | 118 | #if HAVE_DECL_LE32TOH == 0 119 | inline uint32_t le32toh(uint32_t little_endian_32bits) 120 | { 121 | return bswap_32(little_endian_32bits); 122 | } 123 | #endif // HAVE_DECL_LE32TOH 124 | 125 | #if HAVE_DECL_HTOBE64 == 0 126 | inline uint64_t htobe64(uint64_t host_64bits) 127 | { 128 | return host_64bits; 129 | } 130 | #endif // HAVE_DECL_HTOBE64 131 | 132 | #if HAVE_DECL_HTOLE64 == 0 133 | inline uint64_t htole64(uint64_t host_64bits) 134 | { 135 | return bswap_64(host_64bits); 136 | } 137 | #endif // HAVE_DECL_HTOLE64 138 | 139 | #if HAVE_DECL_BE64TOH == 0 140 | inline uint64_t be64toh(uint64_t big_endian_64bits) 141 | { 142 | return big_endian_64bits; 143 | } 144 | #endif // HAVE_DECL_BE64TOH 145 | 146 | #if HAVE_DECL_LE64TOH == 0 147 | inline uint64_t le64toh(uint64_t little_endian_64bits) 148 | { 149 | return bswap_64(little_endian_64bits); 150 | } 151 | #endif // HAVE_DECL_LE64TOH 152 | 153 | #else // WORDS_BIGENDIAN 154 | 155 | #if HAVE_DECL_HTOBE16 == 0 156 | inline uint16_t htobe16(uint16_t host_16bits) 157 | { 158 | return bswap_16(host_16bits); 159 | } 160 | #endif // HAVE_DECL_HTOBE16 161 | 162 | #if HAVE_DECL_HTOLE16 == 0 163 | inline uint16_t htole16(uint16_t host_16bits) 164 | { 165 | return host_16bits; 166 | } 167 | #endif // HAVE_DECL_HTOLE16 168 | 169 | #if HAVE_DECL_BE16TOH == 0 170 | inline uint16_t be16toh(uint16_t big_endian_16bits) 171 | { 172 | return bswap_16(big_endian_16bits); 173 | } 174 | #endif // HAVE_DECL_BE16TOH 175 | 176 | #if HAVE_DECL_LE16TOH == 0 177 | inline uint16_t le16toh(uint16_t little_endian_16bits) 178 | { 179 | return little_endian_16bits; 180 | } 181 | #endif // HAVE_DECL_LE16TOH 182 | 183 | #if HAVE_DECL_HTOBE32 == 0 184 | inline uint32_t htobe32(uint32_t host_32bits) 185 | { 186 | return bswap_32(host_32bits); 187 | } 188 | #endif // HAVE_DECL_HTOBE32 189 | 190 | #if HAVE_DECL_HTOLE32 == 0 191 | inline uint32_t htole32(uint32_t host_32bits) 192 | { 193 | return host_32bits; 194 | } 195 | #endif // HAVE_DECL_HTOLE32 196 | 197 | #if HAVE_DECL_BE32TOH == 0 198 | inline uint32_t be32toh(uint32_t big_endian_32bits) 199 | { 200 | return bswap_32(big_endian_32bits); 201 | } 202 | #endif // HAVE_DECL_BE32TOH 203 | 204 | #if HAVE_DECL_LE32TOH == 0 205 | inline uint32_t le32toh(uint32_t little_endian_32bits) 206 | { 207 | return little_endian_32bits; 208 | } 209 | #endif // HAVE_DECL_LE32TOH 210 | 211 | #if HAVE_DECL_HTOBE64 == 0 212 | inline uint64_t htobe64(uint64_t host_64bits) 213 | { 214 | return bswap_64(host_64bits); 215 | } 216 | #endif // HAVE_DECL_HTOBE64 217 | 218 | #if HAVE_DECL_HTOLE64 == 0 219 | inline uint64_t htole64(uint64_t host_64bits) 220 | { 221 | return host_64bits; 222 | } 223 | #endif // HAVE_DECL_HTOLE64 224 | 225 | #if HAVE_DECL_BE64TOH == 0 226 | inline uint64_t be64toh(uint64_t big_endian_64bits) 227 | { 228 | return bswap_64(big_endian_64bits); 229 | } 230 | #endif // HAVE_DECL_BE64TOH 231 | 232 | #if HAVE_DECL_LE64TOH == 0 233 | inline uint64_t le64toh(uint64_t little_endian_64bits) 234 | { 235 | return little_endian_64bits; 236 | } 237 | #endif // HAVE_DECL_LE64TOH 238 | 239 | #endif // WORDS_BIGENDIAN 240 | 241 | #endif // BITCOIN_COMPAT_ENDIAN_H 242 | -------------------------------------------------------------------------------- /bitcoin/crypto/common.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2018 The Bitcoin Core developers 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #ifndef BITCOIN_CRYPTO_COMMON_H 6 | #define BITCOIN_CRYPTO_COMMON_H 7 | 8 | #if defined(HAVE_CONFIG_H) 9 | #include 10 | #endif 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | uint16_t static inline ReadLE16(const unsigned char* ptr) 18 | { 19 | uint16_t x; 20 | memcpy((char*)&x, ptr, 2); 21 | return le16toh(x); 22 | } 23 | 24 | uint32_t static inline ReadLE32(const unsigned char* ptr) 25 | { 26 | uint32_t x; 27 | memcpy((char*)&x, ptr, 4); 28 | return le32toh(x); 29 | } 30 | 31 | uint64_t static inline ReadLE64(const unsigned char* ptr) 32 | { 33 | uint64_t x; 34 | memcpy((char*)&x, ptr, 8); 35 | return le64toh(x); 36 | } 37 | 38 | void static inline WriteLE16(unsigned char* ptr, uint16_t x) 39 | { 40 | uint16_t v = htole16(x); 41 | memcpy(ptr, (char*)&v, 2); 42 | } 43 | 44 | void static inline WriteLE32(unsigned char* ptr, uint32_t x) 45 | { 46 | uint32_t v = htole32(x); 47 | memcpy(ptr, (char*)&v, 4); 48 | } 49 | 50 | void static inline WriteLE64(unsigned char* ptr, uint64_t x) 51 | { 52 | uint64_t v = htole64(x); 53 | memcpy(ptr, (char*)&v, 8); 54 | } 55 | 56 | uint32_t static inline ReadBE32(const unsigned char* ptr) 57 | { 58 | uint32_t x; 59 | memcpy((char*)&x, ptr, 4); 60 | return be32toh(x); 61 | } 62 | 63 | uint64_t static inline ReadBE64(const unsigned char* ptr) 64 | { 65 | uint64_t x; 66 | memcpy((char*)&x, ptr, 8); 67 | return be64toh(x); 68 | } 69 | 70 | void static inline WriteBE32(unsigned char* ptr, uint32_t x) 71 | { 72 | uint32_t v = htobe32(x); 73 | memcpy(ptr, (char*)&v, 4); 74 | } 75 | 76 | void static inline WriteBE64(unsigned char* ptr, uint64_t x) 77 | { 78 | uint64_t v = htobe64(x); 79 | memcpy(ptr, (char*)&v, 8); 80 | } 81 | 82 | /** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */ 83 | uint64_t static inline CountBits(uint64_t x) 84 | { 85 | #if HAVE_DECL___BUILTIN_CLZL 86 | if (sizeof(unsigned long) >= sizeof(uint64_t)) { 87 | return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0; 88 | } 89 | #endif 90 | #if HAVE_DECL___BUILTIN_CLZLL 91 | if (sizeof(unsigned long long) >= sizeof(uint64_t)) { 92 | return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0; 93 | } 94 | #endif 95 | int ret = 0; 96 | while (x) { 97 | x >>= 1; 98 | ++ret; 99 | } 100 | return ret; 101 | } 102 | 103 | #endif // BITCOIN_CRYPTO_COMMON_H 104 | -------------------------------------------------------------------------------- /bitcoin/prevector.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015-2018 The Bitcoin Core developers 2 | // Distributed under the MIT software license, see the accompanying 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | 5 | #ifndef BITCOIN_PREVECTOR_H 6 | #define BITCOIN_PREVECTOR_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #pragma pack(push, 1) 19 | /** Implements a drop-in replacement for std::vector which stores up to N 20 | * elements directly (without heap allocation). The types Size and Diff are 21 | * used to store element counts, and can be any unsigned + signed type. 22 | * 23 | * Storage layout is either: 24 | * - Direct allocation: 25 | * - Size _size: the number of used elements (between 0 and N) 26 | * - T direct[N]: an array of N elements of type T 27 | * (only the first _size are initialized). 28 | * - Indirect allocation: 29 | * - Size _size: the number of used elements plus N + 1 30 | * - Size capacity: the number of allocated elements 31 | * - T* indirect: a pointer to an array of capacity elements of type T 32 | * (only the first _size are initialized). 33 | * 34 | * The data type T must be movable by memmove/realloc(). Once we switch to C++, 35 | * move constructors can be used instead. 36 | */ 37 | template 38 | class prevector { 39 | public: 40 | typedef Size size_type; 41 | typedef Diff difference_type; 42 | typedef T value_type; 43 | typedef value_type& reference; 44 | typedef const value_type& const_reference; 45 | typedef value_type* pointer; 46 | typedef const value_type* const_pointer; 47 | 48 | class iterator { 49 | T* ptr; 50 | public: 51 | typedef Diff difference_type; 52 | typedef T value_type; 53 | typedef T* pointer; 54 | typedef T& reference; 55 | typedef std::random_access_iterator_tag iterator_category; 56 | iterator(T* ptr_) : ptr(ptr_) {} 57 | T& operator*() const { return *ptr; } 58 | T* operator->() const { return ptr; } 59 | T& operator[](size_type pos) { return ptr[pos]; } 60 | const T& operator[](size_type pos) const { return ptr[pos]; } 61 | iterator& operator++() { ptr++; return *this; } 62 | iterator& operator--() { ptr--; return *this; } 63 | iterator operator++(int) { iterator copy(*this); ++(*this); return copy; } 64 | iterator operator--(int) { iterator copy(*this); --(*this); return copy; } 65 | difference_type friend operator-(iterator a, iterator b) { return (&(*a) - &(*b)); } 66 | iterator operator+(size_type n) { return iterator(ptr + n); } 67 | iterator& operator+=(size_type n) { ptr += n; return *this; } 68 | iterator operator-(size_type n) { return iterator(ptr - n); } 69 | iterator& operator-=(size_type n) { ptr -= n; return *this; } 70 | bool operator==(iterator x) const { return ptr == x.ptr; } 71 | bool operator!=(iterator x) const { return ptr != x.ptr; } 72 | bool operator>=(iterator x) const { return ptr >= x.ptr; } 73 | bool operator<=(iterator x) const { return ptr <= x.ptr; } 74 | bool operator>(iterator x) const { return ptr > x.ptr; } 75 | bool operator<(iterator x) const { return ptr < x.ptr; } 76 | }; 77 | 78 | class reverse_iterator { 79 | T* ptr; 80 | public: 81 | typedef Diff difference_type; 82 | typedef T value_type; 83 | typedef T* pointer; 84 | typedef T& reference; 85 | typedef std::bidirectional_iterator_tag iterator_category; 86 | reverse_iterator(T* ptr_) : ptr(ptr_) {} 87 | T& operator*() { return *ptr; } 88 | const T& operator*() const { return *ptr; } 89 | T* operator->() { return ptr; } 90 | const T* operator->() const { return ptr; } 91 | reverse_iterator& operator--() { ptr++; return *this; } 92 | reverse_iterator& operator++() { ptr--; return *this; } 93 | reverse_iterator operator++(int) { reverse_iterator copy(*this); ++(*this); return copy; } 94 | reverse_iterator operator--(int) { reverse_iterator copy(*this); --(*this); return copy; } 95 | bool operator==(reverse_iterator x) const { return ptr == x.ptr; } 96 | bool operator!=(reverse_iterator x) const { return ptr != x.ptr; } 97 | }; 98 | 99 | class const_iterator { 100 | const T* ptr; 101 | public: 102 | typedef Diff difference_type; 103 | typedef const T value_type; 104 | typedef const T* pointer; 105 | typedef const T& reference; 106 | typedef std::random_access_iterator_tag iterator_category; 107 | const_iterator(const T* ptr_) : ptr(ptr_) {} 108 | const_iterator(iterator x) : ptr(&(*x)) {} 109 | const T& operator*() const { return *ptr; } 110 | const T* operator->() const { return ptr; } 111 | const T& operator[](size_type pos) const { return ptr[pos]; } 112 | const_iterator& operator++() { ptr++; return *this; } 113 | const_iterator& operator--() { ptr--; return *this; } 114 | const_iterator operator++(int) { const_iterator copy(*this); ++(*this); return copy; } 115 | const_iterator operator--(int) { const_iterator copy(*this); --(*this); return copy; } 116 | difference_type friend operator-(const_iterator a, const_iterator b) { return (&(*a) - &(*b)); } 117 | const_iterator operator+(size_type n) { return const_iterator(ptr + n); } 118 | const_iterator& operator+=(size_type n) { ptr += n; return *this; } 119 | const_iterator operator-(size_type n) { return const_iterator(ptr - n); } 120 | const_iterator& operator-=(size_type n) { ptr -= n; return *this; } 121 | bool operator==(const_iterator x) const { return ptr == x.ptr; } 122 | bool operator!=(const_iterator x) const { return ptr != x.ptr; } 123 | bool operator>=(const_iterator x) const { return ptr >= x.ptr; } 124 | bool operator<=(const_iterator x) const { return ptr <= x.ptr; } 125 | bool operator>(const_iterator x) const { return ptr > x.ptr; } 126 | bool operator<(const_iterator x) const { return ptr < x.ptr; } 127 | }; 128 | 129 | class const_reverse_iterator { 130 | const T* ptr; 131 | public: 132 | typedef Diff difference_type; 133 | typedef const T value_type; 134 | typedef const T* pointer; 135 | typedef const T& reference; 136 | typedef std::bidirectional_iterator_tag iterator_category; 137 | const_reverse_iterator(const T* ptr_) : ptr(ptr_) {} 138 | const_reverse_iterator(reverse_iterator x) : ptr(&(*x)) {} 139 | const T& operator*() const { return *ptr; } 140 | const T* operator->() const { return ptr; } 141 | const_reverse_iterator& operator--() { ptr++; return *this; } 142 | const_reverse_iterator& operator++() { ptr--; return *this; } 143 | const_reverse_iterator operator++(int) { const_reverse_iterator copy(*this); ++(*this); return copy; } 144 | const_reverse_iterator operator--(int) { const_reverse_iterator copy(*this); --(*this); return copy; } 145 | bool operator==(const_reverse_iterator x) const { return ptr == x.ptr; } 146 | bool operator!=(const_reverse_iterator x) const { return ptr != x.ptr; } 147 | }; 148 | 149 | private: 150 | size_type _size = 0; 151 | union direct_or_indirect { 152 | char direct[sizeof(T) * N]; 153 | struct { 154 | size_type capacity; 155 | char* indirect; 156 | }; 157 | } _union = {}; 158 | 159 | T* direct_ptr(difference_type pos) { return reinterpret_cast(_union.direct) + pos; } 160 | const T* direct_ptr(difference_type pos) const { return reinterpret_cast(_union.direct) + pos; } 161 | T* indirect_ptr(difference_type pos) { return reinterpret_cast(_union.indirect) + pos; } 162 | const T* indirect_ptr(difference_type pos) const { return reinterpret_cast(_union.indirect) + pos; } 163 | bool is_direct() const { return _size <= N; } 164 | 165 | void change_capacity(size_type new_capacity) { 166 | if (new_capacity <= N) { 167 | if (!is_direct()) { 168 | T* indirect = indirect_ptr(0); 169 | T* src = indirect; 170 | T* dst = direct_ptr(0); 171 | memcpy(dst, src, size() * sizeof(T)); 172 | free(indirect); 173 | _size -= N + 1; 174 | } 175 | } else { 176 | if (!is_direct()) { 177 | /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert 178 | success. These should instead use an allocator or new/delete so that handlers 179 | are called as necessary, but performance would be slightly degraded by doing so. */ 180 | _union.indirect = static_cast(realloc(_union.indirect, ((size_t)sizeof(T)) * new_capacity)); 181 | assert(_union.indirect); 182 | _union.capacity = new_capacity; 183 | } else { 184 | char* new_indirect = static_cast(malloc(((size_t)sizeof(T)) * new_capacity)); 185 | assert(new_indirect); 186 | T* src = direct_ptr(0); 187 | T* dst = reinterpret_cast(new_indirect); 188 | memcpy(dst, src, size() * sizeof(T)); 189 | _union.indirect = new_indirect; 190 | _union.capacity = new_capacity; 191 | _size += N + 1; 192 | } 193 | } 194 | } 195 | 196 | T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); } 197 | const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); } 198 | 199 | void fill(T* dst, ptrdiff_t count, const T& value = T{}) { 200 | std::fill_n(dst, count, value); 201 | } 202 | 203 | template 204 | void fill(T* dst, InputIterator first, InputIterator last) { 205 | while (first != last) { 206 | new(static_cast(dst)) T(*first); 207 | ++dst; 208 | ++first; 209 | } 210 | } 211 | 212 | public: 213 | void assign(size_type n, const T& val) { 214 | clear(); 215 | if (capacity() < n) { 216 | change_capacity(n); 217 | } 218 | _size += n; 219 | fill(item_ptr(0), n, val); 220 | } 221 | 222 | template 223 | void assign(InputIterator first, InputIterator last) { 224 | size_type n = last - first; 225 | clear(); 226 | if (capacity() < n) { 227 | change_capacity(n); 228 | } 229 | _size += n; 230 | fill(item_ptr(0), first, last); 231 | } 232 | 233 | prevector() {} 234 | 235 | explicit prevector(size_type n) { 236 | resize(n); 237 | } 238 | 239 | explicit prevector(size_type n, const T& val) { 240 | change_capacity(n); 241 | _size += n; 242 | fill(item_ptr(0), n, val); 243 | } 244 | 245 | template 246 | prevector(InputIterator first, InputIterator last) { 247 | size_type n = last - first; 248 | change_capacity(n); 249 | _size += n; 250 | fill(item_ptr(0), first, last); 251 | } 252 | 253 | prevector(const prevector& other) { 254 | size_type n = other.size(); 255 | change_capacity(n); 256 | _size += n; 257 | fill(item_ptr(0), other.begin(), other.end()); 258 | } 259 | 260 | prevector(prevector&& other) { 261 | swap(other); 262 | } 263 | 264 | prevector& operator=(const prevector& other) { 265 | if (&other == this) { 266 | return *this; 267 | } 268 | assign(other.begin(), other.end()); 269 | return *this; 270 | } 271 | 272 | prevector& operator=(prevector&& other) { 273 | swap(other); 274 | return *this; 275 | } 276 | 277 | size_type size() const { 278 | return is_direct() ? _size : _size - N - 1; 279 | } 280 | 281 | bool empty() const { 282 | return size() == 0; 283 | } 284 | 285 | iterator begin() { return iterator(item_ptr(0)); } 286 | const_iterator begin() const { return const_iterator(item_ptr(0)); } 287 | iterator end() { return iterator(item_ptr(size())); } 288 | const_iterator end() const { return const_iterator(item_ptr(size())); } 289 | 290 | reverse_iterator rbegin() { return reverse_iterator(item_ptr(size() - 1)); } 291 | const_reverse_iterator rbegin() const { return const_reverse_iterator(item_ptr(size() - 1)); } 292 | reverse_iterator rend() { return reverse_iterator(item_ptr(-1)); } 293 | const_reverse_iterator rend() const { return const_reverse_iterator(item_ptr(-1)); } 294 | 295 | size_t capacity() const { 296 | if (is_direct()) { 297 | return N; 298 | } else { 299 | return _union.capacity; 300 | } 301 | } 302 | 303 | T& operator[](size_type pos) { 304 | return *item_ptr(pos); 305 | } 306 | 307 | const T& operator[](size_type pos) const { 308 | return *item_ptr(pos); 309 | } 310 | 311 | void resize(size_type new_size) { 312 | size_type cur_size = size(); 313 | if (cur_size == new_size) { 314 | return; 315 | } 316 | if (cur_size > new_size) { 317 | erase(item_ptr(new_size), end()); 318 | return; 319 | } 320 | if (new_size > capacity()) { 321 | change_capacity(new_size); 322 | } 323 | ptrdiff_t increase = new_size - cur_size; 324 | fill(item_ptr(cur_size), increase); 325 | _size += increase; 326 | } 327 | 328 | void reserve(size_type new_capacity) { 329 | if (new_capacity > capacity()) { 330 | change_capacity(new_capacity); 331 | } 332 | } 333 | 334 | void shrink_to_fit() { 335 | change_capacity(size()); 336 | } 337 | 338 | void clear() { 339 | resize(0); 340 | } 341 | 342 | iterator insert(iterator pos, const T& value) { 343 | size_type p = pos - begin(); 344 | size_type new_size = size() + 1; 345 | if (capacity() < new_size) { 346 | change_capacity(new_size + (new_size >> 1)); 347 | } 348 | T* ptr = item_ptr(p); 349 | memmove(ptr + 1, ptr, (size() - p) * sizeof(T)); 350 | _size++; 351 | new(static_cast(ptr)) T(value); 352 | return iterator(ptr); 353 | } 354 | 355 | void insert(iterator pos, size_type count, const T& value) { 356 | size_type p = pos - begin(); 357 | size_type new_size = size() + count; 358 | if (capacity() < new_size) { 359 | change_capacity(new_size + (new_size >> 1)); 360 | } 361 | T* ptr = item_ptr(p); 362 | memmove(ptr + count, ptr, (size() - p) * sizeof(T)); 363 | _size += count; 364 | fill(item_ptr(p), count, value); 365 | } 366 | 367 | template 368 | void insert(iterator pos, InputIterator first, InputIterator last) { 369 | size_type p = pos - begin(); 370 | difference_type count = last - first; 371 | size_type new_size = size() + count; 372 | if (capacity() < new_size) { 373 | change_capacity(new_size + (new_size >> 1)); 374 | } 375 | T* ptr = item_ptr(p); 376 | memmove(ptr + count, ptr, (size() - p) * sizeof(T)); 377 | _size += count; 378 | fill(ptr, first, last); 379 | } 380 | 381 | inline void resize_uninitialized(size_type new_size) { 382 | // resize_uninitialized changes the size of the prevector but does not initialize it. 383 | // If size < new_size, the added elements must be initialized explicitly. 384 | if (capacity() < new_size) { 385 | change_capacity(new_size); 386 | _size += new_size - size(); 387 | return; 388 | } 389 | if (new_size < size()) { 390 | erase(item_ptr(new_size), end()); 391 | } else { 392 | _size += new_size - size(); 393 | } 394 | } 395 | 396 | iterator erase(iterator pos) { 397 | return erase(pos, pos + 1); 398 | } 399 | 400 | iterator erase(iterator first, iterator last) { 401 | // Erase is not allowed to the change the object's capacity. That means 402 | // that when starting with an indirectly allocated prevector with 403 | // size and capacity > N, the result may be a still indirectly allocated 404 | // prevector with size <= N and capacity > N. A shrink_to_fit() call is 405 | // necessary to switch to the (more efficient) directly allocated 406 | // representation (with capacity N and size <= N). 407 | iterator p = first; 408 | char* endp = (char*)&(*end()); 409 | if (!std::is_trivially_destructible::value) { 410 | while (p != last) { 411 | (*p).~T(); 412 | _size--; 413 | ++p; 414 | } 415 | } else { 416 | _size -= last - p; 417 | } 418 | memmove(&(*first), &(*last), endp - ((char*)(&(*last)))); 419 | return first; 420 | } 421 | 422 | void push_back(const T& value) { 423 | size_type new_size = size() + 1; 424 | if (capacity() < new_size) { 425 | change_capacity(new_size + (new_size >> 1)); 426 | } 427 | new(item_ptr(size())) T(value); 428 | _size++; 429 | } 430 | 431 | void pop_back() { 432 | erase(end() - 1, end()); 433 | } 434 | 435 | T& front() { 436 | return *item_ptr(0); 437 | } 438 | 439 | const T& front() const { 440 | return *item_ptr(0); 441 | } 442 | 443 | T& back() { 444 | return *item_ptr(size() - 1); 445 | } 446 | 447 | const T& back() const { 448 | return *item_ptr(size() - 1); 449 | } 450 | 451 | void swap(prevector& other) { 452 | std::swap(_union, other._union); 453 | std::swap(_size, other._size); 454 | } 455 | 456 | ~prevector() { 457 | if (!std::is_trivially_destructible::value) { 458 | clear(); 459 | } 460 | if (!is_direct()) { 461 | free(_union.indirect); 462 | _union.indirect = nullptr; 463 | } 464 | } 465 | 466 | bool operator==(const prevector& other) const { 467 | if (other.size() != size()) { 468 | return false; 469 | } 470 | const_iterator b1 = begin(); 471 | const_iterator b2 = other.begin(); 472 | const_iterator e1 = end(); 473 | while (b1 != e1) { 474 | if ((*b1) != (*b2)) { 475 | return false; 476 | } 477 | ++b1; 478 | ++b2; 479 | } 480 | return true; 481 | } 482 | 483 | bool operator!=(const prevector& other) const { 484 | return !(*this == other); 485 | } 486 | 487 | bool operator<(const prevector& other) const { 488 | if (size() < other.size()) { 489 | return true; 490 | } 491 | if (size() > other.size()) { 492 | return false; 493 | } 494 | const_iterator b1 = begin(); 495 | const_iterator b2 = other.begin(); 496 | const_iterator e1 = end(); 497 | while (b1 != e1) { 498 | if ((*b1) < (*b2)) { 499 | return true; 500 | } 501 | if ((*b2) < (*b1)) { 502 | return false; 503 | } 504 | ++b1; 505 | ++b2; 506 | } 507 | return false; 508 | } 509 | 510 | size_t allocated_memory() const { 511 | if (is_direct()) { 512 | return 0; 513 | } else { 514 | return ((size_t)(sizeof(T))) * _union.capacity; 515 | } 516 | } 517 | 518 | value_type* data() { 519 | return item_ptr(0); 520 | } 521 | 522 | const value_type* data() const { 523 | return item_ptr(0); 524 | } 525 | }; 526 | #pragma pack(pop) 527 | 528 | #endif // BITCOIN_PREVECTOR_H 529 | -------------------------------------------------------------------------------- /bitcoin/script/script.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto 2 | // Copyright (c) 2009-2018 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