Skip to content

Instantly share code, notes, and snippets.

@jb55
Last active October 22, 2017 08:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jb55/af967a43fb53185d17bb4b5087eca0bd to your computer and use it in GitHub Desktop.
Save jb55/af967a43fb53185d17bb4b5087eca0bd to your computer and use it in GitHub Desktop.
enum opcode_token
{
// push value
_OP_0=1,
_OP_FALSE,
_OP_PUSHDATA1,
_OP_PUSHDATA2,
_OP_PUSHDATA4,
_OP_1NEGATE,
_OP_RESERVED,
_OP_1,
_OP_TRUE,
_OP_2,
_OP_3,
_OP_4,
_OP_5,
_OP_6,
_OP_7,
_OP_8,
_OP_9,
_OP_10,
_OP_11,
_OP_12,
_OP_13,
_OP_14,
_OP_15,
_OP_16,
// control
_OP_NOP,
_OP_VER,
_OP_IF,
_OP_NOTIF,
_OP_VERIF,
_OP_VERNOTIF,
_OP_ELSE,
_OP_ENDIF,
_OP_VERIFY,
_OP_RETURN,
// stack ops
_OP_TOALTSTACK,
_OP_FROMALTSTACK,
_OP_2DROP,
_OP_2DUP,
_OP_3DUP,
_OP_2OVER,
_OP_2ROT,
_OP_2SWAP,
_OP_IFDUP,
_OP_DEPTH,
_OP_DROP,
_OP_DUP,
_OP_NIP,
_OP_OVER,
_OP_PICK,
_OP_ROLL,
_OP_ROT,
_OP_SWAP,
_OP_TUCK,
// splice ops
_OP_CAT,
_OP_SUBSTR,
_OP_LEFT,
_OP_RIGHT,
_OP_SIZE,
// bit logic
_OP_INVERT,
_OP_AND,
_OP_OR,
_OP_XOR,
_OP_EQUAL,
_OP_EQUALVERIFY,
_OP_RESERVED1,
_OP_RESERVED2,
// numeric
_OP_1ADD,
_OP_1SUB,
_OP_2MUL,
_OP_2DIV,
_OP_NEGATE,
_OP_ABS,
_OP_NOT,
_OP_0NOTEQUAL,
_OP_ADD,
_OP_SUB,
_OP_MUL,
_OP_DIV,
_OP_MOD,
_OP_LSHIFT,
_OP_RSHIFT,
_OP_BOOLAND,
_OP_BOOLOR,
_OP_NUMEQUAL,
_OP_NUMEQUALVERIFY,
_OP_NUMNOTEQUAL,
_OP_LESSTHAN,
_OP_GREATERTHAN,
_OP_LESSTHANOREQUAL,
_OP_GREATERTHANOREQUAL,
_OP_MIN,
_OP_MAX,
_OP_WITHIN,
// crypto
_OP_RIPEMD160,
_OP_SHA1,
_OP_SHA256,
_OP_HASH160,
_OP_HASH256,
_OP_CODESEPARATOR,
_OP_CHECKSIG,
_OP_CHECKSIGVERIFY,
_OP_CHECKMULTISIG,
_OP_CHECKMULTISIGVERIFY,
// expansion
_OP_NOP1,
_OP_CHECKLOCKTIMEVERIFY,
_OP_NOP2,
_OP_CHECKSEQUENCEVERIFY,
_OP_NOP3,
_OP_NOP4,
_OP_NOP5,
_OP_NOP6,
_OP_NOP7,
_OP_NOP8,
_OP_NOP9,
_OP_NOP10,
// template matching params
_OP_SMALLINTEGER,
_OP_PUBKEYS,
_OP_PUBKEYHASH,
_OP_PUBKEY,
_OP_INVALIDOPCODE,
};
#!/usr/bin/env python
# Easy Perfect Minimal Hashing
# By Steve Hanov. Released to the public domain.
#
# Based on:
# Edward A. Fox, Lenwood S. Heath, Qi Fan Chen and Amjad M. Daoud,
# "Practical minimal perfect hash functions for large databases", CACM, 35(1):105-121
# also a good reference:
# Compress, Hash, and Displace algorithm by Djamal Belazzougui,
# Fabiano C. Botelho, and Martin Dietzfelbinger
import sys
DICTIONARY = sys.argv[1]
# Calculates a distinct hash function for a given string. Each value of the
# integer d results in a different hash value.
def hash( d, str ):
if d == 0: d = 0x01000193
# Use the FNV algorithm from http://isthe.com/chongo/tech/comp/fnv/
for c in str:
d = ( (d * 0x01000193) ^ ord(c) ) & 0xffffffff;
return d
# Computes a minimal perfect hash table using the given python dictionary. It
# returns a tuple (G, V). G and V are both arrays. G contains the intermediate
# table of values needed to compute the index of the value in V. V contains the
# values of the dictionary.
def CreateMinimalPerfectHash( dict ):
size = len(dict)
# Step 1: Place all of the keys into buckets
buckets = [ [] for i in range(size) ]
G = [0] * size
values = [None] * size
for key in dict.keys():
buckets[hash(0, key) % size].append( key )
# Step 2: Sort the buckets and process the ones with the most items first.
buckets.sort( key=len, reverse=True )
for b in xrange( size ):
bucket = buckets[b]
if len(bucket) <= 1: break
d = 1
item = 0
slots = []
# Repeatedly try different values of d until we find a hash function
# that places all items in the bucket into free slots
while item < len(bucket):
slot = hash( d, bucket[item] ) % size
if values[slot] != None or slot in slots:
d += 1
item = 0
slots = []
else:
slots.append( slot )
item += 1
G[hash(0, bucket[0]) % size] = d
for i in range(len(bucket)):
values[slots[i]] = dict[bucket[i]]
# Only buckets with 1 item remain. Process them more quickly by directly
# placing them into a free slot. Use a negative value of d to indicate
# this.
freelist = []
for i in xrange(size):
if values[i] == None: freelist.append( i )
for b in xrange( b, size ):
bucket = buckets[b]
if len(bucket) == 0: break
slot = freelist.pop()
# We subtract one to ensure it's negative even if the zeroeth slot was
# used.
G[hash(0, bucket[0]) % size] = -slot-1
values[slot] = dict[bucket[0]]
return (G, values)
# Look up a value in the hash table, defined by G and V.
def PerfectHashLookup( G, V, key ):
d = G[hash(0,key) % len(G)]
if d < 0: return V[-d-1]
return V[hash(d, key) % len(V)]
dict = {}
line = 1
keys = map(lambda x: x.strip(), open(DICTIONARY, "rt").readlines())
for key in keys:
dict[key] = line
line += 1
(G, V) = CreateMinimalPerfectHash( dict )
Gstrs = ",".join(map(str, G))
Vstrs = ",".join(map(str, V))
header = open('oplookup.h', 'w')
header.write("#include \"misc.h\"\n")
header.write("extern int opcodes_g[{}];\n".format(len(G)))
header.write("extern int opcodes_v[{}];\n".format(len(V)))
header.close()
cfile = open('oplookup.c', 'w')
cfile.write("#include \"oplookup.h\"\n".format(Gstrs))
cfile.write("int opcodes_g[{}] = {{ {} }};\n".format(len(G), Gstrs))
cfile.write("int opcodes_v[{}] = {{ {} }};\n".format(len(V), Vstrs))
cfile.close()
0
FALSE
PUSHDATA1
PUSHDATA2
PUSHDATA4
1NEGATE
RESERVED
1
TRUE
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NOP
VER
IF
NOTIF
VERIF
VERNOTIF
ELSE
ENDIF
VERIFY
RETURN
TOALTSTACK
FROMALTSTACK
2DROP
2DUP
3DUP
2OVER
2ROT
2SWAP
IFDUP
DEPTH
DROP
DUP
NIP
OVER
PICK
ROLL
ROT
SWAP
TUCK
CAT
SUBSTR
LEFT
RIGHT
SIZE
INVERT
AND
OR
XOR
EQUAL
EQUALVERIFY
RESERVED1
RESERVED2
1ADD
1SUB
2MUL
2DIV
NEGATE
ABS
NOT
0NOTEQUAL
ADD
SUB
MUL
DIV
MOD
LSHIFT
RSHIFT
BOOLAND
BOOLOR
NUMEQUAL
NUMEQUALVERIFY
NUMNOTEQUAL
LESSTHAN
GREATERTHAN
LESSTHANOREQUAL
GREATERTHANOREQUAL
MIN
MAX
WITHIN
RIPEMD160
SHA1
SHA256
HASH160
HASH256
CODESEPARATOR
CHECKSIG
CHECKSIGVERIFY
CHECKMULTISIG
CHECKMULTISIGVERIFY
NOP1
CHECKLOCKTIMEVERIFY
NOP2
CHECKSEQUENCEVERIFY
NOP3
NOP4
NOP5
NOP6
NOP7
NOP8
NOP9
NOP10
SMALLINTEGER
PUBKEYS
PUBKEYHASH
PUBKEY
INVALIDOPCODE
#include "oplookup.h"
int opcodes_g[120] = { 1,-118,0,2,-116,0,0,2,0,0,0,-114,3,-111,8,0,0,0,0,8,-110,-107,1,0,0,-101,0,-98,0,-92,0,10,1,1,0,0,0,0,-89,0,5,-88,2,-87,4,-86,-79,-78,2,0,-74,-73,-72,-70,-69,0,1,1,-63,-61,-59,-56,-55,0,0,0,-53,0,-49,0,1,-48,0,-47,0,0,2,-46,1,0,5,3,-44,-41,0,2,-38,-33,-30,14,-29,0,2,0,-28,0,-27,0,0,-26,0,0,-23,0,0,0,-20,1,-18,0,-15,-12,8,1,0,-10,10,2,6,7 };
int opcodes_v[120] = { 66,111,5,90,50,33,76,105,6,104,65,77,55,32,116,49,71,85,75,113,60,26,52,88,46,57,86,41,96,36,18,19,69,56,95,63,42,51,30,117,4,13,80,64,68,72,67,59,74,89,83,34,44,53,24,23,48,39,22,47,21,70,20,109,112,7,103,40,25,43,8,2,9,73,99,110,81,14,15,106,97,45,17,16,29,12,10,1,120,114,58,118,31,82,37,62,92,102,3,108,107,11,28,93,27,94,79,115,98,78,87,54,38,101,35,100,119,91,84,61 };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment