def ecrecover(msg, signature, address=None): """ Returns None on failure, returns the recovered address on success. If address is provided: Returns True if the recovered address matches it, otherwise False. """ rawhash = sha3(msg) if len(signature) >= 65: v = safe_ord(signature[64]) + 27 r = big_endian_to_int(signature[0:32]) s = big_endian_to_int(signature[32:64]) else: if address: return False else: return None pk = PublicKey(flags=ALL_FLAGS) pk.public_key = pk.ecdsa_recover( rawhash, pk.ecdsa_recoverable_deserialize( zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32) + zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32), v - 27), raw=True) pub = pk.serialize(compressed=False) recaddr = data_encoder(sha3(pub[1:])[-20:]) if address: if not address.startswith("0x"): recaddr = recaddr[2:] return recaddr == address return recaddr
def test(): t.gas_price = 0 s = t.state() c = s.abi_contract("randao.se") votes = [] ids = [] xor = 0 for i in range(5): r = random.randrange(2 ** 256) xor ^= r votes.append(utils.zpad(utils.encode_int(r), 32)) f = c.getFee() for i in range(5): ids.append(c.submitHash(utils.sha3(votes[i]), value=f)) while c.getPhase() == 0: s.mine(10) for i in range(5): c.submitValue(ids[i], votes[i]) while c.getPhase() == 1: s.mine(10) c.claimResults() assert c.getNextResultPos() == 1 assert c.getResult(0) == utils.zpad(utils.encode_int(xor), 32), ( c.getResult(0), utils.zpad(utils.encode_int(xor), 32), )
def recover_sender(self): if self.v: if self.r >= N or self.s >= P or self.v < 27 or self.v > 28 \ or self.r == 0 or self.s == 0: raise InvalidSignature() rlpdata = rlp.encode(self, self.__class__.exclude(['v', 'r', 's'])) rawhash = sha3(rlpdata) pk = PublicKey(flags=ALL_FLAGS) try: pk.public_key = pk.ecdsa_recover( rawhash, pk.ecdsa_recoverable_deserialize( zpad( "".join( chr(c) for c in int_to_32bytearray(self.r)), 32) + zpad( "".join( chr(c) for c in int_to_32bytearray(self.s)), 32), self.v - 27), raw=True) pub = pk.serialize(compressed=False) except Exception: raise InvalidSignature() if pub[1:] == "\x00" * 32: raise InvalidSignature() pub = encode_pubkey(pub, 'bin') return sha3(pub[1:])[-20:]
def test(): t.gas_price = 0 s = t.state() c = s.abi_contract('randao.se') votes = [] ids = [] xor = 0 for i in range(5): r = random.randrange(2**256) xor ^= r votes.append(utils.zpad(utils.encode_int(r), 32)) f = c.getFee() for i in range(5): ids.append(c.submitHash(utils.sha3(votes[i]), value=f)) while c.getPhase() == 0: s.mine(10) for i in range(5): c.submitValue(ids[i], votes[i]) while c.getPhase() == 1: s.mine(10) c.claimResults() assert c.getNextResultPos() == 1 assert c.getResult(0) == utils.zpad( utils.encode_int(xor), 32), (c.getResult(0), utils.zpad(utils.encode_int(xor), 32))
def test_transaction(filename, testname, testdata): testdata = fixture_to_bytes(testdata) try: rlpdata = decode_hex(testdata["rlp"][2:]) o = {} tx = rlp.decode(rlpdata, transactions.Transaction) blknum = int(testdata["blocknumber"]) if blknum >= config.default_config["HOMESTEAD_FORK_BLKNUM"]: tx.check_low_s() o["sender"] = tx.sender o["transaction"] = { "data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data), "gasLimit": str_to_bytes(str(tx.startgas)), "gasPrice": str_to_bytes(str(tx.gasprice)), "nonce": str_to_bytes(str(tx.nonce)), "r": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)), "s": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)), "v": str_to_bytes(str(tx.v)), "value": str_to_bytes(str(tx.value)), "to": encode_hex(tx.to), } except Exception as e: tx = None sys.stderr.write(str(e)) if 'transaction' not in testdata: # expected to fail assert tx is None else: assert set(o['transaction'].keys()) == set( testdata.get("transaction", dict()).keys()) o.get("transaction", None) == testdata.get("transaction", None) assert encode_hex(o.get("sender", '')) == testdata.get("sender", '')
def test_transaction(filename, testname, testdata): testdata = fixture_to_bytes(testdata) try: rlpdata = decode_hex(testdata["rlp"][2:]) o = {} tx = rlp.decode(rlpdata, transactions.Transaction) blknum = int(testdata["blocknumber"]) if blknum >= config.default_config["HOMESTEAD_FORK_BLKNUM"]: tx.check_low_s() o["sender"] = tx.sender o["transaction"] = { "data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data), "gasLimit": str_to_bytes(str(tx.startgas)), "gasPrice": str_to_bytes(str(tx.gasprice)), "nonce": str_to_bytes(str(tx.nonce)), "r": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)), "s": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)), "v": str_to_bytes(str(tx.v)), "value": str_to_bytes(str(tx.value)), "to": encode_hex(tx.to), } except Exception as e: tx = None sys.stderr.write(str(e)) if 'transaction' not in testdata: # expected to fail assert tx is None else: assert set(o['transaction'].keys()) == set(testdata.get("transaction", dict()).keys()) o.get("transaction", None) == testdata.get("transaction", None) assert encode_hex(o.get("sender", '')) == testdata.get("sender", '')
def test(): t.gas_price = 0 s = t.state() c = s.abi_contract('gamble.se') rseed = os.urandom(32) seed1 = utils.sha3(rseed) c.set_curseed(seed1) s.block.set_balance(c.address, 27000) totbal = sum([s.block.get_balance(x) for x in t.accounts]) # 90 bets succeed (bet with 25% winning probability) for i in range(90): assert c.bet(utils.zpad(str(i), 32), 250, sender=t.keys[i % 10], value=100) >= 0 # 10 bets fail due to not enough collateral for i in range(90, 100): assert c.bet(utils.zpad(str(i), 32), 250, sender=t.keys[i % 10], value=100) == -2 # Add more collateral s.block.delta_balance(c.address, 3000) # 10 bets succeed for i in range(90, 100): assert c.bet(utils.zpad(str(i), 32), 250, sender=t.keys[i % 10], value=100) >= 0 # 10 bets fail due to limit of 100 for i in range(100, 110): assert c.bet(utils.zpad(str(i), 32), 250, sender=t.keys[i % 10], value=100) == -1 mid_totbal = sum([s.block.get_balance(x) for x in t.accounts]) assert c.set_curseed(rseed, os.urandom(32)) # Check that a reasonable number of bets succeeded new_totbal = sum([s.block.get_balance(x) for x in t.accounts]) print 'Profit: ', totbal - new_totbal assert -4000 < (new_totbal - totbal) < 7000 assert 26000 < s.block.get_balance(c.address) < 37000
def _db_decode_type(cls, value_type, data): if value_type in ('string', 'bytes', 'binary'): return int_to_big_endian(data) if value_type == 'address': return zpad(int_to_big_endian(data), 20) return abi.decode_abi([value_type], zpad(int_to_big_endian(data), 32))[0]
def run_test(filename, testname, testdata): testdata = fixture_to_bytes(testdata) try: rlpdata = decode_hex(testdata["rlp"][2:]) print rlpdata.encode('hex') o = {} tx = rlp.decode(rlpdata, transactions.Transaction) o["sender"] = tx.sender o["transaction"] = { "data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data), "gasLimit": str_to_bytes(str(tx.startgas)), "gasPrice": str_to_bytes(str(tx.gasprice)), "nonce": str_to_bytes(str(tx.nonce)), "r": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)), "s": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)), "v": str_to_bytes(str(tx.v)), "value": str_to_bytes(str(tx.value)), "to": encode_hex(tx.to), } except: tx = None if 'transaction' not in testdata: # expected to fail assert tx is None else: assert set(o['transaction'].keys()) == set( testdata.get("transaction", dict()).keys()) o.get("transaction", None) == testdata.get("transaction", None) assert encode_hex(o.get("sender", '')) == testdata.get("sender", '')
def run_test(filename, testname, testdata): testdata = fixture_to_bytes(testdata) try: rlpdata = decode_hex(testdata["rlp"][2:]) print rlpdata.encode("hex") o = {} tx = rlp.decode(rlpdata, transactions.Transaction) o["sender"] = tx.sender o["transaction"] = { "data": b"0x" * (len(tx.data) > 0) + encode_hex(tx.data), "gasLimit": str_to_bytes(str(tx.startgas)), "gasPrice": str_to_bytes(str(tx.gasprice)), "nonce": str_to_bytes(str(tx.nonce)), "r": b"0x" + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)), "s": b"0x" + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)), "v": str_to_bytes(str(tx.v)), "value": str_to_bytes(str(tx.value)), "to": encode_hex(tx.to), } except: tx = None if "transaction" not in testdata: # expected to fail assert tx is None else: assert set(o["transaction"].keys()) == set(testdata.get("transaction", dict()).keys()) o.get("transaction", None) == testdata.get("transaction", None) assert encode_hex(o.get("sender", "")) == testdata.get("sender", "")
def test_get_logs(self): addr = '0x' + zpad('deadbeef', 32).encode('hex') log_id = '0x' + zpad('beefbeef', 32).encode('hex') client = self.client logs = client.get_logs(from_block='latest', to_block='latest', topics=[log_id, addr]) assert logs == []
def sign_block(block, key, randao_parent, vchash, skips): block.header.extra_data = \ randao_parent + \ utils.zpad(utils.encode_int(skips), 32) + \ vchash for val in utils.ecsign(block.header.signing_hash, key): block.header.extra_data += utils.zpad(utils.encode_int(val), 32) return block
def test_encode_bool(): bool_ = ('bool', '', []) uint8 = ('uint', '8', []) assert encode_single(bool_, True) == zpad(b'\x01', 32) assert encode_single(bool_, False) == zpad(b'\x00', 32) assert encode_single(bool_, True) == encode_single(uint8, 1) assert encode_single(bool_, False) == encode_single(uint8, 0)
def sign(self, payload): rawhash = keccak256(payload) v, r, s = ecsign(rawhash, self.key) signature = \ zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32) + \ zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32) + \ bytearray_to_bytestr([v]) return signature
def run(self, sender=None, to=None, code=None, gas=None): sender = normalize_address(sender) if sender else normalize_address(zpad('sender', 20)) to = normalize_address(to) if to else normalize_address(zpad('receiver', 20)) code = scan_bin(code) if code else '' gas = scan_int(gas) if gas else 10000000000000 msg = vm.Message(sender, to, gas=gas) ext = VMExt(self.state, Transaction(0, 0, 21000, b'', 0, b'')) result, gas_remained, data = _apply_msg(ext, msg, code) return bytearray_to_bytestr(data) if result else None
def test_abi_encode_single_int(): assert abi.encode_single(['int', '256', []], -2**255) == (b'\x80'+b'\x00'*31) assert abi.encode_single(['int', '256', []], (b'\x80'+b'\x00'*31)) == (b'\x80'+b'\x00'*31) assert abi.encode_single(['int', '8', []], -128) == zpad(b'\x80', 32) with pytest.raises(abi.ValueOutOfBounds): assert abi.encode_single(['int', '8', []], -129) assert abi.encode_single(['int', '8', []], 127) == zpad(b'\x7f', 32) with pytest.raises(abi.ValueOutOfBounds): assert abi.encode_single(['int', '8', []], 128)
def test(): t.gas_price = 0 s = t.state() c = s.abi_contract('gamble.se') rseed = os.urandom(32) seed1 = utils.sha3(rseed) c.set_curseed(seed1) s.block.set_balance(c.address, 27000) totbal = sum([s.block.get_balance(x) for x in t.accounts]) assert c.get_fee_millis() == 0 # 90 bets succeed (bet with 25% winning probability) for i in range(90): assert c.bet( utils.zpad(str(i), 32), 250, sender=t.keys[i % 10], value=100) >= 0 # 10 bets fail due to not enough collateral for i in range(90, 100): assert c.bet(utils.zpad(str(i), 32), 250, sender=t.keys[i % 10], value=100) == -2 # Add more collateral s.block.delta_balance(c.address, 3000) # 10 bets succeed for i in range(90, 100): assert c.bet( utils.zpad(str(i), 32), 250, sender=t.keys[i % 10], value=100) >= 0 # 10 bets fail due to limit of 100 for i in range(100, 110): assert c.bet(utils.zpad(str(i), 32), 250, sender=t.keys[i % 10], value=100) == -1 mid_totbal = sum([s.block.get_balance(x) for x in t.accounts]) assert c.get_administration_status() == -1 c.unlock_for_administration() assert c.get_administration_status() == 5 s.block.coinbase = '\x35' * 20 s.mine(5, coinbase='\x35' * 20) s.block.set_balance('\x35' * 20, 0) assert c.get_administration_status() == 0 assert c.set_curseed(rseed, os.urandom(32)) assert c.get_administration_status() == -1 # Check that a reasonable number of bets succeeded new_totbal = sum([s.block.get_balance(x) for x in t.accounts]) print 'Profit: ', totbal - new_totbal assert -4000 < (new_totbal - totbal) < 7000 assert 26000 < s.block.get_balance(c.address) < 37000 assert not c.withdraw(20000) c.unlock_for_administration() s.mine(5) assert c.withdraw(20000) assert not c.withdraw(20000)
def personal_sign(private_key, message): if isinstance(private_key, str): private_key = data_decoder(private_key) rawhash = sha3("\x19Ethereum Signed Message:\n{}{}".format(len(message), message)) v, r, s = ecsign(rawhash, private_key) signature = zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32) + \ zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32) + \ bytearray_to_bytestr([v]) return data_encoder(signature)
def sign_payload(private_key, payload): if isinstance(private_key, str): private_key = data_decoder(private_key) rawhash = sha3(payload) v, r, s = ecsign(rawhash, private_key) signature = zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32) + \ zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32) + \ bytearray_to_bytestr([v]) return data_encoder(signature)
def _encode_function(self, signature, param_values): signature = signature.replace(' ', '') prefix = utils.big_endian_to_int(utils.sha3(signature)[:4]) if signature.find('(') == -1: raise RuntimeError('Invalid function signature. Missing "(" and/or ")"...') if signature.find(')') - signature.find('(') == 1: return utils.zpad(utils.encode_int(prefix), 4))) types = signature[signature.find('(') + 1: signature.find(')')].split(',') encoded_params = encode_abi(types, param_values) return utils.zpad(utils.encode_int(prefix), 4) + encoded_params
def mine(block_number, difficulty, mining_hash, start_nonce=0, rounds=1000): assert isinstance(start_nonce, (int, long)) cache = get_cache(block_number) nonce = start_nonce target = utils.zpad(utils.int_to_big_endian(2**256 // (difficulty or 1)), 32) for i in range(1, rounds + 1): bin_nonce = utils.zpad(utils.int_to_big_endian((nonce + i) & TT64M1), 8) o = hashimoto_light(block_number, cache, mining_hash, bin_nonce) if o["result"] <= target: log.debug("nonce found") assert len(bin_nonce) == 8 assert len(o["mix digest"]) == 32 return bin_nonce, o["mix digest"] return None, None
def get_state_variable_from_storage(self, address, params=[]): (position, length, mappings) = (0, 1, []) try: if params[0] == "mapping": if len(params) < 3: raise CriticalError("Invalid number of parameters.") position = int(params[1]) position_formatted = utils.zpad(utils.int_to_big_endian(position), 32) for i in range(2, len(params)): key = bytes(params[i], 'utf8') key_formatted = utils.rzpad(key, 32) mappings.append(int.from_bytes(utils.sha3(key_formatted + position_formatted), byteorder='big')) length = len(mappings) if length == 1: position = mappings[0] else: if len(params) >= 4: raise CriticalError("Invalid number of parameters.") if len(params) >= 1: position = int(params[0]) if len(params) >= 2: length = int(params[1]) if len(params) == 3 and params[2] == "array": position_formatted = utils.zpad(utils.int_to_big_endian(position), 32) position = int.from_bytes(utils.sha3(position_formatted), byteorder='big') except ValueError: raise CriticalError("Invalid storage index. Please provide a numeric value.") outtxt = [] try: if length == 1: outtxt.append("{}: {}".format(position, self.eth.eth_getStorageAt(address, position))) else: if len(mappings) > 0: for i in range(0, len(mappings)): position = mappings[i] outtxt.append("{}: {}".format(hex(position), self.eth.eth_getStorageAt(address, position))) else: for i in range(position, position + length): outtxt.append("{}: {}".format(hex(i), self.eth.eth_getStorageAt(address, i))) except FileNotFoundError as e: raise CriticalError("IPC error: " + str(e)) except ConnectionError as e: raise CriticalError("Could not connect to RPC server. Make sure that your node is running and that RPC parameters are set correctly.") return '\n'.join(outtxt)
def test_abi_encode_single_int(): assert abi.encode_single(['int', '256', []], -2**255) == (b'\x80' + b'\x00' * 31) assert abi.encode_single(['int', '256', []], (b'\x80' + b'\x00' * 31)) == (b'\x80' + b'\x00' * 31) assert abi.encode_single(['int', '8', []], -128) == zpad(b'\x80', 32) with pytest.raises(abi.ValueOutOfBounds): assert abi.encode_single(['int', '8', []], -129) assert abi.encode_single(['int', '8', []], 127) == zpad(b'\x7f', 32) with pytest.raises(abi.ValueOutOfBounds): assert abi.encode_single(['int', '8', []], 128)
def tester_state(deploy_key, private_keys, tester_blockgas_limit): tester_state = tester.state() # special addresses 1 to 5 alloc = { int_to_addr(i): {'wei': 1} for i in range(1, 5) } for privkey in [deploy_key] + private_keys: address = privatekey_to_address(privkey) alloc[address] = { 'balance': DEFAULT_BALANCE, } for account in tester.accounts: alloc[account] = { 'balance': DEFAULT_BALANCE, } db = ethereum.db.EphemDB() env = ethereum.config.Env( db, ethereum.config.default_config, ) genesis_overwrite = { 'nonce': zpad(data_decoder('0x00006d6f7264656e'), 8), 'difficulty': quantity_decoder('0x20000'), 'mixhash': zpad(b'\x00', 32), 'coinbase': address_decoder('0x0000000000000000000000000000000000000000'), 'timestamp': 0, 'extra_data': b'', 'gas_limit': tester_blockgas_limit, 'start_alloc': alloc, } genesis_block = ethereum.blocks.genesis( env, **genesis_overwrite ) # enable DELEGATECALL opcode genesis_block.number = genesis_block.config['HOMESTEAD_FORK_BLKNUM'] + 1 tester_state.db = db tester_state.env = env tester_state.block = genesis_block tester_state.blocks = [genesis_block] return tester_state
def encode_function_call(self, function_name, args): if function_name not in self.function_data: raise ValueError('Unkown function {}'.format(function_name)) description = self.function_data[function_name] function_selector = zpad(encode_int(description['prefix']), 4) arguments = encode_abi(description['encode_types'], args) return function_selector + arguments
def hash_array(arr): o = '' for x in arr: if isinstance(x, (int, long)): x = utils.zpad(utils.encode_int(x), 32) o += x return utils.big_endian_to_int(utils.sha3(o))
def serialize_block(block, full_transactions): if full_transactions: transactions = [ serialize_txn(block, txn, txn_index) for txn_index, txn in enumerate(block.transaction_list) ] else: transactions = [ encode_32bytes(txn.hash) for txn in block.transaction_list ] unpadded_logs_bloom = int_to_big_endian(block.bloom) logs_bloom = zpad(unpadded_logs_bloom, (256 - len(unpadded_logs_bloom))) return { "number": encode_number(block.number), "hash": encode_32bytes(block.hash), "parentHash": encode_32bytes(block.prevhash), "nonce": encode_32bytes(block.nonce), "sha3Uncles": encode_32bytes(block.uncles_hash), # TODO logsBloom / padding "logsBloom": logs_bloom, "transactionsRoot": encode_32bytes(block.tx_list_root), "stateRoot": encode_32bytes(block.state_root), "miner": encode_address(block.coinbase), "difficulty": encode_number(block.difficulty), "totalDifficulty": encode_number(block.chain_difficulty()), "size": encode_number(len(rlp.encode(block))), "extraData": encode_32bytes(block.extra_data), "gasLimit": encode_number(block.gas_limit), "gasUsed": encode_number(block.gas_used), "timestamp": encode_number(block.timestamp), "transactions": transactions, "uncles": block.uncles }
def test_lottery_payer_deposit_owner(self): self.deploy_contract(9) payer = tester.a6 w0 = self.state.block.get_balance(payer) lottery = Lottery({tester.a1: 11 * eth, tester.a2: 39 * eth}) g1 = self.lottery_init(6, lottery) v = 50 * eth deposit = v / 10 assert self.lottery_get_value(lottery) == v assert self.lottery_get_maturity(lottery) == 10 b = self.state.block.get_balance(payer) - w0 assert b == -(v + deposit + g1) self.state.mine(256 + 11) expected_rand = self.state.block.get_parent().hash[-4:] # Owner gets the deposit self.lottery_randomise(8, lottery) r = self.lottery_get_rand(lottery) r = zpad(int_to_big_endian(r), 4) assert r == expected_rand assert b == -(v + deposit + g1) assert self.lottery_get_owner_deposit() == deposit b0 = self.state.block.get_balance(tester.a9) self.lottery_owner_payout() b = self.state.block.get_balance(tester.a9) - b0 assert b == deposit assert self.lottery_get_owner_deposit() == 0
def mine(block_number, difficulty, mining_hash, start_nonce=0, rounds=1000): assert utils.is_numeric(start_nonce) cache = get_cache(block_number) nonce = start_nonce target = utils.zpad( utils.int_to_big_endian(2**256 // (difficulty or 1) - 1), 32) for i in range(1, rounds + 1): bin_nonce = utils.zpad(utils.int_to_big_endian((nonce + i) & TT64M1), 8) o = hashimoto_light(block_number, cache, mining_hash, bin_nonce) if o[b'result'] <= target: log.debug('nonce found: {}'.format(bin_nonce)) assert len(bin_nonce) == 8 assert len(o[b'mix digest']) == 32 return bin_nonce, o[b'mix digest'] return None, None
def commit_state(self): """Commit account caches""" """Write the acount caches on the corresponding tries.""" changes = [] if len(self.journal) == 0: # log_state.trace('delta', changes=[]) return addresses = sorted(list(self.caches['all'].keys())) for addr in addresses: acct = self._get_acct(addr) # storage for field in ('balance', 'nonce', 'code', 'storage'): if addr in self.caches[field]: v = self.caches[field][addr] changes.append([field, addr, v]) setattr(acct, field, v) t = SecureTrie(Trie(self.db, acct.storage)) for k, v in self.caches.get(b'storage:' + addr, {}).items(): enckey = utils.zpad(utils.coerce_to_bytes(k), 32) val = rlp.encode(v) changes.append(['storage', addr, k, v]) if v: t.update(enckey, val) else: t.delete(enckey) acct.storage = t.root_hash self.state.update(addr, rlp.encode(acct)) log_state.trace('delta', changes=changes) self.reset_cache() self.db.put(b'validated:' + self.hash, '1')
def encode_data(data, length=None): """Encode unformatted binary `data`. If `length` is given, the result will be padded like this: ``quantity_encoder(255, 3) == '0x0000ff'``. """ return add_0x(encode_hex(zpad(data, length or 0)))
def load_state(env, alloc): db = env.db state = SecureTrie(Trie(db, BLANK_ROOT)) count = 0 print("Start loading state from snapshot") for addr in alloc: print("[%d] loading account %s" % (count, addr)) account = alloc[addr] acct = Account.blank_account(db, env.config['ACCOUNT_INITIAL_NONCE']) if len(account['storage']) > 0: t = SecureTrie(Trie(db, BLANK_ROOT)) c = 0 for k in account['storage']: v = account['storage'][k] enckey = zpad(decode_hex(k), 32) t.update(enckey, decode_hex(v)) c += 1 if c % 1000 and len(db.db_service.uncommitted) > 50000: print("%d uncommitted. committing..." % len(db.db_service.uncommitted)) db.commit() acct.storage = t.root_hash if account['nonce']: acct.nonce = int(account['nonce']) if account['balance']: acct.balance = int(account['balance']) if account['code']: acct.code = decode_hex(account['code']) state.update(decode_hex(addr), rlp.encode(acct)) count += 1 db.commit() return state
def test_lottery_payer_deposit_sender(self): self.deploy_contract() payer = tester.a6 w0 = self.state.block.get_balance(payer) lottery = Lottery({tester.a1: 11 * eth, tester.a2: 39 * eth}) g1 = self.lottery_init(6, lottery) v = 50 * eth deposit = v / 10 assert self.lottery_get_value(lottery) == v assert self.lottery_get_maturity(lottery) == 10 b = self.state.block.get_balance(payer) - w0 assert b == -(v + deposit + g1) self.state.mine(11) expected_rand = self.state.block.get_parent().hash[-4:] self.state.mine(255) s0 = self.state.block.get_balance(tester.a8) # Sender gets the deposit g2 = self.lottery_randomise(8, lottery, deposit) assert g2 > 0 and g2 <= 32000 r = self.lottery_get_rand(lottery) r = zpad(int_to_big_endian(r), 4) assert r == expected_rand b = self.state.block.get_balance(payer) - w0 assert b == -(v + deposit + g1) s = self.state.block.get_balance(tester.a8) - s0 assert s == deposit - g2
def mine(self, start_nonce=0): cache = get_cache(self._block_number_int) nonce = start_nonce i = 0 difficulty = int(bin_to_hex_b(self._target_bin)[2:], 16) print('Difficulty: ', difficulty) print('Block Number: ', self._block_number_int) cnt = 0 start = time.time() while True: i += 1 cnt += 1 bin_nonce = utils.zpad(utils.int_to_big_endian((nonce + i)), 8) k = sha3.keccak_256() k.update(self._mining_hash_bin) k.update(bin_nonce) hash1 = int(k.hexdigest(), 16) # o = hashimoto_light(self._block_number_int, cache, self._mining_hash_bin, bin_nonce) if hash1 <= difficulty: end = time.time() self._nonce_bin = bin_nonce print('Hashes Done: ', cnt) # for x in self._mining_hash_bin: # print(x) # for x in bin_nonce: # print(x) # print('Nonce: ', bin_nonce, len( bin_nonce)) print('Block Mining Time: ', end - start) return
def listen(self, log, noprint=False): if not len(log.topics) or log.topics[0] not in self.event_data: return types = self.event_data[log.topics[0]]['types'] name = self.event_data[log.topics[0]]['name'] names = self.event_data[log.topics[0]]['names'] indexed = self.event_data[log.topics[0]]['indexed'] indexed_types = [types[i] for i in range(len(types)) if indexed[i]] unindexed_types = [types[i] for i in range(len(types)) if not indexed[i]] # print('listen', log.data.encode('hex'), log.topics) deserialized_args = decode_abi(unindexed_types, log.data) o = {} c1, c2 = 0, 0 for i in range(len(names)): if indexed[i]: topic_bytes = utils.zpad(utils.encode_int(log.topics[c1 + 1]), 32) o[names[i]] = decode_single(process_type(indexed_types[c1]), topic_bytes) c1 += 1 else: o[names[i]] = deserialized_args[c2] c2 += 1 o["_event_type"] = utils.to_string(name) if not noprint: print(o) return o
def sender(self): if not self._sender: # Determine sender if self.v: if self.r >= N or self.s >= N or self.v < 27 or self.v > 28 \ or self.r == 0 or self.s == 0: raise InvalidTransaction("Invalid signature values!") log.debug('recovering sender') rlpdata = rlp.encode(self, UnsignedTransaction) rawhash = utils.sha3(rlpdata) pk = PublicKey(flags=ALL_FLAGS) try: pk.public_key = pk.ecdsa_recover( rawhash, pk.ecdsa_recoverable_deserialize( zpad(utils.bytearray_to_bytestr(int_to_32bytearray(self.r)), 32) + zpad(utils.bytearray_to_bytestr(int_to_32bytearray(self.s)), 32), self.v - 27 ), raw=True ) pub = pk.serialize(compressed=False) except Exception: raise InvalidTransaction("Invalid signature values (x^3+7 is non-residue)") if pub[1:] == b"\x00" * 32: raise InvalidTransaction("Invalid signature (zero privkey cannot sign)") pub = encode_pubkey(pub, 'bin') self._sender = utils.sha3(pub[1:])[-20:] assert self.sender == self._sender else: self._sender = 0 return self._sender
def listen(self, log, noprint=False): if not len(log.topics) or log.topics[0] not in self.event_data: return types = self.event_data[log.topics[0]]['types'] name = self.event_data[log.topics[0]]['name'] names = self.event_data[log.topics[0]]['names'] indexed = self.event_data[log.topics[0]]['indexed'] indexed_types = [types[i] for i in range(len(types)) if indexed[i]] unindexed_types = [ types[i] for i in range(len(types)) if not indexed[i] ] # print('listen', log.data.encode('hex'), log.topics) deserialized_args = decode_abi(unindexed_types, log.data) o = {} c1, c2 = 0, 0 for i in range(len(names)): if indexed[i]: topic_bytes = utils.zpad(utils.encode_int(log.topics[c1 + 1]), 32) o[names[i]] = decode_single(process_type(indexed_types[c1]), topic_bytes) c1 += 1 else: o[names[i]] = deserialized_args[c2] c2 += 1 o["_event_type"] = utils.to_string(name) if not noprint: print(o) return o
def hash_array(arr): o = b'' for x in arr: if isinstance(x, int): x = utils.zpad(utils.encode_int(x), 32) o += x return utils.big_endian_to_int(utils.sha3(o))
def validate_proof(lottery, ticket, proof): start = zpad(int_to_big_endian(ticket.begin), 4) assert len(start) == 4 length = zpad(int_to_big_endian(ticket.length), 4) assert len(length) == 4 h = sha3(ticket.address + start + length) assert h == ticket.node.hash for p in proof: xor = b''.join(chr(ord(a) ^ ord(b)) for a, b in zip(h, p)) h = sha3(xor) assert h == lottery.root.hash h = sha3(lottery.nonce + h) assert h == lottery.hash
def sha3num(*args): o = '' for arg in args: if isinstance(arg, (int, long)): o += utils.zpad(utils.encode_int(arg), 32) else: o += arg return utils.sha3(o)
def getWork(self): print 'Sending work...' h = self.chain.chain.head_candidate return [ encode_hex(h.header.mining_hash), encode_hex(h.header.seed), encode_hex(zpad(int_to_big_endian(2**256 // h.header.difficulty), 32)) ]
def test_batch_transfer_to_zero(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) addr = b'\0' * 20 vv = zpad(int_to_big_endian(1), 12) mix = vv + addr payments = [mix] assert len(mix) == 32 with pytest.raises(TransactionFailed): gntb.transact({'from': owner_addr}).batchTransfer(payments, 123)
def __init__(self, left=None, right=None, value=None): self.parent = None if value: begin = zpad(int_to_big_endian(value.begin), 4) assert len(begin) == 4 length = zpad(int_to_big_endian(value.length), 4) assert len(length) == 4 data = value.address + begin + length assert len(data) == 20 + 4 + 4 self.hash = sha3(data) self.value = value self.value.node = self else: xor = b''.join(chr(ord(a) ^ ord(b)) for a, b in zip(left.hash, right.hash)) self.hash = sha3(xor) self.left = left self.right = right self.left.parent = self self.right.parent = self
def test_block_18315_changes(): pre = {} toadd = [ ['0x0000000000000000000000000000000000000000000000000000000000000000', '0xf9e88bc2b3203e764fe67b4d0f4171b7756117c8'], ['0x0000000000000000000000000000000000000000000000000000000000000001', '0x'], ['0x0000000000000000000000000000000000000000000000000000000000000002', '0x'], ] db = RefcountDB(EphemDB()) db.logging = True NODES = 60 t1 = pruning_trie.Trie(db) t2 = pruning_trie.Trie(db) db.ttl = NODES * 2 c = 0 for k, v in pre.items(): triekey = utils.sha3(utils.zpad(k[2:].decode('hex'), 32)) t1.update(triekey, rlp.encode(v[2:].decode('hex'))) t2.update(triekey, rlp.encode(v[2:].decode('hex'))) db.commit_refcount_changes(c) db.cleanup(c) c += 1 sys.stderr.write('##############################\n') print(utils.encode_hex(t1.root_hash)) print(t1.to_dict()) for k, v in toadd: sys.stderr.write('kv: %s %s\n' % (k, v)) triekey = utils.sha3(utils.zpad(utils.decode_hex(k[2:]), 32)) if v == '0x': t1.delete(triekey) else: t1.update(triekey, rlp.encode(utils.decode_hex(v[2:]))) db.commit_refcount_changes(c) db.cleanup(c) c += 1 t1.clear_all() db.commit_refcount_changes(c) for i in range(db.ttl + 1): db.cleanup(c) c += 1 t3 = pruning_trie.Trie(db) t3.root_hash = t2.root_hash print(t3.to_dict())
def encode_payment(to, value): value = long(value) assert value < 2**96 value = zpad(int_to_big_endian(value), 12) assert type(value) is str assert len(value) == 12 to = normalize_address(to) assert len(to) == 20 mix = value + to assert len(mix) == 32 return mix
def run_test(filename, testname, testdata): testdata = fixture_to_bytes(testdata) try: rlpdata = decode_hex(testdata["rlp"][2:]) o = {} tx = rlp.decode(rlpdata, transactions.Transaction) o["sender"] = tx.sender o["transaction"] = { "data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data), "gasLimit": str_to_bytes(str(tx.startgas)), "gasPrice": str_to_bytes(str(tx.gasprice)), "nonce": str_to_bytes(str(tx.nonce)), "r": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)), "s": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)), "v": str_to_bytes(str(tx.v)), "value": str_to_bytes(str(tx.value)), "to": encode_hex(tx.to), } except Exception, e: tx = None sys.stderr.write(str(e))
def _encode_function(self, signature, param_values): prefix = utils.big_endian_to_int(utils.sha3(signature)[:4]) if signature.find('(') == -1: raise RuntimeError('Invalid function signature. Missing "(" and/or ")"...') if signature.find(')') - signature.find('(') == 1: return utils.encode_int(prefix) types = signature[signature.find('(') + 1: signature.find(')')].split(',') encoded_params = encode_abi(types, param_values) return utils.zpad(utils.encode_int(prefix), 4) + encoded_params
def test_block_18503_changes(): pre = {'0x0c': '0x29d33c02a200937995e632c4597b4dca8e503978'} toadd = [ ['0x', '0x09'], ] db = RefcountDB(EphemDB()) db.logging = True NODES = 60 t1 = pruning_trie.Trie(db) t2 = pruning_trie.Trie(db) db.ttl = NODES * 2 c = 0 for k, v in pre.items(): triekey = utils.sha3(utils.zpad(utils.decode_hex(k[2:]), 32)) t1.update(triekey, rlp.encode(utils.decode_hex(v[2:]))) t2.update(triekey, rlp.encode(utils.decode_hex(v[2:]))) db.commit_refcount_changes(c) db.cleanup(c) c += 1 print(utils.encode_hex(t1.root_hash)) for k, v in toadd: sys.stderr.write('kv: %s %s\n' % (k, v)) triekey = utils.sha3(utils.zpad(utils.decode_hex(k[2:]), 32)) if v == '0x': t1.delete(triekey) else: t1.update(triekey, rlp.encode(utils.decode_hex(v[2:]))) db.commit_refcount_changes(c) db.cleanup(c) c += 1 t1.clear_all() db.commit_refcount_changes(c) for i in range(db.ttl + 1): db.cleanup(c) c += 1 t3 = pruning_trie.Trie(db) t3.root_hash = t2.root_hash print(t3.to_dict())
def update(self, key, value): """ - increases the update counter - retrieves the the old_update_counter for the key - stores the value in leveldb - generates a log: rlp[key, value, old_update_counter] - computes the new state_digest as: H(last_state_digest, H(log)) - adds to the journal: state_digest | log | journal_entry_length - updates index with the postion of the end of above journal_entry """ self.update_counter += 1 old_value, old_counter = self.get_raw(key) # store in leveldb if value: _stored_value = rlp.encode([value, self.update_counter]) self.db.put(key, _stored_value) else: self.db.delete(key) # generate log log = rlp.encode([key, value, old_counter]) # update state self.state_digest = sha3(self.state_digest + sha3(log)) # state_digest | [key, value, old_counter] | journal_entry_length self.journal.write(self.state_digest) self.journal.write(log) journal_entry_length = 32 + len(log) + 2 assert journal_entry_length < b16, journal_entry_length self.journal.write(zpad(int_to_big_endian(journal_entry_length), 2)) # 2 bytes # write index pos = self.journal.tell() assert pos < b32 idx = zpad(int_to_big_endian(pos), 4) # 4 bytes self.journal_index.write(idx)
def encode_payments(payments): args = [] value_sum = 0L for idx, v in payments: addr = tester.accounts[idx] value_sum += v v = long(v) assert v < 2**96 vv = zpad(int_to_big_endian(v), 12) mix = vv + addr assert len(mix) == 32 print encode_hex(mix), "v: ", v, "addr", encode_hex(addr) args.append(mix) return args, value_sum
def make_match(self, buyer, seller): if buyer.epoch < self.current_block + self.SEALED_WINDOW: print(self.name, 'making sealed offer', buyer.id, seller.id) # TODO: check hash for adding sealed offer, ie hash preferences? # TODO: rework this, see reveal hash_arr = [buyer.epoch, buyer.id, seller.id] shasum = utils.sha3(''.join(map(lambda x: utils.zpad(utils.encode_int(x), 32), hash_arr))) # shasum = utils.sha3(hash_arr) # TODO check epoch against SEALED_WINDOW offer_id = self.market.add_sealed_offer(buyer.id, shasum) print(self.name, 'shasum', utils.decode_int(shasum)) # TODO, combine preferences # TODO rework this, can probably just have buyer and seller instead of id's only offer = Offer(offer_id, buyer.epoch, buyer.id, seller.id, shasum, buyer.preferences) self.sealed_offers.append(offer)
def account_to_dict(self, address, with_storage_root=False, with_storage=True): """Serialize an account to a dictionary with human readable entries. :param address: the 20 bytes account address :param with_storage_root: include the account's storage root :param with_storage: include the whole account's storage """ if len(address) == 40: address = decode_hex(address) assert len(address) == 20 if with_storage_root: # if there are uncommited account changes the current storage root # is meaningless assert len(self.journal) == 0 med_dict = {} account = self._get_acct(address) for field in ('balance', 'nonce'): value = self.caches[field].get(address, getattr(account, field)) med_dict[field] = to_string(value) code = self.caches['code'].get(address, account.code) med_dict['code'] = b'0x' + encode_hex(code) storage_trie = SecureTrie(Trie(self.db, account.storage)) if with_storage_root: med_dict['storage_root'] = encode_hex(storage_trie.get_root_hash()) if with_storage: med_dict['storage'] = {} d = storage_trie.to_dict() subcache = self.caches.get(b'storage:' + address, {}) subkeys = [utils.zpad(utils.coerce_to_bytes(kk), 32) for kk in list(subcache.keys())] for k in list(d.keys()) + subkeys: v = d.get(k, None) v2 = subcache.get(utils.big_endian_to_int(k), None) hexkey = b'0x' + encode_hex(utils.zunpad(k)) if v2 is not None: if v2 != 0: med_dict['storage'][hexkey] = \ b'0x' + encode_hex(utils.int_to_big_endian(v2)) elif v is not None: med_dict['storage'][hexkey] = b'0x' + encode_hex(rlp.decode(v)) return med_dict
def _encode_payments(payments): paymap = {} for p in payments: if p.payee in paymap: paymap[p.payee] += p.value else: paymap[p.payee] = p.value args = [] value = 0L for to, v in paymap.iteritems(): value += v assert v < 2**96 v = utils.zpad(utils.int_to_big_endian(v), 12) pair = v + to assert len(pair) == 32 args.append(pair) return args, value
def test_lottery_randomise(self): self.deploy_contract() lottery = Lottery({tester.a1: 50 * eth, tester.a2: 50 * eth}) assert lottery.value == 100 * eth self.lottery_init(3, lottery) assert self.lottery_get_value(lottery) == lottery.value self.state.mine(11) assert self.state.block.number == 11 assert self.state.block.number > self.lottery_get_maturity(lottery) r = self.lottery_get_rand(lottery) assert r == 0 g = self.lottery_randomise(3, lottery) assert g <= 44919 r = self.lottery_get_rand(lottery) r = zpad(int_to_big_endian(r), 4) assert r == self.state.block.get_parent().hash[-4:] assert self.lottery_get_maturity(lottery) == 0 assert self.lottery_get_value(lottery) == lottery.value