def initialize(state, block=None): config = state.config state.txindex = 0 state.gas_used = 0 state.bloom = 0 state.receipts = [] if block is not None: update_block_env_variables(state, block) # Initalize the next epoch in the Casper contract if state.block_number % state.config['EPOCH_LENGTH'] == 0 and state.block_number != 0: key, account = state.config['NULL_SENDER'], privtoaddr(state.config['NULL_SENDER']) data = casper_utils.casper_translator.encode('initialize_epoch', [state.block_number // state.config['EPOCH_LENGTH']]) transaction = transactions.Transaction(state.get_nonce(account), 0, 3141592, state.config['CASPER_ADDRESS'], 0, data).sign(key) success, output = apply_transaction(state, transaction) assert success if state.is_DAO(at_fork_height=True): for acct in state.config['CHILD_DAO_LIST']: state.transfer_value( acct, state.config['DAO_WITHDRAWER'], state.get_balance(acct)) if state.is_METROPOLIS(at_fork_height=True): state.set_code(utils.normalize_address( config["METROPOLIS_STATEROOT_STORE"]), config["METROPOLIS_GETTER_CODE"]) state.set_code(utils.normalize_address( config["METROPOLIS_BLOCKHASH_STORE"]), config["METROPOLIS_GETTER_CODE"])
def del_account(self, address): self.set_balance(address, 0) self.set_nonce(address, 0) self.set_code(address, b'') self.reset_storage(address) self.set_and_journal( self.get_and_cache_account(utils.normalize_address(address)), 'deleted', True) self.set_and_journal( self.get_and_cache_account(utils.normalize_address(address)), 'touched', False)
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 make_casper_genesis(validators, alloc, timestamp=0, epoch_length=100): state = mk_basic_state(alloc, None, env=Env(config=casper_config)) state.gas_limit = 10**8 * (len(validators) + 1) state.timestamp = timestamp state.block_difficulty = 1 header = state.prev_headers[0] header.timestamp = timestamp header.difficulty = 1 ct = get_casper_ct() initialize(state) casper_contract_bootstrap(state, timestamp=header.timestamp, gas_limit=header.gas_limit) # Add validators for i, (vcode, deposit_size, randao_commitment, address) in enumerate(validators): validator_inject(state, vcode, deposit_size, randao_commitment, address, i, ct) # Start the first epoch casper_start_epoch(state) assert call_casper(state, 'getEpoch', []) == 0 assert call_casper(state, 'getTotalDeposits', []) == sum([d for a, d, r, a in validators]) state.set_storage_data( utils.normalize_address(state.config['METROPOLIS_BLOCKHASH_STORE']), state.block_number % state.config['METROPOLIS_WRAPAROUND'], header.hash) state.commit() return state
def generate_validation_code(addr): import serpent code = """ # First 32 bytes of input = hash, remaining 96 = signature mustbe = %s a = ecrecover(~calldataload(0), ~calldataload(32), ~calldataload(64), ~calldataload(96)) if a != mustbe: ~invalid() return(1) """ % ('0x' + utils.normalize_address(addr).encode('hex')) return get_contract_code(serpent.compile(code))
def account_exists(self, address): if self.is_SPURIOUS_DRAGON(): o = not self.get_and_cache_account( utils.normalize_address(address)).is_blank() else: a = self.get_and_cache_account(address) if a.deleted and not a.touched: return False if a.touched: return True else: return a.existent_at_start return o
def call(self, sender=k0, to=b'\x00' * 20, value=0, data=b'', startgas=STARTGAS, gasprice=GASPRICE): self.head_state.commit() to = normalize_address(to) sender_addr = privtoaddr(sender) result = apply_message(self.head_state.ephemeral_clone(), sender=sender_addr, to=to, code_address=to, value=value, data=data, gas=startgas) if result is None: raise TransactionFailed() return result
def __init__(self, nonce, gasprice, startgas, to, value, data, v=0, r=0, s=0): self.data = None to = utils.normalize_address(to, allow_blank=True) super(Transaction, self).__init__(nonce, gasprice, startgas, to, value, data, v, r, s) if self.gasprice >= TT256 or self.startgas >= TT256 or \ self.value >= TT256 or self.nonce >= TT256: raise InvalidTransaction("Values way too high!")
def mk_basic_state(alloc, header=None, env=None, executing_on_head=False): env = env or Env() state = State(env=env, executing_on_head=executing_on_head) if not header: header = { "number": 0, "gas_limit": env.config['BLOCK_GAS_LIMIT'], "gas_used": 0, "timestamp": 1467446877, "difficulty": 1, "uncles_hash": '0x' + encode_hex(BLANK_UNCLES_HASH) } h = BlockHeader(number=parse_as_int(header['number']), timestamp=parse_as_int(header['timestamp']), difficulty=parse_as_int(header['difficulty']), gas_limit=parse_as_int(header['gas_limit']), uncles_hash=parse_as_bin(header['uncles_hash'])) state.prev_headers = [h] for addr, data in 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, parse_as_bin(k), parse_as_bin(v)) state.block_number = header["number"] state.gas_limit = header["gas_limit"] state.timestamp = header["timestamp"] state.block_difficulty = header["difficulty"] state.commit() return state
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 account_to_dict(self, address): return self.get_and_cache_account( utils.normalize_address(address)).to_dict()
def set_code(self, address, value): # assert is_string(value) acct = self.get_and_cache_account(utils.normalize_address(address)) self.set_and_journal(acct, 'code', value) self.set_and_journal(acct, 'touched', True)
def delta_balance(self, address, value): address = utils.normalize_address(address) acct = self.get_and_cache_account(address) newbal = acct.balance + value self.set_and_journal(acct, 'balance', newbal) self.set_and_journal(acct, 'touched', True)
def set_nonce(self, address, value): acct = self.get_and_cache_account(utils.normalize_address(address)) self.set_and_journal(acct, 'nonce', value) self.set_and_journal(acct, 'touched', True)
METROPOLIS_FORK_BLKNUM=4370000, METROPOLIS_ENTRY_POINT=2**160 - 1, METROPOLIS_STATEROOT_STORE=0x10, METROPOLIS_BLOCKHASH_STORE=0x20, METROPOLIS_WRAPAROUND=65536, METROPOLIS_GETTER_CODE=decode_hex('6000355460205260206020f3'), METROPOLIS_DIFF_ADJUSTMENT_CUTOFF=9, # Constantinople fork CONSTANTINOPLE_FORK_BLKNUM=2**100, # DAO fork DAO_FORK_BLKNUM=1920000, DAO_FORK_BLKHASH=decode_hex( '4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb'), DAO_FORK_BLKEXTRA=decode_hex('64616f2d686172642d666f726b'), CHILD_DAO_LIST=list(map(utils.normalize_address, child_dao_list)), DAO_WITHDRAWER=utils.normalize_address( '0xbf4ed7b27f1d666546e30d74d50d173d20bca754'), # Anti-DoS fork ANTI_DOS_FORK_BLKNUM=2463000, SPURIOUS_DRAGON_FORK_BLKNUM=2675000, CONTRACT_CODE_SIZE_LIMIT=0x6000, # Default consensus strategy: ethash, poa, casper, pbft CONSENSUS_STRATEGY='ethash', # Serenity fork SERENITY_FORK_BLKNUM=2**99, PREV_HEADER_DEPTH=256, SYSTEM_ENTRY_POINT=utils.int_to_addr(2**160 - 2), SERENITY_HEADER_VERIFIER=utils.int_to_addr(255), SERENITY_HEADER_POST_FINALIZER=utils.int_to_addr(254), SERENITY_GETTER_CODE=decode_hex( '60ff331436604014161560155760203560003555005b6000355460205260206020f3' ),
def increment_nonce(self, address): address = utils.normalize_address(address) acct = self.get_and_cache_account(address) newnonce = acct.nonce + 1 self.set_and_journal(acct, 'nonce', newnonce) self.set_and_journal(acct, 'touched', True)
def get_nonce(self, address): return self.get_and_cache_account( utils.normalize_address(address)).nonce
def get_storage_data(self, address, key): return self.get_and_cache_account( utils.normalize_address(address)).get_storage_data(key)
def set_storage_data(self, address, key, value): acct = self.get_and_cache_account(utils.normalize_address(address)) preval = acct.get_storage_data(key) acct.set_storage_data(key, value) self.journal.append(lambda: acct.set_storage_data(key, preval)) self.set_and_journal(acct, 'touched', True)