def consume_length_prefix(rlp, start): """Read a length prefix from an RLP string. :param rlp: the rlp string to read from :param start: the position at which to start reading :returns: a tuple ``(type, length, end)``, where ``type`` is either ``str`` or ``list`` depending on the type of the following payload, ``length`` is the length of the payload in bytes, and ``end`` is the position of the first payload byte in the rlp string """ b0 = safe_ord(rlp[start]) if b0 < 128: # single byte return (str, 1, start) elif b0 < 128 + 56: # short string return (str, b0 - 128, start + 1) elif b0 < 192: # long string ll = b0 - 128 - 56 + 1 l = big_endian_to_int(rlp[start + 1:start + 1 + ll]) return (str, l, start + 1 + ll) elif b0 < 192 + 56: # short list return (list, b0 - 192, start + 1) else: # long list ll = b0 - 192 - 56 + 1 l = big_endian_to_int(rlp[start + 1:start + 1 + ll]) return (list, l, start + 1 + ll)
def mk_test(b, e, m, execgas): encoded = mk_modexp_data(b, e, m) s = c.snapshot() x = c.contract(kode % (len(encoded) + 36, max(intlen(m), 1), max(intlen(m), 1)), language='viper') pre = tester.mk_state_test_prefill(c) try: o = x.foo( encoded, startgas=21000 + intrinsic_gas_of_data(x.translator.encode('foo', [encoded])) + execgas) if big_endian_to_int(o[:intlen(m)]) != (pow(b, e, m) if m else 0): raise Exception( "Mismatch! %d %d %d expected %d computed %d" % (b, e, m, pow(b, e, m), big_endian_to_int(o[:intlen(m)]))) print("Succeeded %d %d %d sg %d" % (b, e, m, execgas)) except tester.TransactionFailed: print('OOG %d %d %d sg %d' % (b, e, m, execgas)) print(c.last_sender) o = tester.mk_state_test_postfill(c, pre) o2 = tester.mk_state_test_postfill(c, pre, filler_mode=True) assert new_statetest_utils.verify_state_test(o) c.revert(s) return o, o2
def init_state(env, pre): # Setup env state = State( env=Env(config=konfig), block_prevhash=decode_hex(remove_0x_head(env['previousHash'])), prev_headers=[ mk_fake_header(i) for i in range( parse_int_or_hex(env['currentNumber']) - 1, max(-1, parse_int_or_hex(env['currentNumber']) - 257), -1) ], block_number=parse_int_or_hex(env['currentNumber']), block_coinbase=decode_hex(remove_0x_head(env['currentCoinbase'])), block_difficulty=parse_int_or_hex(env['currentDifficulty']), gas_limit=parse_int_or_hex(env['currentGasLimit']), timestamp=parse_int_or_hex(env['currentTimestamp'])) # Fill up pre for address, h in list(pre.items()): assert len(address) in (40, 42) address = decode_hex(remove_0x_head(address)) assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage']) state.set_nonce(address, parse_int_or_hex(h['nonce'])) state.set_balance(address, parse_int_or_hex(h['balance'])) state.set_code(address, decode_hex(remove_0x_head(h['code']))) for k, v in h['storage'].items(): state.set_storage_data(address, big_endian_to_int(decode_hex(k[2:])), big_endian_to_int(decode_hex(v[2:]))) state.commit(allow_empties=True) # state.commit() return state
def mk_test(p1, m, execgas, datarestrict=96): encoded = mk_ecmul_data(p1, m)[:datarestrict] + \ b'\x00' * max(datarestrict - 96, 0) pre = tester.mk_state_test_prefill(c) try: o = x1.foo( encoded, startgas=21000 + intrinsic_gas_of_data( x1.translator.encode( 'foo', [encoded])) + execgas) x, y = big_endian_to_int(o[:32]), big_endian_to_int(o[32:]) if py_pairing.normalize(py_pairing.multiply(p1, m)) != ( py_pairing.FQ(x), py_pairing.FQ(y)): raise Exception("Mismatch! %r %r %d, expected %r computed %r" % (p1, m, datarestrict, py_pairing.normalize(py_pairing.multiply(p1, m)), (x, y))) print('Succeeded! %r %d %d %r' % (p1, m, datarestrict, (x, y))) except tester.TransactionFailed: print('OOG %r %d %d %d' % (p1, m, datarestrict, execgas)) o = tester.mk_state_test_postfill(c, pre) o2 = tester.mk_state_test_postfill(c, pre, filler_mode=True) assert new_statetest_utils.verify_state_test(o) return o, o2
def get_tx_position(self, tx): if not isinstance(tx, (str, bytes)): tx = tx.hash if b'txindex:' + tx in self.db: data = rlp.decode(self.db.get(b'txindex:' + tx)) return big_endian_to_int(data[0]), big_endian_to_int(data[1]) else: return None
def from_snapshot(cls, snapshot_data, env, executing_on_head=False): state = State(env=env) if "alloc" in snapshot_data: for addr, data in snapshot_data["alloc"].items(): if len(addr) == 40: addr = decode_hex(addr) assert len(addr) == 20 if 'wei' in data: state.set_balance(addr, parse_as_int(data['wei'])) if 'balance' in data: state.set_balance(addr, parse_as_int(data['balance'])) if 'code' in data: state.set_code(addr, parse_as_bin(data['code'])) if 'nonce' in data: state.set_nonce(addr, parse_as_int(data['nonce'])) if 'storage' in data: for k, v in data['storage'].items(): state.set_storage_data( addr, big_endian_to_int(parse_as_bin(k)), big_endian_to_int(parse_as_bin(v))) elif "state_root" in snapshot_data: state.trie.root_hash = parse_as_bin(snapshot_data["state_root"]) else: raise Exception( "Must specify either alloc or state root parameter") for k, default in STATE_DEFAULTS.items(): default = copy.copy(default) v = snapshot_data[k] if k in snapshot_data else None if is_numeric(default): setattr(state, k, parse_as_int(v) if k in snapshot_data else default) elif is_string(default): setattr(state, k, parse_as_bin(v) if k in snapshot_data else default) elif k == 'prev_headers': if k in snapshot_data: headers = [dict_to_prev_header(h) for h in v] else: headers = default setattr(state, k, headers) elif k == 'recent_uncles': if k in snapshot_data: uncles = {} for height, _uncles in v.items(): uncles[int(height)] = [] for uncle in _uncles: uncles[int(height)].append(parse_as_bin(uncle)) else: uncles = default setattr(state, k, uncles) if executing_on_head: state.executing_on_head = True state.commit() state.changed = {} return state
def get_transaction(self, tx): if not isinstance(tx, (str, bytes)): tx = tx.hash if b'txindex:' + tx in self.db: data = rlp.decode(self.db.get(b'txindex:' + tx)) blk, index = self.get_block_by_number(big_endian_to_int( data[0])), big_endian_to_int(data[1]) tx = blk.transactions[index] return tx, blk, index else: return None
def test_returnten(): c = tester.Chain() open(filename, 'w').write(mul2_code) x = c.contract(returnten_code, language='serpent') o1 = c.tx(tester.k0, x.address, 0) os.remove(filename) assert utils.big_endian_to_int(o1) == 10
def induct_validator(chain, casper, key, value): valcode_addr = chain.tx(key, "", 0, mk_validation_code(utils.privtoaddr(key))) assert utils.big_endian_to_int( chain.tx(key, purity_checker_address, 0, purity_translator.encode('submit', [valcode_addr]))) == 1 casper.deposit(valcode_addr, utils.privtoaddr(key), value=value)
def test_callcode(): c = tester.Chain() open(filename3, 'w').write(add1_code) x = c.contract(callcode_test_code, language='serpent') c.mine(1) o1 = c.tx(tester.k0, x.address, 0) os.remove(filename3) assert utils.big_endian_to_int(o1) == 64
def optimized_decode_single(x, pos): z = safe_ord(x[pos]) if z < 128: return x[pos:pos + 1], 1 elif z < 184: return x[pos + 1:pos + z - 127], z - 127 else: ll = big_endian_to_int(x[pos + 1:pos + z - 182]) return x[pos + z - 182:pos + z - 182 + ll], z - 182 + ll
def test_ecrecover(): c = tester.Chain() x = c.contract(ecrecover_code, language='serpent') priv = utils.sha3('some big long brainwallet password') pub = bitcoin.privtopub(priv) msghash = utils.sha3('the quick brown fox jumps over the lazy dog') V, R, S = utils.ecsign(msghash, priv) assert bitcoin.ecdsa_raw_verify(msghash, (V, R, S), pub) addr = utils.big_endian_to_int( utils.sha3(bitcoin.encode_pubkey(pub, 'bin')[1:])[12:]) assert utils.big_endian_to_int(utils.privtoaddr(priv)) == addr result = x.test_ecrecover(utils.big_endian_to_int(msghash), V, R, S) assert result == addr
def decode_single(typ, data): base, sub, _ = typ if base == 'address': return '0x' + encode_hex(data[12:]) elif base == 'hash': return data[32 - int(sub):] elif base == 'string' or base == 'bytes': if len(sub): return data[:int(sub)] else: l = big_endian_to_int(data[0:32]) return data[32:][:l] elif base == 'uint': return big_endian_to_int(data) % 2**int(sub) elif base == 'int': o = big_endian_to_int(data) % 2 ** int(sub) return (o - 2 ** int(sub)) if o >= 2 ** (int(sub) - 1) else o elif base == 'ufixed': high, low = [int(x) for x in sub.split('x')] return big_endian_to_int(data) * 1.0 // 2 ** low elif base == 'fixed': high, low = [int(x) for x in sub.split('x')] o = big_endian_to_int(data) i = (o - 2 ** (high + low)) if o >= 2 ** (high + low - 1) else o return (i * 1.0 // 2 ** low) elif base == 'decimal': o = big_endian_to_int(data) i = (o - 2 ** 256 if o > 2 ** 255 else o) return i / 10 ** int(sub) elif base == 'bool': return bool(int(encode_hex(data), 16)) else: raise EncodingError("Unhandled type: %r %r" % (base, sub))
def dec(typ, arg): base, sub, arrlist = typ sz = get_size(typ) # Dynamic-sized strings are encoded as <len(str)> + <str> if base in ('string', 'bytes') and not sub: L = big_endian_to_int(arg[:32]) assert len(arg[32:]) == ceil32( L), "Wrong data size for string/bytes object: expected %d actual %d" % (ceil32(L), len(arg[32:])) return arg[32:][:L] # Dynamic-sized arrays elif sz is None: L = big_endian_to_int(arg[:32]) subtyp = base, sub, arrlist[:-1] subsize = get_size(subtyp) # If children are dynamic, use the head/tail mechanism. Fortunately, # here the code is simpler since we do not have to worry about # mixed dynamic and static children, as we do in the top-level multi-arg # case if subsize is None: assert len(arg) >= 32 + 32 * L, "Not enough data for head" start_positions = [big_endian_to_int(arg[32 + 32 * i: 64 + 32 * i]) for i in range(L)] + [len(arg)] outs = [arg[start_positions[i]: start_positions[i + 1]] for i in range(L)] return [dec(subtyp, out) for out in outs] # If children are static, then grab the data slice for each one and # sequentially decode them manually else: return [dec(subtyp, arg[32 + subsize * i: 32 + subsize * (i + 1)]) for i in range(L)] # Static-sized arrays: decode piece-by-piece elif len(arrlist): L = arrlist[-1][0] subtyp = base, sub, arrlist[:-1] subsize = get_size(subtyp) return [dec(subtyp, arg[subsize * i:subsize * (i + 1)]) for i in range(L)] else: return decode_single(typ, arg)
def state_from_genesis_declaration(genesis_data, env, block=None, allow_empties=False, executing_on_head=False): if block: assert isinstance(block, Block) else: block = block_from_genesis_declaration(genesis_data, env) state = State(env=env) for addr, data in genesis_data["alloc"].items(): addr = normalize_address(addr) assert len(addr) == 20 if 'wei' in data: state.set_balance(addr, parse_as_int(data['wei'])) if 'balance' in data: state.set_balance(addr, parse_as_int(data['balance'])) if 'code' in data: state.set_code(addr, parse_as_bin(data['code'])) if 'nonce' in data: state.set_nonce(addr, parse_as_int(data['nonce'])) if 'storage' in data: for k, v in data['storage'].items(): state.set_storage_data(addr, big_endian_to_int(parse_as_bin(k)), big_endian_to_int(parse_as_bin(v))) get_consensus_strategy(state.config).initialize(state, block) if executing_on_head: state.executing_on_head = True state.commit(allow_empties=allow_empties) print('deleting %d' % len(state.deletes)) rdb = RefcountDB(state.db) for delete in state.deletes: rdb.delete(delete) block.header.state_root = state.trie.root_hash state.changed = {} state.prev_headers = [block.header] return state
def proc_modexp(ext, msg): if not ext.post_metropolis_hardfork(): return 1, msg.gas, [] print('modexp proc', msg.gas) baselen = msg.data.extract32(0) explen = msg.data.extract32(32) modlen = msg.data.extract32(64) first_exp_bytes = msg.data.extract32(96 + baselen) >> (8 * max(32 - explen, 0)) bitlength = -1 while first_exp_bytes: bitlength += 1 first_exp_bytes >>= 1 adjusted_explen = max(bitlength, 0) + 8 * max(explen - 32, 0) gas_cost = (mult_complexity(max(modlen, baselen)) * max(adjusted_explen, 1)) // opcodes.GMODEXPQUADDIVISOR print(baselen, explen, modlen, 'expected gas cost', gas_cost) if msg.gas < gas_cost: return 0, 0, [] if baselen == 0: return 1, msg.gas - gas_cost, [0] * modlen if modlen == 0: return 1, msg.gas - gas_cost, [] base = bytearray(baselen) msg.data.extract_copy(base, 0, 96, baselen) exp = bytearray(explen) msg.data.extract_copy(exp, 0, 96 + baselen, explen) mod = bytearray(modlen) msg.data.extract_copy(mod, 0, 96 + baselen + explen, modlen) if utils.big_endian_to_int(mod) == 0: return 1, msg.gas - gas_cost, [0] * modlen o = pow(utils.big_endian_to_int(base), utils.big_endian_to_int(exp), utils.big_endian_to_int(mod)) return 1, msg.gas - \ gas_cost, [ safe_ord(x) for x in utils.zpad( utils.int_to_big_endian(o), modlen)]
def decint(n, signed=False): # pylint: disable=invalid-name,too-many-branches """ Decode an unsigned/signed integer. """ if isinstance(n, str): n = utils.to_string(n) if n is True: return 1 if n is False: return 0 if n is None: return 0 if is_numeric(n): if signed: if not -TT255 <= n <= TT255 - 1: raise EncodingError('Number out of range: %r' % n) else: if not 0 <= n <= TT256 - 1: raise EncodingError('Number out of range: %r' % n) return n if is_string(n): if len(n) > 32: raise EncodingError('String too long: %r' % n) if len(n) == 40: int_bigendian = decode_hex(n) else: int_bigendian = n # pylint: disable=redefined-variable-type result = big_endian_to_int(int_bigendian) if signed: if result >= TT255: result -= TT256 if not -TT255 <= result <= TT255 - 1: raise EncodingError('Number out of range: %r' % n) else: if not 0 <= result <= TT256 - 1: raise EncodingError('Number out of range: %r' % n) return result raise EncodingError('Cannot decode integer: %r' % n)
def preprocess_code(code): o = 0 i = 0 pushcache = {} code = code + b'\x00' * 32 while i < len(code) - 32: codebyte = safe_ord(code[i]) if codebyte == 0x5b: o |= 1 << i if 0x60 <= codebyte <= 0x7f: pushcache[i] = utils.big_endian_to_int( code[i + 1: i + codebyte - 0x5e]) i += codebyte - 0x5e else: i += 1 return o, pushcache
def check_pow(block_number, header_hash, mixhash, nonce, difficulty): """Check if the proof-of-work of the block is valid. :param nonce: if given the proof of work function will be evaluated with this nonce instead of the one already present in the header :returns: `True` or `False` """ log.debug('checking pow', block_number=block_number) if len(mixhash) != 32 or len(header_hash) != 32 or len(nonce) != 8: return False # Grab current cache cache = get_cache(block_number) mining_output = hashimoto_light(block_number, cache, header_hash, nonce) if mining_output[b'mix digest'] != mixhash: return False return utils.big_endian_to_int( mining_output[b'result']) <= 2**256 // (difficulty or 1)
def decode_abi(types, data): # Process types proctypes = [process_type(typ) for typ in types] # Get sizes of everything sizes = [get_size(typ) for typ in proctypes] # Initialize array of outputs outs = [None] * len(types) # Initialize array of start positions start_positions = [None] * len(types) + [len(data)] # If a type is static, grab the data directly, otherwise record # its start position pos = 0 for i, typ in enumerate(types): if sizes[i] is None: start_positions[i] = big_endian_to_int(data[pos:pos + 32]) j = i - 1 while j >= 0 and start_positions[j] is None: start_positions[j] = start_positions[i] j -= 1 pos += 32 else: outs[i] = data[pos:pos + sizes[i]] pos += sizes[i] # We add a start position equal to the length of the entire data # for convenience. j = len(types) - 1 while j >= 0 and start_positions[j] is None: start_positions[j] = start_positions[len(types)] j -= 1 assert pos <= len(data), "Not enough data for head" # Grab the data for tail arguments using the start positions # calculated above for i, typ in enumerate(types): if sizes[i] is None: offset = start_positions[i] next_offset = start_positions[i + 1] outs[i] = data[offset:next_offset] # Recursively decode them all return [dec(proctypes[i], outs[i]) for i in range(len(outs))]
def event_id(name, encode_types): """ Return the event id. Defined as: `keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")` Where `canonical_type_of` is a function that simply returns the canonical type of a given argument, e.g. for uint indexed foo, it would return uint256). Note the lack of spaces. """ event_types = [ _canonical_type(type_) for type_ in encode_types ] event_signature = '{event_name}({canonical_types})'.format( event_name=name, canonical_types=','.join(event_types), ) return big_endian_to_int(utils.sha3(event_signature))
def method_id(name, encode_types): """ Return the unique method id. The signature is defined as the canonical expression of the basic prototype, i.e. the function name with the parenthesised list of parameter types. Parameter types are split by a single comma - no spaces are used. The method id is defined as the first four bytes (left, high-order in big-endian) of the Keccak (SHA-3) hash of the signature of the function. """ function_types = [ _canonical_type(type_) for type_ in encode_types ] function_signature = '{function_name}({canonical_types})'.format( function_name=name, canonical_types=','.join(function_types), ) function_keccak = utils.sha3(function_signature) first_bytes = function_keccak[:4] return big_endian_to_int(first_bytes)
def test_sixten(): c = tester.Chain() addr = decode_hex('1231231231231234564564564564561231231231') c.head_state.set_code(addr, serpent.compile_lll(sixten_code)) o1 = c.tx(tester.k0, addr, 0) assert utils.big_endian_to_int(o1) == 610
def vm_execute(ext, msg, code): # precompute trace flag # if we trace vm, we're in slow mode anyway trace_vm = log_vm_op.is_active('trace') compustate = Compustate(gas=msg.gas) stk = compustate.stack mem = compustate.memory if code in code_cache: processed_code = code_cache[code] else: processed_code = preprocess_code(code) code_cache[code] = processed_code # print(processed_code.keys(), code) codelen = len(code) s = time.time() steps = 0 _prevop = None # for trace only while compustate.pc in processed_code: ops, minstack, maxstack, totgas, nextpos = processed_code[ compustate.pc] if len(compustate.stack) < minstack: return vm_exception('INSUFFICIENT STACK') if len(compustate.stack) > maxstack: return vm_exception('STACK SIZE LIMIT EXCEEDED') if totgas > compustate.gas: return vm_exception('OUT OF GAS %d %d' % (totgas, compustate.gas)) jumped = False compustate.gas -= totgas compustate.pc = nextpos # Invalid operation; can only come at the end of a chunk if ops[-1][0] == 'INVALID': return vm_exception('INVALID OP', opcode=ops[-1][1]) for op, opcode, pushval in ops: if trace_vm: """ This diverges from normal logging, as we use the logging namespace only to decide which features get logged in 'bible.vm.op' i.e. tracing can not be activated by activating a sub like 'bible.vm.op.stack' """ trace_data = {} trace_data['stack'] = list( map(to_string, list(compustate.stack))) if _prevop in ('MLOAD', 'MSTORE', 'MSTORE8', 'SHA3', 'CALL', 'CALLCODE', 'CREATE', 'CALLDATACOPY', 'CODECOPY', 'EXTCODECOPY'): if len(compustate.memory) < 1024: trace_data['memory'] = \ ''.join([encode_hex(ascii_chr(x)) for x in compustate.memory]) else: trace_data['sha3memory'] = \ encode_hex(utils.sha3(b''.join([ascii_chr(x) for x in compustate.memory]))) if _prevop in ('SSTORE', ) or steps == 0: trace_data['storage'] = ext.log_storage(msg.to) trace_data['gas'] = to_string(compustate.gas + totgas) trace_data['inst'] = opcode trace_data['pc'] = to_string(compustate.pc - 1) if steps == 0: trace_data['depth'] = msg.depth trace_data['address'] = msg.to trace_data['steps'] = steps trace_data['depth'] = msg.depth if op[:4] == 'PUSH': trace_data['pushvalue'] = pushval log_vm_op.trace('vm', op=op, **trace_data) steps += 1 _prevop = op # Valid operations # Pushes first because they are very frequent if 0x60 <= opcode <= 0x7f: # compustate.pc += opcode - 0x5f # Move 1 byte forward for # 0x60, up to 32 bytes for 0x7f stk.append(pushval) elif opcode < 0x10: if op == 'STOP': return peaceful_exit('STOP', compustate.gas, []) elif op == 'ADD': stk.append((stk.pop() + stk.pop()) & TT256M1) elif op == 'SUB': stk.append((stk.pop() - stk.pop()) & TT256M1) elif op == 'MUL': stk.append((stk.pop() * stk.pop()) & TT256M1) elif op == 'DIV': s0, s1 = stk.pop(), stk.pop() stk.append(0 if s1 == 0 else s0 // s1) elif op == 'MOD': s0, s1 = stk.pop(), stk.pop() stk.append(0 if s1 == 0 else s0 % s1) elif op == 'SDIV': s0, s1 = utils.to_signed(stk.pop()), utils.to_signed( stk.pop()) stk.append(0 if s1 == 0 else (abs(s0) // abs(s1) * (-1 if s0 * s1 < 0 else 1)) & TT256M1) elif op == 'SMOD': s0, s1 = utils.to_signed(stk.pop()), utils.to_signed( stk.pop()) stk.append(0 if s1 == 0 else (abs(s0) % abs(s1) * (-1 if s0 < 0 else 1)) & TT256M1) elif op == 'ADDMOD': s0, s1, s2 = stk.pop(), stk.pop(), stk.pop() stk.append((s0 + s1) % s2 if s2 else 0) elif op == 'MULMOD': s0, s1, s2 = stk.pop(), stk.pop(), stk.pop() stk.append((s0 * s1) % s2 if s2 else 0) elif op == 'EXP': base, exponent = stk.pop(), stk.pop() # fee for exponent is dependent on its bytes # calc n bytes to represent exponent nbytes = len(utils.encode_int(exponent)) expfee = nbytes * opcodes.GEXPONENTBYTE if ext.post_clearing_hardfork(): expfee += opcodes.EXP_SUPPLEMENTAL_GAS * nbytes if compustate.gas < expfee: compustate.gas = 0 return vm_exception('OOG EXPONENT') compustate.gas -= expfee stk.append(pow(base, exponent, TT256)) elif op == 'SIGNEXTEND': s0, s1 = stk.pop(), stk.pop() if s0 <= 31: testbit = s0 * 8 + 7 if s1 & (1 << testbit): stk.append(s1 | (TT256 - (1 << testbit))) else: stk.append(s1 & ((1 << testbit) - 1)) else: stk.append(s1) elif opcode < 0x20: if op == 'LT': stk.append(1 if stk.pop() < stk.pop() else 0) elif op == 'GT': stk.append(1 if stk.pop() > stk.pop() else 0) elif op == 'SLT': s0, s1 = utils.to_signed(stk.pop()), utils.to_signed( stk.pop()) stk.append(1 if s0 < s1 else 0) elif op == 'SGT': s0, s1 = utils.to_signed(stk.pop()), utils.to_signed( stk.pop()) stk.append(1 if s0 > s1 else 0) elif op == 'EQ': stk.append(1 if stk.pop() == stk.pop() else 0) elif op == 'ISZERO': stk.append(0 if stk.pop() else 1) elif op == 'AND': stk.append(stk.pop() & stk.pop()) elif op == 'OR': stk.append(stk.pop() | stk.pop()) elif op == 'XOR': stk.append(stk.pop() ^ stk.pop()) elif op == 'NOT': stk.append(TT256M1 - stk.pop()) elif op == 'BYTE': s0, s1 = stk.pop(), stk.pop() if s0 >= 32: stk.append(0) else: stk.append((s1 // 256**(31 - s0)) % 256) elif opcode < 0x40: if op == 'SHA3': s0, s1 = stk.pop(), stk.pop() compustate.gas -= opcodes.GSHA3WORD * \ (utils.ceil32(s1) // 32) if compustate.gas < 0: return vm_exception('OOG PAYING FOR SHA3') if not mem_extend(mem, compustate, op, s0, s1): return vm_exception('OOG EXTENDING MEMORY') data = bytearray_to_bytestr(mem[s0:s0 + s1]) stk.append(utils.big_endian_to_int(utils.sha3(data))) elif op == 'ADDRESS': stk.append(utils.coerce_to_int(msg.to)) elif op == 'BALANCE': if ext.post_anti_dos_hardfork(): if not eat_gas(compustate, opcodes.BALANCE_SUPPLEMENTAL_GAS): return vm_exception("OUT OF GAS") addr = utils.coerce_addr_to_hex(stk.pop() % 2**160) stk.append(ext.get_balance(addr)) elif op == 'ORIGIN': stk.append(utils.coerce_to_int(ext.tx_origin)) elif op == 'CALLER': stk.append(utils.coerce_to_int(msg.sender)) elif op == 'CALLVALUE': stk.append(msg.value) elif op == 'CALLDATALOAD': stk.append(msg.data.extract32(stk.pop())) elif op == 'CALLDATASIZE': stk.append(msg.data.size) elif op == 'CALLDATACOPY': mstart, dstart, size = stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, mstart, size): return vm_exception('OOG EXTENDING MEMORY') if not data_copy(compustate, size): return vm_exception('OOG COPY DATA') msg.data.extract_copy(mem, mstart, dstart, size) elif op == 'CODESIZE': stk.append(len(code)) elif op == 'CODECOPY': mstart, dstart, size = stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, mstart, size): return vm_exception('OOG EXTENDING MEMORY') if not data_copy(compustate, size): return vm_exception('OOG COPY DATA') for i in range(size): if dstart + i < len(code): mem[mstart + i] = utils.safe_ord(code[dstart + i]) else: mem[mstart + i] = 0 elif op == 'RETURNDATACOPY': mstart, dstart, size = stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, mstart, size): return vm_exception('OOG EXTENDING MEMORY') if not data_copy(compustate, size): return vm_exception('OOG COPY DATA') if dstart + size > len(compustate.last_returned): return vm_exception('RETURNDATACOPY out of range') mem[mstart:mstart + size] = compustate.last_returned elif op == 'RETURNDATASIZE': stk.append(len(compustate.last_returned)) elif op == 'GASPRICE': stk.append(ext.tx_gasprice) elif op == 'EXTCODESIZE': if ext.post_anti_dos_hardfork(): if not eat_gas(compustate, opcodes.EXTCODELOAD_SUPPLEMENTAL_GAS): return vm_exception("OUT OF GAS") addr = utils.coerce_addr_to_hex(stk.pop() % 2**160) stk.append(len(ext.get_code(addr) or b'')) elif op == 'EXTCODECOPY': if ext.post_anti_dos_hardfork(): if not eat_gas(compustate, opcodes.EXTCODELOAD_SUPPLEMENTAL_GAS): return vm_exception("OUT OF GAS") addr = utils.coerce_addr_to_hex(stk.pop() % 2**160) start, s2, size = stk.pop(), stk.pop(), stk.pop() extcode = ext.get_code(addr) or b'' assert utils.is_string(extcode) if not mem_extend(mem, compustate, op, start, size): return vm_exception('OOG EXTENDING MEMORY') if not data_copy(compustate, size): return vm_exception('OOG COPY DATA') for i in range(size): if s2 + i < len(extcode): mem[start + i] = utils.safe_ord(extcode[s2 + i]) else: mem[start + i] = 0 elif opcode < 0x50: if op == 'BLOCKHASH': if ext.post_metropolis_hardfork() and False: bh_addr = ext.blockhash_store stk.append(ext.get_storage_data(bh_addr, stk.pop())) else: stk.append( utils.big_endian_to_int(ext.block_hash(stk.pop()))) elif op == 'COINBASE': stk.append(utils.big_endian_to_int(ext.block_coinbase)) elif op == 'TIMESTAMP': stk.append(ext.block_timestamp) elif op == 'NUMBER': stk.append(ext.block_number) elif op == 'DIFFICULTY': stk.append(ext.block_difficulty) elif op == 'GASLIMIT': stk.append(ext.block_gas_limit) elif opcode < 0x60: if op == 'POP': stk.pop() elif op == 'MLOAD': s0 = stk.pop() if not mem_extend(mem, compustate, op, s0, 32): return vm_exception('OOG EXTENDING MEMORY') stk.append(utils.bytes_to_int(mem[s0:s0 + 32])) elif op == 'MSTORE': s0, s1 = stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, s0, 32): return vm_exception('OOG EXTENDING MEMORY') mem[s0:s0 + 32] = utils.encode_int32(s1) elif op == 'MSTORE8': s0, s1 = stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, s0, 1): return vm_exception('OOG EXTENDING MEMORY') mem[s0] = s1 % 256 elif op == 'SLOAD': if ext.post_anti_dos_hardfork(): if not eat_gas(compustate, opcodes.SLOAD_SUPPLEMENTAL_GAS): return vm_exception("OUT OF GAS") stk.append(ext.get_storage_data(msg.to, stk.pop())) elif op == 'SSTORE': s0, s1 = stk.pop(), stk.pop() if msg.static: return vm_exception( 'Cannot SSTORE inside a static context') if ext.get_storage_data(msg.to, s0): gascost = opcodes.GSTORAGEMOD if s1 else opcodes.GSTORAGEKILL refund = 0 if s1 else opcodes.GSTORAGEREFUND else: gascost = opcodes.GSTORAGEADD if s1 else opcodes.GSTORAGEMOD refund = 0 if compustate.gas < gascost: return vm_exception('OUT OF GAS') compustate.gas -= gascost # adds neg gascost as a refund if below zero ext.add_refund(refund) ext.set_storage_data(msg.to, s0, s1) elif op == 'JUMP': compustate.pc = stk.pop() opnew = code[ compustate.pc] if compustate.pc < codelen else 0 jumped = True if opnew != JUMPDEST: return vm_exception('BAD JUMPDEST') elif op == 'JUMPI': s0, s1 = stk.pop(), stk.pop() if s1: compustate.pc = s0 opnew = code[ compustate.pc] if compustate.pc < codelen else 0 jumped = True if opnew != JUMPDEST: return vm_exception('BAD JUMPDEST') elif op == 'PC': stk.append(compustate.pc - 1) elif op == 'MSIZE': stk.append(len(mem)) elif op == 'GAS': stk.append(compustate.gas) # AFTER subtracting cost 1 elif op[:3] == 'DUP': # 0x7f - opcode is a negative number, -1 for 0x80 ... -16 for # 0x8f stk.append(stk[0x7f - opcode]) elif op[:4] == 'SWAP': # 0x8e - opcode is a negative number, -2 for 0x90 ... -17 for # 0x9f temp = stk[0x8e - opcode] stk[0x8e - opcode] = stk[-1] stk[-1] = temp elif op[:3] == 'LOG': """ 0xa0 ... 0xa4, 32/64/96/128/160 + len(data) gas a. Opcodes LOG0...LOG4 are added, takes 2-6 stack arguments MEMSTART MEMSZ (TOPIC1) (TOPIC2) (TOPIC3) (TOPIC4) b. Logs are kept track of during tx execution exactly the same way as suicides (except as an ordered list, not a set). Each log is in the form [address, [topic1, ... ], data] where: * address is what the ADDRESS opcode would output * data is mem[MEMSTART: MEMSTART + MEMSZ] * topics are as provided by the opcode c. The ordered list of logs in the transaction are expressed as [log0, log1, ..., logN]. """ depth = int(op[3:]) mstart, msz = stk.pop(), stk.pop() topics = [stk.pop() for x in range(depth)] compustate.gas -= msz * opcodes.GLOGBYTE if msg.static: return vm_exception('Cannot LOG inside a static context') if not mem_extend(mem, compustate, op, mstart, msz): return vm_exception('OOG EXTENDING MEMORY') data = bytearray_to_bytestr(mem[mstart:mstart + msz]) ext.log(msg.to, topics, data) log_log.trace('LOG', to=msg.to, topics=topics, data=list(map(utils.safe_ord, data))) # print('LOG', msg.to, topics, list(map(ord, data))) elif op == 'CREATE': value, mstart, msz = stk.pop(), stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, mstart, msz): return vm_exception('OOG EXTENDING MEMORY') if msg.static: return vm_exception( 'Cannot CREATE inside a static context') if ext.get_balance(msg.to) >= value and msg.depth < MAX_DEPTH: cd = CallData(mem, mstart, msz) ingas = compustate.gas if ext.post_anti_dos_hardfork(): ingas = all_but_1n(ingas, opcodes.CALL_CHILD_LIMIT_DENOM) create_msg = Message(msg.to, b'', value, ingas, cd, msg.depth + 1) o, gas, addr = ext.create(create_msg) if o: stk.append(utils.coerce_to_int(addr)) else: stk.append(0) compustate.gas = compustate.gas - ingas + gas else: stk.append(0) elif op in ('CALL', 'CALLCODE', 'DELEGATECALL', 'STATICCALL'): # Pull arguments from the stack if op in ('CALL', 'CALLCODE'): gas, to, value, meminstart, meminsz, memoutstart, memoutsz = \ stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop() else: gas, to, meminstart, meminsz, memoutstart, memoutsz = \ stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop() value = 0 # Static context prohibition if msg.static and value > 0: return vm_exception( 'Cannot make a non-zero-value call inside a static context' ) # Expand memory if not mem_extend(mem, compustate, op, meminstart, meminsz) or \ not mem_extend(mem, compustate, op, memoutstart, memoutsz): return vm_exception('OOG EXTENDING MEMORY') to = utils.int_to_addr(to) # Extra gas costs based on hard fork-dependent factors extra_gas = (not ext.account_exists(to)) * (op == 'CALL') * (value > 0 or not ext.post_clearing_hardfork()) * opcodes.GCALLNEWACCOUNT + \ (value > 0) * opcodes.GCALLVALUETRANSFER + \ ext.post_anti_dos_hardfork() * opcodes.CALL_SUPPLEMENTAL_GAS # Compute child gas limit if ext.post_anti_dos_hardfork(): if compustate.gas < extra_gas: return vm_exception('OUT OF GAS', needed=extra_gas) gas = min( gas, all_but_1n(compustate.gas - extra_gas, opcodes.CALL_CHILD_LIMIT_DENOM)) else: if compustate.gas < gas + extra_gas: return vm_exception('OUT OF GAS', needed=gas + extra_gas) submsg_gas = gas + opcodes.GSTIPEND * (value > 0) # Verify that there is sufficient balance and depth if ext.get_balance(msg.to) < value or msg.depth >= MAX_DEPTH: compustate.gas -= (gas + extra_gas - submsg_gas) stk.append(0) else: # Subtract gas from parent compustate.gas -= (gas + extra_gas) assert compustate.gas >= 0 cd = CallData(mem, meminstart, meminsz) # Generate the message if op == 'CALL': call_msg = Message(msg.to, to, value, submsg_gas, cd, msg.depth + 1, code_address=to, static=msg.static) elif ext.post_homestead_hardfork( ) and op == 'DELEGATECALL': call_msg = Message(msg.sender, msg.to, msg.value, submsg_gas, cd, msg.depth + 1, code_address=to, transfers_value=False, static=msg.static) elif op == 'DELEGATECALL': return vm_exception('OPCODE INACTIVE') elif op == 'CALLCODE': call_msg = Message(msg.to, msg.to, value, submsg_gas, cd, msg.depth + 1, code_address=to, static=msg.static) elif op == 'STATICCALL': call_msg = Message(msg.to, to, value, submsg_gas, cd, msg.depth + 1, code_address=to, static=True) else: raise Exception("Lolwut") # Get result result, gas, data = ext.msg(call_msg) if result == 0: stk.append(0) else: stk.append(1) # Set output memory for i in range(min(len(data), memoutsz)): mem[memoutstart + i] = data[i] compustate.gas += gas compustate.last_returned = bytearray(data) elif op == 'RETURN': s0, s1 = stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, s0, s1): return vm_exception('OOG EXTENDING MEMORY') return peaceful_exit('RETURN', compustate.gas, mem[s0:s0 + s1]) elif op == 'REVERT': if not ext.post_metropolis_hardfork(): return vm_exception('Opcode not yet enabled') s0, s1 = stk.pop(), stk.pop() if not mem_extend(mem, compustate, op, s0, s1): return vm_exception('OOG EXTENDING MEMORY') return revert(compustate.gas, mem[s0:s0 + s1]) elif op == 'SUICIDE': if msg.static: return vm_exception( 'Cannot SUICIDE inside a static context') to = utils.encode_int(stk.pop()) to = ((b'\x00' * (32 - len(to))) + to)[12:] xfer = ext.get_balance(msg.to) if ext.post_anti_dos_hardfork(): extra_gas = opcodes.SUICIDE_SUPPLEMENTAL_GAS + \ (not ext.account_exists( to)) * (xfer > 0 or not ext.post_clearing_hardfork()) * opcodes.GCALLNEWACCOUNT if not eat_gas(compustate, extra_gas): return vm_exception("OUT OF GAS") ext.set_balance(to, ext.get_balance(to) + xfer) ext.set_balance(msg.to, 0) ext.add_suicide(msg.to) log_msg.debug('SUICIDING', addr=utils.checksum_encode(msg.to), to=utils.checksum_encode(to), xferring=xfer) return 1, compustate.gas, [] # assert utils.is_numeric(compustate.gas) # this is slow! # for a in stk: # assert is_numeric(a), (op, stk) # assert a >= 0 and a < 2**256, (a, op, stk) # if not jumped: # assert compustate.pc == nextpos # compustate.pc = nextpos if compustate.pc >= codelen: return peaceful_exit('CODE OUT OF RANGE', compustate.gas, []) return vm_exception('INVALID JUMP')
def hashimoto_light(s, c, h, n): return \ pyethash.hashimoto_light(s, c, h, utils.big_endian_to_int(n)) else:
def scan_int(v): if v[:2] in ('0x', b'0x'): v = v[2:] if len(v) % 2 != 0: v = '0' + v return big_endian_to_int(decode_hex(v))
def perturb(inp, pos, by): return inp[:pos] + \ encode_int32(big_endian_to_int( inp[pos: pos + 32]) + by) + inp[pos + 32:]
def __hash__(self): return utils.big_endian_to_int(self.hash)
def test_types(): c = tester.Chain() x = c.contract(type_code, language='serpent') assert utils.big_endian_to_int(c.tx(tester.k0, x.address, 0)) == 5
alloc[utils.int_to_addr(i)] = {'balance': 1} alloc[t.a0] = {'balance': 10**22} alloc[t.a1] = {'balance': 10**22} genesis = casper_utils.make_casper_genesis(alloc, 5, 100, 0.02, 0.002) c = t.Chain(genesis=genesis) t.languages['viper'] = compiler.Compiler() t.gas_limit = 9999999 t.STARTGAS = 2000000 c.mine(1) EPOCH_LENGTH = c.chain.config['EPOCH_LENGTH'] ct = abi.ContractTranslator(purity_checker_abi) # Check that the RLP decoding library and the sig hashing library are "pure" assert utils.big_endian_to_int( c.tx(t.k0, purity_checker_address, 0, ct.encode('submit', [viper_rlp_decoder_address]))) == 1 assert utils.big_endian_to_int( c.tx(t.k0, purity_checker_address, 0, ct.encode('submit', [sig_hasher_address]))) == 1 casper = t.ABIContract(c, casper_abi, c.chain.config['CASPER_ADDRESS']) c.mine(1) # Begin the test print("Starting tests") # Initialize the first epoch c.mine(EPOCH_LENGTH - c.head_state.block_number) # casper.initialize_epoch(1) assert casper.get_nextValidatorIndex() == 0