def init_chain_and_casper(): genesis = casper_utils.make_casper_genesis(ALLOC, EPOCH_LENGTH, 100, 0.02, 0.002) t = tester.Chain(genesis=genesis) casper = tester.ABIContract(t, casper_utils.casper_abi, t.chain.config['CASPER_ADDRESS']) return t, casper
def generate_prepare_message(self, state): epoch = state.block_number // self.epoch_length # NO_DBL_PREPARE: Don't prepare if we have already if epoch in self.prepares: return None # Create a Casper contract which we can use to get related values casper = tester.ABIContract(tester.State(state), casper_utils.casper_abi, self.chain.casper_address) # Get the ancestry hash and source ancestry hash validator_index = self.get_validator_index(state) _e, _a, _se, _sa, _pce = self.get_recommended_casper_msg_contents(casper, validator_index) # PREPARE_COMMIT_CONSISTENCY if _se < self.prev_commit_epoch and self.prev_commit_epoch < epoch: return None prepare_msg = casper_utils.mk_prepare(validator_index, _e, _a, _se, _sa, self.key) try: # Attempt to submit the prepare, to make sure that it is justified casper.prepare(prepare_msg) except tester.TransactionFailed: log.info('Prepare failed! Validator {} - hash justified {} - validator start {} - valcode addr {}' .format(self.get_validator_index(state), casper.get_consensus_messages__ancestry_hash_justified(epoch, _a), casper.get_validators__dynasty_start(validator_index), utils.encode_hex(self.valcode_addr))) return None # Save the prepare message we generated self.prepares[epoch] = prepare_msg # Save the highest source epoch we have referenced in our prepare's source epoch if epoch > self.prev_prepare_epoch: self.prev_prepare_epoch = epoch log.info('Prepare submitted: validator %d - epoch %d - prev_commit_epoch %d - hash %s' % (self.get_validator_index(state), epoch, self.prev_commit_epoch, utils.encode_hex(self.epoch_blockhash(state, epoch)))) return prepare_msg
def get_validator_index(self, state): t = tester.State(state.ephemeral_clone()) t.state.gas_limit = 9999999999 casper = tester.ABIContract(t, casper_utils.casper_abi, self.chain.casper_address) if self.valcode_addr is None: raise Exception('Valcode address not set') try: return casper.get_validator_indexes(self.coinbase) except tester.TransactionFailed: return None
def generate_commit_message(self, state): epoch = state.block_number // self.epoch_length # PREPARE_COMMIT_CONSISTENCY if self.prev_prepare_epoch < self.prev_commit_epoch and self.prev_commit_epoch < epoch: return None # Create a Casper contract which we can use to get related values casper = tester.ABIContract(tester.State(state), casper_utils.casper_abi, self.chain.casper_address) validator_index = self.get_validator_index(state) _e, _a, _se, _sa, _pce = self.get_recommended_casper_msg_contents(casper, validator_index) # Make the commit message commit_msg = casper_utils.mk_commit(validator_index, _e, _a, _pce, self.key) try: # Attempt to submit the commit, to make sure that it doesn't doesn't violate DBL_PREPARE & it is justified casper.commit(commit_msg) except tester.TransactionFailed: log.info('Commit failed! Validator {} - blockhash {} - valcode addr {}' .format(self.get_validator_index(state), self.epoch_blockhash(state, epoch), utils.encode_hex(self.valcode_addr))) return None # Save the commit as now our last commit epoch log.info('Commit submitted: validator %d - epoch %d - prev_commit_epoch %d - hash %s' % (self.get_validator_index(state), epoch, self.prev_commit_epoch, utils.encode_hex(self.epoch_blockhash(state, epoch)))) self.prev_commit_epoch = epoch return commit_msg
def __init__(self, test_string, epoch_length, withdrawal_delay, base_interest_factor, base_penalty_factor): if test_string == '': raise Exception("Please pass in a valid test string") self.test_string = test_string self.genesis = casper_utils.make_casper_genesis( ALLOC, epoch_length, withdrawal_delay, base_interest_factor, base_penalty_factor) self.t = tester.Chain(genesis=self.genesis) self.casper = tester.ABIContract( self.t, casper_utils.casper_abi, self.t.chain.env.config['CASPER_ADDRESS']) self.saved_blocks = dict() self.validators = dict() # Register token handlers self.handlers = dict() self.handlers['B'] = self.mine_blocks self.handlers['J'] = self.join self.handlers['P'] = self.prepare self.handlers['C'] = self.commit self.handlers['S'] = self.save_block self.handlers['R'] = self.revert_to_block self.handlers['H'] = self.check_head_equals_block self.handlers['X'] = self.slash
def add_block(self, block): # ~~~ Validate ~~~~ # # Validate that the block should be added if not self.should_add_block(block): return False # ~~~ Store ~~~~ # # Store the block self.db.put(block.header.hash, rlp.encode(block)) self.add_child(block) if block.number % self.config['EPOCH_LENGTH'] == 0: self.db.put(b'cp_subtree_score' + block.hash, 0) # Store the state root if block.header.prevhash == self.head_hash: temp_state = self.state.ephemeral_clone() else: temp_state = self.mk_poststate_of_blockhash(block.header.prevhash) apply_block(temp_state, block) self.db.put(b'state:' + block.header.hash, temp_state.trie.root_hash) # ~~~ Finality Gadget Fork Choice ~~~~ # old_head_chekpoint = self.head_checkpoint # Store the new score cp_hash = self.get_prev_checkpoint_hash(block.hash) casper = tester.ABIContract(tester.State(temp_state), casper_utils.casper_abi, self.config['CASPER_ADDRESS']) try: new_score = casper.get_main_hash_committed_frac() log.info('Got new score! {}'.format(new_score)) except tester.TransactionFailed: new_score = 0 if self.get_checkpoint_score( cp_hash) < new_score or self.get_checkpoint_score( cp_hash) == 0: log.info( 'Updating checkpoint score. Block num: {} - New Score: {}'. format(self.get_block(cp_hash).number, new_score)) self.db.put(b'cp_score:' + cp_hash, new_score) # Update our view self.update_subtree_scores_and_child_pointers(cp_hash) cp = self.get_block(cp_hash) # Store the block as its checkpoint child if is is heavier than the current child p_cp = cp while cp is not self.genesis and self.get_checkpoint_score( cp.hash) == 0: cp = self.get_prev_checkpoint_block(cp) log.info( 'Recieved block. Block num: {} - Prev cp num: {} - Prev committed cp num: {} - Head cp num: {} - Prev committed cp score: {} - Current head cp score: {}' .format(block.number, p_cp.number, cp.number, self.head_checkpoint.number, self.get_checkpoint_score(cp.hash), self.get_checkpoint_score(self.checkpoint_head_hash))) log.info('head cp hash: {} - block prev cp hash: {}'.format( utils.encode_hex(cp_hash), utils.encode_hex(self.checkpoint_head_hash))) # Recompute head self.recompute_head_checkpoint(cp) # Set a new head if required log.info('Head cp num: {} - block prev cp num: {}'.format( self.head_checkpoint.number, cp.number)) if self.head_checkpoint == cp: if self.head_checkpoint == old_head_chekpoint: log.info( 'Head checkpoint == old head. CP Head Num: {} - Head diff: {} - Block diff: {}' .format(self.head_checkpoint.number, self.get_pow_difficulty(self.head), self.get_pow_difficulty(block))) if self.get_pow_difficulty( self.head) < self.get_pow_difficulty(block): self.set_head(block) else: log.info('Head checkpoint changed to cp number: {}'.format( self.head_checkpoint.number)) new_head, _ = self.find_heaviest_pow_block( self.head_checkpoint) self.set_head(new_head) else: log.info('Skipping block: Head checkpoint is not equal to cp!') # Are there blocks that we received that were waiting for this block? # If so, process them. if block.header.hash in self.parent_queue: for _blk in self.parent_queue[block.header.hash]: self.add_block(_blk) del self.parent_queue[block.header.hash] return True
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 assert casper.get_current_epoch() == 1 print("Epoch initialized") # Deposit one validator induct_validator(c, casper, t.k1, 200 * 10**18) # Mine two epochs