def test_farm_two_blocks(): """ In this test, we farm two blocks: one empty block, then one block which spends the coinbase transaction from the empty block. """ REWARD = 10000 unspent_db = RAM_DB() chain_view = ChainView.for_genesis_hash(GENESIS_BLOCK, unspent_db) assert chain_view.genesis_hash == GENESIS_BLOCK assert chain_view.tip_hash == HeaderHash(GENESIS_BLOCK) assert chain_view.tip_index == 0 assert chain_view.unspent_db == unspent_db pos_1 = ProofOfSpace(get_pool_public_key(), get_plot_public_key()) puzzle_hash = puzzle_hash_for_index(1) empty_spend_bundle = SpendBundle.aggregate([]) header, header_signature, body = farm_block(GENESIS_BLOCK, Signature.zero(), 1, pos_1, empty_spend_bundle, puzzle_hash, REWARD) run = asyncio.get_event_loop().run_until_complete additions, removals = run( chain_view.accept_new_block(header, unspent_db, REWARD, 0)) assert len(additions) == 2 assert len(removals) == 0 # TODO: check additions assert additions[1].puzzle_hash == body.fees_coin.puzzle_hash assert additions[1].amount == 0 chain_view = run( chain_view.augment_chain_view(header, header_signature, unspent_db, unspent_db, REWARD, 0)) assert chain_view.genesis_hash == GENESIS_BLOCK assert chain_view.tip_hash == HeaderHash(header) assert chain_view.tip_index == 1 assert chain_view.unspent_db == unspent_db conditions = standard_conditions() spend_bundle_2 = spend_coin(coin=additions[0], conditions=conditions, index=1) assert validate_spend_bundle_signature(spend_bundle_2) pos_2 = ProofOfSpace(get_pool_public_key(1), get_plot_public_key()) header_2, header_signature_2, body_2 = farm_block(header, header_signature, 2, pos_2, spend_bundle_2, puzzle_hash, REWARD) print(header_2) print(header_signature_2) removals = removals_for_body(body_2) assert len(removals) == 1 assert removals[0] == list(spend_bundle_2.coin_solutions)[0].coin.name()
async def farm_block(wallet, ledger_api, last_known_header): coinbase_puzzle_hash = wallet.get_new_puzzlehash() fees_puzzle_hash = wallet.get_new_puzzlehash() r = await ledger_api.next_block(coinbase_puzzle_hash=coinbase_puzzle_hash, fees_puzzle_hash=fees_puzzle_hash) header = r['header'] header_hash = HeaderHash(header) tip = await ledger_api.get_tip() await process_blocks( wallet, ledger_api, tip['genesis_hash'] if last_known_header is None else last_known_header, header_hash) return header_hash
async def augment_chain_view(self, header, header_signature, storage, new_unspent_db, reward, timestamp) -> "ChainView": tip_index = self.tip_index + 1 additions, removals = await self.accept_new_block( header, storage, reward, timestamp) await apply_deltas(tip_index, additions, removals, storage, new_unspent_db) chain_view = self.__class__(self.genesis_hash, HeaderHash(header), header_signature, tip_index, new_unspent_db) await chain_view.check_tip_signature(storage) return chain_view
def farm_block(previous_header, previous_signature, block_number, proof_of_space, spend_bundle, coinbase_puzzle_hash, reward): fees_puzzle_hash = puzzle_hash_for_index(3) coinbase_coin, coinbase_signature = create_coinbase_coin_and_signature( block_number, coinbase_puzzle_hash, reward, proof_of_space.pool_public_key) timestamp = int(1e10) + 300 * block_number header, body = farm_new_block(previous_header, previous_signature, block_number, proof_of_space, spend_bundle, coinbase_coin, coinbase_signature, fees_puzzle_hash, timestamp) header_signature = sign_header(header, proof_of_space.plot_public_key) bad_bls_public_key = BLSPublicKey.from_bytes(public_key_bytes_for_index(9)) bad_eor_public_key = EORPrivateKey(std_hash(bytes([5]))).public_key() hkp = header_signature.aggsig_pair(proof_of_space.plot_public_key, HeaderHash(header)) _ = header_signature.validate([hkp]) assert _ hkp = header_signature.aggsig_pair(bad_eor_public_key, HeaderHash(header)) assert not header_signature.validate([hkp]) hkp = body.coinbase_signature.aggsig_pair(proof_of_space.pool_public_key, body.coinbase_coin.name()) assert body.coinbase_signature.validate([hkp]) hkp = body.coinbase_signature.aggsig_pair(bad_bls_public_key, body.coinbase_coin.name()) assert not body.coinbase_signature.validate([hkp]) return header, header_signature, body
async def sync(self): """ Get blocks from ledger sim and make a note of new and spent coins that are "interesting". """ headers = [] tip_dict = await self._ledger_sim.get_tip() genesis_hash = tip_dict["genesis_hash"] header_hash = tip_dict["tip_hash"] header_index = tip_dict["tip_index"] while True: if header_hash == genesis_hash: break if len(self._header_list ) >= header_index and header_hash == HeaderHash( self._header_list[header_index - 1]): break preimage = await self._ledger_sim.hash_preimage(hash=header_hash) header = Header.from_bytes(preimage) headers.append(header) header_hash = header.previous_hash header_index -= 1 await self.rollback_to_block(header_index) new_block_count = len(headers) while headers: header = headers.pop() preimage = await self._ledger_sim.hash_preimage( hash=header.body_hash) body = Body.from_bytes(preimage) additions = [ _ for _ in additions_for_body(body) if _.puzzle_hash in self._interested_puzzled_hashes ] removals = [ _ for _ in removals_for_body(body) if _ in self._interested_puzzled_hashes ] await apply_deltas(header_index, additions, removals, self, self) self._header_list.append(header) header_index += 1 return new_block_count
async def check_header_signature(header_hash: HeaderHash, header_signature: Signature, storage: Storage): # fetch header for header_hash header = await header_hash.obj(storage) if header is None: raise ConsensusError(Err.MISSING_FROM_STORAGE, header_hash) # get proof of space pos = await header.proof_of_space_hash.obj(storage) if pos is None: raise ConsensusError(Err.MISSING_FROM_STORAGE, header.proof_of_space_hash) # verify header signature hkp = header_signature.aggsig_pair(pos.plot_public_key, HeaderHash(header)) if not header_signature.validate([hkp]): raise ConsensusError(Err.BAD_HEADER_SIGNATURE, header_signature)
import datetime import logging from chiasim.atoms import uint64 from chiasim.farming import farm_new_block, get_plot_public_key, sign_header from chiasim.hashable import (HeaderHash, ProgramHash, ProofOfSpace, SpendBundle, Header) from chiasim.pool import (create_coinbase_coin_and_signature, get_pool_public_key) from chiasim.remote.api_decorators import api_request from chiasim.validation import ChainView, validate_spend_bundle_signature from chiasim.hashable.Body import BodyList log = logging.getLogger(__name__) GENESIS_HASH = HeaderHash([0] * 32) class LedgerAPI: def __init__(self, block_tip: HeaderHash, storage): self._chain_view = ChainView.for_genesis_hash(GENESIS_HASH, storage) self._storage = storage self._unspent_db = storage # TODO: fixme, HACK self._spend_bundles = [] self._next_block_lock = asyncio.Lock() self._now = 0 async def do_ping(self, m=None): log.info("ping") return dict(response="got ping message %r at time %s" % (m, datetime.datetime.utcnow()))