def make_head_candidate(chain, txqueue=None, parent=None, timestamp=None, coinbase='\x35' * 20, extra_data='moo ha ha says the laughing cow.', min_gasprice=0): log.info('Creating head candidate') if parent is None: temp_state = State.from_snapshot( chain.state.to_snapshot(root_only=True), chain.env) else: temp_state = chain.mk_poststate_of_blockhash(parent.hash) cs = get_consensus_strategy(chain.env.config) # Initialize a block with the given parent and variables blk = mk_block_from_prevstate(chain, temp_state, timestamp, coinbase, extra_data) # Find and set the uncles blk.uncles = cs.get_uncles(chain, temp_state) blk.header.uncles_hash = sha3(rlp.encode(blk.uncles)) # Call the initialize state transition function cs.initialize(temp_state, blk) # Add transactions add_transactions(temp_state, blk, txqueue, min_gasprice) # Call the finalize state transition function cs.finalize(temp_state, blk) # Set state root, receipt root, etc set_execution_results(temp_state, blk) log.info('Created head candidate successfully') return blk, temp_state
def mk_poststate_of_blockhash(self, blockhash, convert=False): if blockhash not in self.db: raise Exception("Block hash %s not found" % encode_hex(blockhash)) block_rlp = self.db.get(blockhash) if block_rlp == b'GENESIS': return State.from_snapshot( json.loads(self.db.get(b'GENESIS_STATE')), self.env) block = rlp.decode(block_rlp, Block) state = State(env=self.env) state.trie.root_hash = block.header.state_root if convert else self.db.get( b'state:' + blockhash) update_block_env_variables(state, block) state.gas_used = block.header.gas_used state.txindex = len(block.transactions) state.recent_uncles = {} state.prev_headers = [] b = block header_depth = state.config['PREV_HEADER_DEPTH'] for i in range(header_depth + 1): state.prev_headers.append(b.header) if i < 6: state.recent_uncles[state.block_number - i] = [] for u in b.uncles: state.recent_uncles[state.block_number - i].append(u.hash) try: b = rlp.decode(state.db.get(b.header.prevhash), Block) except: break if i < header_depth: if state.db.get(b.header.prevhash) == b'GENESIS': jsondata = json.loads(state.db.get(b'GENESIS_STATE')) for h in jsondata["prev_headers"][:header_depth - i]: state.prev_headers.append(dict_to_prev_header(h)) for blknum, uncles in jsondata["recent_uncles"].items(): if int(blknum) >= state.block_number - int( state.config['MAX_UNCLE_DEPTH']): state.recent_uncles[blknum] = [ parse_as_bin(u) for u in uncles ] else: raise Exception("Dangling prevhash") assert len(state.journal) == 0, state.journal return state
def mk_poststate_of_collation_hash(self, collation_hash): """Return the post-state of the collation """ if collation_hash not in self.db: raise Exception("Collation hash %s not found" % encode_hex(collation_hash)) collation_rlp = self.db.get(collation_hash) if collation_rlp == 'GENESIS': return State.from_snapshot( json.loads(self.db.get('GENESIS_STATE')), self.env) collation = rlp.decode(collation_rlp, Collation) state = State(env=self.env) state.trie.root_hash = collation.header.post_state_root update_collation_env_variables(state, collation) state.gas_used = 0 state.txindex = len(collation.transactions) state.recent_uncles = {} state.prev_headers = [] assert len(state.journal) == 0, state.journal return state
def __init__(self, genesis=None, env=None, coinbase=b'\x00' * 20, new_head_cb=None, reset_genesis=False, localtime=None, **kwargs): self.env = env or Env() # Initialize the state if b'head_hash' in self.db: # new head tag self.state = self.mk_poststate_of_blockhash( self.db.get(b'head_hash')) print('Initializing chain from saved head, #%d (%s)' % (self.state.prev_headers[0].number, encode_hex(self.state.prev_headers[0].hash))) elif genesis is None: raise Exception("Need genesis decl!") elif isinstance(genesis, State): assert env is None self.state = genesis self.env = self.state.env print('Initializing chain from provided state') elif "extraData" in genesis: self.state = state_from_genesis_declaration(genesis, self.env) reset_genesis = True print('Initializing chain from provided genesis declaration') elif "prev_headers" in genesis: self.state = State.from_snapshot(genesis, self.env) reset_genesis = True print('Initializing chain from provided state snapshot, %d (%s)' % (self.state.block_number, encode_hex(self.state.prev_headers[0].hash[:8]))) else: print('Initializing chain from new state based on alloc') self.state = mk_basic_state( genesis, { "number": kwargs.get('number', 0), "gas_limit": kwargs.get('gas_limit', 4712388), "gas_used": kwargs.get('gas_used', 0), "timestamp": kwargs.get('timestamp', 1467446877), "difficulty": kwargs.get('difficulty', 2**25), "hash": kwargs.get('prevhash', '00' * 32), "uncles_hash": kwargs.get('uncles_hash', '0x' + encode_hex(BLANK_UNCLES_HASH)) }, self.env) reset_genesis = True assert self.env.db == self.state.db initialize(self.state) self.new_head_cb = new_head_cb self.head_hash = self.state.prev_headers[0].hash self.checkpoint_head_hash = b'\x00' * 32 self.db.put(b'cp_subtree_score' + b'\x00' * 32, 2 / 3.) self.commit_logs = [] self.casper_address = self.config['CASPER_ADDRESS'] self.db.put(b'GENESIS_NUMBER', to_string(self.state.block_number)) assert self.state.block_number == self.state.prev_headers[0].number if reset_genesis: self.genesis = Block(self.state.prev_headers[0], [], []) initialize_genesis_keys(self.state, self.genesis) else: self.genesis = self.get_block_by_number(0) self.db.put(b'cp_subtree_score' + self.genesis.hash, 2 / 3.) self.min_gasprice = kwargs.get('min_gasprice', 5 * 10**9) self.coinbase = coinbase self.extra_data = 'moo ha ha says the laughing cow.' self.time_queue = [] self.parent_queue = {} self.localtime = time.time() if localtime is None else localtime
def __init__(self, genesis=None, env=None, new_head_cb=None, reset_genesis=False, localtime=None, max_history=1000, **kwargs): self.env = env or Env() # Initialize the state if b'head_hash' in self.db: # new head tag self.state = self.mk_poststate_of_blockhash( self.db.get('head_hash')) self.state.executing_on_head = True print('Initializing chain from saved head, #%d (%s)' % (self.state.prev_headers[0].number, encode_hex(self.state.prev_headers[0].hash))) elif genesis is None: raise Exception("Need genesis decl!") elif isinstance(genesis, State): assert env is None self.state = genesis self.env = self.state.env print('Initializing chain from provided state') reset_genesis = True elif "extraData" in genesis: self.state = state_from_genesis_declaration(genesis, self.env, executing_on_head=True) reset_genesis = True print('Initializing chain from provided genesis declaration') elif "prev_headers" in genesis: self.state = State.from_snapshot(genesis, self.env, executing_on_head=True) reset_genesis = True print('Initializing chain from provided state snapshot, %d (%s)' % (self.state.block_number, encode_hex(self.state.prev_headers[0].hash[:8]))) elif isinstance(genesis, dict): print('Initializing chain from new state based on alloc') self.state = mk_basic_state( genesis, { "number": kwargs.get('number', 0), "gas_limit": kwargs.get('gas_limit', self.env.config['BLOCK_GAS_LIMIT']), "gas_used": kwargs.get('gas_used', 0), "timestamp": kwargs.get('timestamp', 1467446877), "difficulty": kwargs.get('difficulty', 2**25), "hash": kwargs.get('prevhash', '00' * 32), "uncles_hash": kwargs.get('uncles_hash', '0x' + encode_hex(BLANK_UNCLES_HASH)) }, self.env) reset_genesis = True assert self.env.db == self.state.db initialize(self.state) self.new_head_cb = new_head_cb if self.state.block_number == 0: assert self.state.block_number == self.state.prev_headers[0].number else: assert self.state.block_number - 1 == self.state.prev_headers[ 0].number if reset_genesis: if isinstance(self.state.prev_headers[0], FakeHeader): header = self.state.prev_headers[0].to_block_header() else: header = self.state.prev_headers[0] self.genesis = Block(header) self.state.prev_headers[0] = header initialize_genesis_keys(self.state, self.genesis) else: self.genesis = self.get_block_by_number(0) self.head_hash = self.state.prev_headers[0].hash self.time_queue = [] self.parent_queue = {} self.localtime = time.time() if localtime is None else localtime self.max_history = max_history