def eval_contract(block, transaction_list, tx): sys.stderr.write("evaluating contract\n") address = tx.to # Initialize stack stack = [] index = 0 stepcounter = 0 contract = block.get_contract(address) if not contract: return while 1: # Convert the data item into a code piece val_at_index = decode(contract.get(encode(index, 256, 32)), 256) code = [int(val_at_index / (256**i)) % 256 for i in range(6)] code[0] = scriptcode_map.get(code[0], 'INVALID') sys.stderr.write("Evaluating: " + str(code) + "\n") # Invalid code instruction or STOP code stops execution sans fee if val_at_index >= 256 or code[0] in ['STOP', 'INVALID']: sys.stderr.write("stop code, exiting\n") break # Calculate fee minerfee = 0 nullfee = 0 stepcounter += 1 if stepcounter > 16: minerfee += getfee("stepfee") c = scriptcode_map[code[0]] if c in ['STORE', 'LOAD']: minerfee += getfee("datafee") if c in ['EXTRO', 'BALANCE']: minerfee += getfee("extrofee") if c in [ 'SHA256', 'RIPEMD-160', 'ECMUL', 'ECADD', 'ECSIGN', 'ECRECOVER' ]: minerfee += getfee("cryptofee") if c == 'STORE': existing = block.get_contract_state(address, code[2]) if reg[code[1]] != 0: nullfee += getfee("memoryfee") if existing: nullfee -= getfee("memoryfee") # If we can't pay the fee, break, otherwise pay it if block.get_balance(address) < minerfee + nullfee: sys.stderr.write("insufficient fee, exiting\n") break block.set_balance(address, block.get_balance(address) - nullfee - minerfee) block.reward += minerfee sys.stderr.write("evaluating operation\n") exit = False def stack_pop(n): if len(stack) < n: sys.stderr.write("Stack height insufficient, exiting") exit = True return [0] * n o = stack[-n:] stack = stack[:-n] return o # Evaluate operations if c == 'ADD': x, y = stack_pop(2) stack.append((x + y) % 2**256) elif c == 'MUL': x, y = stack_pop(2) stack.append((x * y) % 2**256) elif c == 'SUB': x, y = stack_pop(2) stack.append((x - y) % 2**256) elif c == 'DIV': x, y = stack_pop(2) if y == 0: break stack.append(int(x / y)) elif c == 'SDIV': x, y = stack_pop(2) if y == 0: break sign = (1 if x < 2**255 else -1) * (1 if y < 2**255 else -1) xx = x if x < 2**255 else 2**256 - x yy = y if y < 2**255 else 2**256 - y z = int(xx / yy) stack.append(z if sign == 1 else 2**256 - z) elif code == 'MOD': x, y = stack_pop(2) if y == 0: break stack.append(x % y) elif code == 'SMOD': x, y = stack_pop(2) if y == 0: break sign = (1 if x < 2**255 else -1) * (1 if y < 2**255 else -1) xx = x if x < 2**255 else 2**256 - x yy = y if y < 2**255 else 2**256 - y z = xx % yy stack.append(z if sign == 1 else 2**256 - z) elif code == 'EXP': x, y = stack_pop(2) stack.append(pow(x, y, 2**256)) elif code == 'NEG': stack.append(2**256 - stack.pop(1)[0]) elif code == 'LT': x, y = stack_pop(2) stack.append(1 if x < y else 0) elif code == 'LE': x, y = stack_pop(2) stack.append(1 if x <= y else 0) elif code == 'GT': x, y = stack_pop(2) stack.append(1 if x > y else 0) elif code == 'GE': x, y = stack_pop(2) stack.append(1 if x >= y else 0) elif code == 'EQ': x, y = stack_pop(2) stack.append(1 if x == y else 0) elif code == 'NOT': stack.append(1 if stack.pop(1)[0] == 0 else 0) elif code == 'MYADDRESS': stack.append(address) elif code == 'TXSENDER': stack.append(decode(tx.sender, 256)) elif code == 'TXVALUE': stack.append(tx.value) elif code == 'TXDATAN': stack.append(len(tx.data)) elif code == 'TXDATA': x, = stack_pop(1) stack.append(0 if x >= len(tx.data) else tx.data[x]) elif code == 'BLK_PREVHASH': stack.append(decode(block.prevhash, 256)) elif code == 'BLK_COINBASE': stack.append(decode(block.coinbase, 160)) elif code == 'BLK_TIMESTAMP': stack.append(block.timestamp) elif code == 'BLK_NUMBER': stack.append(block.number) elif code == 'BLK_DIFFICULTY': stack.append(block.difficulty) elif code == 'SHA256': L = stack_pop(1) hdataitems = stack_pop(math.ceil(L / 32.0)) hdata = ''.join([encode(x, 256, 32) for x in hdataitems])[:L] stack.append(decode(hashlib.sha256(hdata).digest(), 256)) elif code == 'RIPEMD-160': L = stack_pop(1) hdataitems = stack_pop(math.ceil(L / 32.0)) hdata = ''.join([encode(x, 256, 32) for x in hdataitems])[:L] stack.append(decode(hashlib.new('ripemd160', hdata).digest(), 256)) elif code == 'ECMUL': n, x, y = stack_pop(3) # Point at infinity if x == 0 and y == 0: stack.extend([0, 0]) # Point not on curve, coerce to infinity elif x >= P or y >= P or (x**3 + 7 - y**2) % P != 0: stack.extend([0, 0]) # Legitimate point else: x2, y2 = base10_multiply((x, y), n) stack.extend([x2, y2]) elif code == 'ECADD': x1, y1, x2, y2 = stack_pop(4) # Invalid point 1 if x1 >= P or y1 >= P or (x1**3 + 7 - y1**2) % P != 0: stack.extend([0, 0]) # Invalid point 2 elif x2 >= P or y2 >= P or (x2**3 + 7 - y2**2) % P != 0: stack.extend([0, 0]) # Legitimate points else: x3, y3 = base10_add((x1, y1), (x2, y2)) stack.extend([x3, y3]) elif code == 'ECSIGN': k, h = stack_pop(2) v, r, s = ecdsa_raw_sign(h, k) stack.extend([v, r, s]) elif code == 'ECRECOVER': h, v, r, s = stack_pop(4) x, y = ecdsa_raw_recover((v, r, s), h) stack.extend([x, y]) elif code == 'SHA3': L = stack_pop(1) hdataitems = stack_pop(math.ceil(L / 32.0)) hdata = ''.join([encode(x, 256, 32) for x in hdataitems])[:L] stack.append(decode(sha3.sha3_256(hdata).digest(), 256)) elif code == 'PUSH': stack.append(contract.get(encode(index + 1, 256, 32))) index += 1 elif code == 'POP': stack_pop(1) elif code == 'DUP': x, = stack_pop(1) stack.extend([x, x]) elif code == 'SWAP': x, y = stack_pop(2) stack.extend([y, x]) elif code == 'SLOAD': stack.append(contract.get(encode(stack_pop(1)[0], 256, 32))) elif code == 'SSTORE': x, y = stack_pop(2) if exit: break contract.update(encode(x, 256, 32), y) elif code == 'JMP': index = stack_pop(1)[0] elif code == 'JMPI': newpos, c = stack_pop(2) if c != 0: index = newpos elif code == 'IND': stack.append(index) elif code == 'EXTRO': ind, addr = stack_pop(2) stack.push( block.get_contract(encode(addr, 256, 20)).get(encode(ind, 256, 32))) elif code == 'BALANCE': stack.push(block.get_balance(encode(stack_pop(1)[0], 256, 20))) elif code == 'MKTX': datan, fee, value, to = stack_pop(4) if exit: break elif (value + fee) > block.get_balance(address): break else: data = stack_pop(datan) tx = Transaction(0, encode(to, 256, 20), value, fee, data) tx.sender = address transaction_list.insert(0, tx) elif code == 'SUICIDE': sz = contract.get_size() negfee = -sz * getfee("memoryfee") toaddress = encode(stack_pop(1)[0], 256, 20) block.pay_fee(toaddress, negfee, False) contract.root = '' break if exit: break block.update_contract(address, contract)
def eval_contract(block,transaction_list,tx): sys.stderr.write("evaluating contract\n") address = tx.to # Initialize registers reg = [0] * 256 reg[0] = decode(tx.sender,256) reg[1] = decode(tx.to,256) reg[2] = tx.value reg[3] = tx.fee index = 0 stepcounter = 0 contract = block.get_contract(address) if not contract: return while 1: # Convert the data item into a code piece val_at_index = decode(contract.get(encode(index,256,32)),256) code = [ int(val_at_index / (256**i)) % 256 for i in range(6) ] code[0] = scriptcode_map.get(code[0],'INVALID') sys.stderr.write("Evaluating: "+ str(code)+"\n") # Invalid code instruction or STOP code stops execution sans fee if val_at_index >= 256**6 or code[0] in ['STOP','INVALID']: sys.stderr.write("stop code, exiting\n") break # Calculate fee minerfee = 0 nullfee = 0 stepcounter += 1 if stepcounter > 16: minerfee += params["stepfee"] c = scriptcode_map[code[0]] if c in ['STORE','LOAD']: minerfee += params["datafee"] if c in ['EXTRO','BALANCE']: minerfee += params["extrofee"] if c in ['SHA256','RIPEMD-160','ECMUL','ECADD','ECSIGN','ECRECOVER']: minerfee += params["cryptofee"] if c == 'STORE': existing = block.get_contract_state(address,code[2]) if reg[code[1]] != 0: nullfee += params["memoryfee"] if existing: nullfee -= params["memoryfee"] # If we can't pay the fee, break, otherwise pay it if block.get_balance(address) < minerfee + nullfee: sys.stderr.write("insufficient fee, exiting\n") break block.set_balance(address,block.get_balance(address) - nullfee - minerfee) block.reward += minerfee sys.stderr.write("evaluating operation\n") # Evaluate operations if c == 'ADD': reg[code[3]] = (reg[code[1]] + reg[code[2]]) % 2**256 elif c == 'MUL': reg[code[3]] = (reg[code[1]] * reg[code[2]]) % 2**256 elif c == 'SUB': reg[code[3]] = (reg[code[1]] + 2**256 - reg[code[2]]) % 2**256 elif c == 'DIV': reg[code[3]] = int(reg[code[1]] / reg[code[2]]) elif c == 'SDIV': sign = 1 sign *= (1 if reg[code[1]] < 2**255 else -1) sign *= (1 if reg[code[2]] < 2**255 else -1) x = reg[code[1]] if reg[code[1]] < 2**255 else 2**256 - reg[code[1]] y = reg[code[2]] if reg[code[2]] < 2**255 else 2**256 - reg[code[2]] z = int(x/y) reg[code[3]] = z if sign == 1 else 2**256 - z elif code == 'MOD': reg[code[3]] = reg[code[1]] % reg[code[2]] elif code == 'SMOD': sign = 1 sign *= (1 if reg[code[1]] < 2**255 else -1) sign *= (1 if reg[code[2]] < 2**255 else -1) x = reg[code[1]] if reg[code[1]] < 2**255 else 2**256 - reg[code[1]] y = reg[code[2]] if reg[code[2]] < 2**255 else 2**256 - reg[code[2]] z = x%y reg[code[3]] = z if sign == 1 else 2**256 - z elif code == 'EXP': reg[code[3]] = pow(reg[code[1]],reg[code[2]],2**256) elif code == 'NEG': reg[code[2]] = 2**256 - reg[code[1]] elif code == 'LT': reg[code[3]] = 1 if reg[code[1]] < reg[code[2]] else 0 elif code == 'LE': reg[code[3]] = 1 if reg[code[1]] <= reg[code[2]] else 0 elif code == 'GT': reg[code[3]] = 1 if reg[code[1]] > reg[code[2]] else 0 elif code == 'GE': reg[code[3]] = 1 if reg[code[1]] >= reg[code[2]] else 0 elif code == 'EQ': reg[code[3]] = 1 if reg[code[1]] == reg[code[2]] else 0 elif code == 'NOT': reg[code[2]] = 1 if reg[code[1]] == 0 else 0 elif code == 'SHA256': inp = encode(reg[code[1]],256,32) reg[code[2]] = decode(hashlib.sha256(inp).digest(),256) elif code == 'RIPEMD-160': inp = encode(reg[code[1]],256,32) reg[code[2]] = decode(hashlib.new('ripemd160',inp).digest(),256) elif code == 'ECMUL': pt = (reg[code[1]],reg[code[2]]) # Point at infinity if pt[0] == 0 and pt[1] == 0: reg[code[4]], reg[code[5]] = 0,0 # Point not on curve, coerce to infinity elif (pt[0] ** 3 + 7 - pt[1] ** 2) % N != 0: reg[code[4]], reg[code[5]] = 0,0 # Legitimate point else: pt2 = base10_multiply(pt,reg[code[3]]) reg[code[4]], reg[code[5]] = pt2[0], pt2[1] elif code == 'ECADD': pt1 = (reg[code[1]],reg[code[2]]) pt2 = (reg[code[3]],reg[code[4]]) # Invalid point 1 if (pt1[0] ** 3 + 7 - pt1[1] ** 2) % N != 0: reg[code[5]], reg[code[6]] = 0,0 # Invalid point 2 elif (pt2[0] ** 3 + 7 - pt2[1] ** 2) % N != 0: reg[code[5]], reg[code[6]] = 0,0 # Legitimate points else: pt3 = base10_add(pt1,pt2) reg[code[5]], reg[code[6]] = pt3[0], pt3[1] elif code == 'ECSIGN': reg[code[3]], reg[code[4]], reg[code[5]] = ecdsa_raw_sign(reg[code[1]],reg[code[2]]) elif code == 'ECRECOVER': pt = ecdsa_raw_recover((reg[code[2]],reg[code[3]],reg[code[4]]),reg[code[1]]) reg[code[5]] = pt[0] reg[code[6]] = pt[1] elif code == 'COPY': reg[code[2]] = reg[code[1]] elif code == 'STORE': contract.update(encode(reg[code[2]],256,32),reg[code[1]]) elif code == 'LOAD': reg[code[2]] = contract.get(encode(reg[code[1]],256,32)) elif code == 'SET': reg[code[1]] = (code[2] + 256 * code[3] + 65536 * code[4] + 16777216 * code[5]) * 2**code[6] % 2**256 elif code == 'JMP': index = reg[code[1]] elif code == 'JMPI': if reg[code[1]]: index = reg[code[2]] elif code == 'IND': reg[code[1]] = index elif code == 'EXTRO': if reg[code[1]] >= 2**160: reg[code[3]] = 0 else: address = encode(reg[code[1]],256,20) field = encode(reg[code[2]]) reg[code[3]] = block.get_contract(address).get(field) elif code == 'BALANCE': if reg[code[1]] >= 2**160: reg[code[2]] = 0 else: address = encode(reg[code[1]],256,20) reg[code[2]] = block.get_balance(address) elif code == 'MKTX': to = encode(reg[code[1]],256,32) value = reg[code[2]] fee = reg[code[3]] if (value + fee) > block.get_balance(address): pass else: datan = reg[code[4]] data = [] for i in range(datan): ind = encode((reg[code[5]] + i) % 2**256,256,32) data.append(contract.get(ind)) tx = Transaction(0,to,value,fee,data) tx.sender = address transaction_list.insert(0,tx) elif code == 'DATA': reg[code[2]] = tx.data[reg[code[1]]] elif code == 'DATAN': reg[code[1]] = len(tx.data) elif code == 'MYADDRESS': reg[code[1]] = address elif code == 'BLKHASH': reg[code[1]] = decode(block.hash()) elif code == 'SUICIDE': sz = contract.get_size() negfee = -sz * params["memoryfee"] toaddress = encode(reg[code[1]],256,20) block.pay_fee(roaddress,negfee,False) contract.root = '' break block.update_contract(address,contract)
def eval_contract(block,transaction_list,tx): sys.stderr.write("evaluating contract\n") address = tx.to # Initialize stack stack = [] index = 0 stepcounter = 0 contract = block.get_contract(address) if not contract: return while 1: # Convert the data item into a code piece val_at_index = decode(contract.get(encode(index,256,32)),256) code = [ int(val_at_index / (256**i)) % 256 for i in range(6) ] code[0] = scriptcode_map.get(code[0],'INVALID') sys.stderr.write("Evaluating: "+ str(code)+"\n") # Invalid code instruction or STOP code stops execution sans fee if val_at_index >= 256 or code[0] in ['STOP','INVALID']: sys.stderr.write("stop code, exiting\n") break # Calculate fee minerfee = 0 nullfee = 0 stepcounter += 1 if stepcounter > 16: minerfee += getfee("stepfee") c = scriptcode_map[code[0]] if c in ['STORE','LOAD']: minerfee += getfee("datafee") if c in ['EXTRO','BALANCE']: minerfee += getfee("extrofee") if c in ['SHA256','RIPEMD-160','ECMUL','ECADD','ECSIGN','ECRECOVER']: minerfee += getfee("cryptofee") if c == 'STORE': existing = block.get_contract_state(address,code[2]) if reg[code[1]] != 0: nullfee += getfee("memoryfee") if existing: nullfee -= getfee("memoryfee") # If we can't pay the fee, break, otherwise pay it if block.get_balance(address) < minerfee + nullfee: sys.stderr.write("insufficient fee, exiting\n") break block.set_balance(address,block.get_balance(address) - nullfee - minerfee) block.reward += minerfee sys.stderr.write("evaluating operation\n") exit = False def stack_pop(n): if len(stack) < n: sys.stderr.write("Stack height insufficient, exiting") exit = True return [0] * n o = stack[-n:] stack = stack[:-n] return o # Evaluate operations if c == 'ADD': x,y = stack_pop(2) stack.append((x + y) % 2**256) elif c == 'MUL': x,y = stack_pop(2) stack.append((x * y) % 2**256) elif c == 'SUB': x,y = stack_pop(2) stack.append((x - y) % 2**256) elif c == 'DIV': x,y = stack_pop(2) if y == 0: break stack.append(int(x / y)) elif c == 'SDIV': x,y = stack_pop(2) if y == 0: break sign = (1 if x < 2**255 else -1) * (1 if y < 2**255 else -1) xx = x if x < 2**255 else 2**256 - x yy = y if y < 2**255 else 2**256 - y z = int(xx/yy) stack.append(z if sign == 1 else 2**256 - z) elif code == 'MOD': x,y = stack_pop(2) if y == 0: break stack.append(x % y) elif code == 'SMOD': x,y = stack_pop(2) if y == 0: break sign = (1 if x < 2**255 else -1) * (1 if y < 2**255 else -1) xx = x if x < 2**255 else 2**256 - x yy = y if y < 2**255 else 2**256 - y z = xx%yy stack.append(z if sign == 1 else 2**256 - z) elif code == 'EXP': x,y = stack_pop(2) stack.append(pow(x,y,2**256)) elif code == 'NEG': stack.append(2**256 - stack.pop(1)[0]) elif code == 'LT': x,y = stack_pop(2) stack.append(1 if x < y else 0) elif code == 'LE': x,y = stack_pop(2) stack.append(1 if x <= y else 0) elif code == 'GT': x,y = stack_pop(2) stack.append(1 if x > y else 0) elif code == 'GE': x,y = stack_pop(2) stack.append(1 if x >= y else 0) elif code == 'EQ': x,y = stack_pop(2) stack.append(1 if x == y else 0) elif code == 'NOT': stack.append(1 if stack.pop(1)[0] == 0 else 0) elif code == 'MYADDRESS': stack.append(address) elif code == 'TXSENDER': stack.append(decode(tx.sender,256)) elif code == 'TXVALUE': stack.append(tx.value) elif code == 'TXDATAN': stack.append(len(tx.data)) elif code == 'TXDATA': x, = stack_pop(1) stack.append(0 if x >= len(tx.data) else tx.data[x]) elif code == 'BLK_PREVHASH': stack.append(decode(block.prevhash,256)) elif code == 'BLK_COINBASE': stack.append(decode(block.coinbase,160)) elif code == 'BLK_TIMESTAMP': stack.append(block.timestamp) elif code == 'BLK_NUMBER': stack.append(block.number) elif code == 'BLK_DIFFICULTY': stack.append(block.difficulty) elif code == 'SHA256': L = stack_pop(1) hdataitems = stack_pop(math.ceil(L / 32.0)) hdata = ''.join([encode(x,256,32) for x in hdataitems])[:L] stack.append(decode(hashlib.sha256(hdata).digest(),256)) elif code == 'RIPEMD-160': L = stack_pop(1) hdataitems = stack_pop(math.ceil(L / 32.0)) hdata = ''.join([encode(x,256,32) for x in hdataitems])[:L] stack.append(decode(hashlib.new('ripemd160',hdata).digest(),256)) elif code == 'ECMUL': n,x,y = stack_pop(3) # Point at infinity if x == 0 and y == 0: stack.extend([0,0]) # Point not on curve, coerce to infinity elif x >= P or y >= P or (x ** 3 + 7 - y ** 2) % P != 0: stack.extend([0,0]) # Legitimate point else: x2,y2 = base10_multiply((x,y),n) stack.extend([x2,y2]) elif code == 'ECADD': x1,y1,x2,y2 = stack_pop(4) # Invalid point 1 if x1 >= P or y1 >= P or (x1 ** 3 + 7 - y1 ** 2) % P != 0: stack.extend([0,0]) # Invalid point 2 elif x2 >= P or y2 >= P or (x2 ** 3 + 7 - y2 ** 2) % P != 0: stack.extend([0,0]) # Legitimate points else: x3,y3 = base10_add((x1,y1),(x2,y2)) stack.extend([x3,y3]) elif code == 'ECSIGN': k,h = stack_pop(2) v,r,s = ecdsa_raw_sign(h,k) stack.extend([v,r,s]) elif code == 'ECRECOVER': h,v,r,s = stack_pop(4) x,y = ecdsa_raw_recover((v,r,s),h) stack.extend([x,y]) elif code == 'SHA3': L = stack_pop(1) hdataitems = stack_pop(math.ceil(L / 32.0)) hdata = ''.join([encode(x,256,32) for x in hdataitems])[:L] stack.append(decode(sha3.sha3_256(hdata).digest(),256)) elif code == 'PUSH': stack.append(contract.get(encode(index + 1,256,32))) index += 1 elif code == 'POP': stack_pop(1) elif code == 'DUP': x, = stack_pop(1) stack.extend([x,x]) elif code == 'SWAP': x,y = stack_pop(2) stack.extend([y,x]) elif code == 'SLOAD': stack.append(contract.get(encode(stack_pop(1)[0],256,32))) elif code == 'SSTORE': x,y = stack_pop(2) if exit: break contract.update(encode(x,256,32),y) elif code == 'JMP': index = stack_pop(1)[0] elif code == 'JMPI': newpos,c = stack_pop(2) if c != 0: index = newpos elif code == 'IND': stack.append(index) elif code == 'EXTRO': ind,addr = stack_pop(2) stack.push(block.get_contract(encode(addr,256,20)).get(encode(ind,256,32))) elif code == 'BALANCE': stack.push(block.get_balance(encode(stack_pop(1)[0],256,20))) elif code == 'MKTX': datan,fee,value,to = stack_pop(4) if exit: break elif (value + fee) > block.get_balance(address): break else: data = stack_pop(datan) tx = Transaction(0,encode(to,256,20),value,fee,data) tx.sender = address transaction_list.insert(0,tx) elif code == 'SUICIDE': sz = contract.get_size() negfee = -sz * getfee("memoryfee") toaddress = encode(stack_pop(1)[0],256,20) block.pay_fee(toaddress,negfee,False) contract.root = '' break if exit: break block.update_contract(address,contract)
def eval_contract(block, transaction_list, tx): sys.stderr.write("evaluating contract\n") address = tx.to # Initialize registers reg = [0] * 256 reg[0] = decode(tx.sender, 256) reg[1] = decode(tx.to, 256) reg[2] = tx.value reg[3] = tx.fee index = 0 stepcounter = 0 contract = block.get_contract(address) if not contract: return while 1: # Convert the data item into a code piece val_at_index = decode(contract.get(encode(index, 256, 32)), 256) code = [int(val_at_index / (256**i)) % 256 for i in range(6)] code[0] = scriptcode_map.get(code[0], 'INVALID') sys.stderr.write("Evaluating: " + str(code) + "\n") # Invalid code instruction or STOP code stops execution sans fee if val_at_index >= 256**6 or code[0] in ['STOP', 'INVALID']: sys.stderr.write("stop code, exiting\n") break # Calculate fee minerfee = 0 nullfee = 0 stepcounter += 1 if stepcounter > 16: minerfee += params["stepfee"] c = scriptcode_map[code[0]] if c in ['STORE', 'LOAD']: minerfee += params["datafee"] if c in ['EXTRO', 'BALANCE']: minerfee += params["extrofee"] if c in [ 'SHA256', 'RIPEMD-160', 'ECMUL', 'ECADD', 'ECSIGN', 'ECRECOVER' ]: minerfee += params["cryptofee"] if c == 'STORE': existing = block.get_contract_state(address, code[2]) if reg[code[1]] != 0: nullfee += params["memoryfee"] if existing: nullfee -= params["memoryfee"] # If we can't pay the fee, break, otherwise pay it if block.get_balance(address) < minerfee + nullfee: sys.stderr.write("insufficient fee, exiting\n") break block.set_balance(address, block.get_balance(address) - nullfee - minerfee) block.reward += minerfee sys.stderr.write("evaluating operation\n") # Evaluate operations if c == 'ADD': reg[code[3]] = (reg[code[1]] + reg[code[2]]) % 2**256 elif c == 'MUL': reg[code[3]] = (reg[code[1]] * reg[code[2]]) % 2**256 elif c == 'SUB': reg[code[3]] = (reg[code[1]] + 2**256 - reg[code[2]]) % 2**256 elif c == 'DIV': reg[code[3]] = int(reg[code[1]] / reg[code[2]]) elif c == 'SDIV': sign = 1 sign *= (1 if reg[code[1]] < 2**255 else -1) sign *= (1 if reg[code[2]] < 2**255 else -1) x = reg[ code[1]] if reg[code[1]] < 2**255 else 2**256 - reg[code[1]] y = reg[ code[2]] if reg[code[2]] < 2**255 else 2**256 - reg[code[2]] z = int(x / y) reg[code[3]] = z if sign == 1 else 2**256 - z elif code == 'MOD': reg[code[3]] = reg[code[1]] % reg[code[2]] elif code == 'SMOD': sign = 1 sign *= (1 if reg[code[1]] < 2**255 else -1) sign *= (1 if reg[code[2]] < 2**255 else -1) x = reg[ code[1]] if reg[code[1]] < 2**255 else 2**256 - reg[code[1]] y = reg[ code[2]] if reg[code[2]] < 2**255 else 2**256 - reg[code[2]] z = x % y reg[code[3]] = z if sign == 1 else 2**256 - z elif code == 'EXP': reg[code[3]] = pow(reg[code[1]], reg[code[2]], 2**256) elif code == 'NEG': reg[code[2]] = 2**256 - reg[code[1]] elif code == 'LT': reg[code[3]] = 1 if reg[code[1]] < reg[code[2]] else 0 elif code == 'LE': reg[code[3]] = 1 if reg[code[1]] <= reg[code[2]] else 0 elif code == 'GT': reg[code[3]] = 1 if reg[code[1]] > reg[code[2]] else 0 elif code == 'GE': reg[code[3]] = 1 if reg[code[1]] >= reg[code[2]] else 0 elif code == 'EQ': reg[code[3]] = 1 if reg[code[1]] == reg[code[2]] else 0 elif code == 'NOT': reg[code[2]] = 1 if reg[code[1]] == 0 else 0 elif code == 'SHA256': inp = encode(reg[code[1]], 256, 32) reg[code[2]] = decode(hashlib.sha256(inp).digest(), 256) elif code == 'RIPEMD-160': inp = encode(reg[code[1]], 256, 32) reg[code[2]] = decode(hashlib.new('ripemd160', inp).digest(), 256) elif code == 'ECMUL': pt = (reg[code[1]], reg[code[2]]) # Point at infinity if pt[0] == 0 and pt[1] == 0: reg[code[4]], reg[code[5]] = 0, 0 # Point not on curve, coerce to infinity elif (pt[0]**3 + 7 - pt[1]**2) % N != 0: reg[code[4]], reg[code[5]] = 0, 0 # Legitimate point else: pt2 = base10_multiply(pt, reg[code[3]]) reg[code[4]], reg[code[5]] = pt2[0], pt2[1] elif code == 'ECADD': pt1 = (reg[code[1]], reg[code[2]]) pt2 = (reg[code[3]], reg[code[4]]) # Invalid point 1 if (pt1[0]**3 + 7 - pt1[1]**2) % N != 0: reg[code[5]], reg[code[6]] = 0, 0 # Invalid point 2 elif (pt2[0]**3 + 7 - pt2[1]**2) % N != 0: reg[code[5]], reg[code[6]] = 0, 0 # Legitimate points else: pt3 = base10_add(pt1, pt2) reg[code[5]], reg[code[6]] = pt3[0], pt3[1] elif code == 'ECSIGN': reg[code[3]], reg[code[4]], reg[code[5]] = ecdsa_raw_sign( reg[code[1]], reg[code[2]]) elif code == 'ECRECOVER': pt = ecdsa_raw_recover((reg[code[2]], reg[code[3]], reg[code[4]]), reg[code[1]]) reg[code[5]] = pt[0] reg[code[6]] = pt[1] elif code == 'COPY': reg[code[2]] = reg[code[1]] elif code == 'STORE': contract.update(encode(reg[code[2]], 256, 32), reg[code[1]]) elif code == 'LOAD': reg[code[2]] = contract.get(encode(reg[code[1]], 256, 32)) elif code == 'SET': reg[code[1]] = (code[2] + 256 * code[3] + 65536 * code[4] + 16777216 * code[5]) * 2**code[6] % 2**256 elif code == 'JMP': index = reg[code[1]] elif code == 'JMPI': if reg[code[1]]: index = reg[code[2]] elif code == 'IND': reg[code[1]] = index elif code == 'EXTRO': if reg[code[1]] >= 2**160: reg[code[3]] = 0 else: address = encode(reg[code[1]], 256, 20) field = encode(reg[code[2]]) reg[code[3]] = block.get_contract(address).get(field) elif code == 'BALANCE': if reg[code[1]] >= 2**160: reg[code[2]] = 0 else: address = encode(reg[code[1]], 256, 20) reg[code[2]] = block.get_balance(address) elif code == 'MKTX': to = encode(reg[code[1]], 256, 32) value = reg[code[2]] fee = reg[code[3]] if (value + fee) > block.get_balance(address): pass else: datan = reg[code[4]] data = [] for i in range(datan): ind = encode((reg[code[5]] + i) % 2**256, 256, 32) data.append(contract.get(ind)) tx = Transaction(0, to, value, fee, data) tx.sender = address transaction_list.insert(0, tx) elif code == 'DATA': reg[code[2]] = tx.data[reg[code[1]]] elif code == 'DATAN': reg[code[1]] = len(tx.data) elif code == 'MYADDRESS': reg[code[1]] = address elif code == 'BLKHASH': reg[code[1]] = decode(block.hash()) elif code == 'SUICIDE': sz = contract.get_size() negfee = -sz * params["memoryfee"] toaddress = encode(reg[code[1]], 256, 20) block.pay_fee(roaddress, negfee, False) contract.root = '' break block.update_contract(address, contract)