Exemplo n.º 1
0
def create_multiple_ref_generator(args: MultipleCompressorArg,
                                  spend_bundle: SpendBundle) -> BlockGenerator:
    """
    Decompress a transaction by referencing bytes from multiple input generator references
    """
    compressed_cse_list = compressed_coin_solution_entry_list(spend_bundle)
    program = TEST_MULTIPLE.curry(
        DECOMPRESS_PUZZLE,
        DECOMPRESS_CSE_WITH_PREFIX,
        args.arg[0].start,
        args.arg[0].end - args.split_offset,
        args.arg[1].end - args.split_offset,
        args.arg[1].end,
        compressed_cse_list,
    )

    # TODO aqk: Improve ergonomics of CompressorArg -> GeneratorArg conversion
    generator_args = [
        GeneratorArg(FAKE_BLOCK_HEIGHT1, args.arg[0].generator),
        GeneratorArg(FAKE_BLOCK_HEIGHT2, args.arg[1].generator),
    ]
    return BlockGenerator(program, generator_args)
Exemplo n.º 2
0
def create_block_generator(
    generator: SerializedProgram, block_heights_list: List[uint32],
    generator_block_cache: GeneratorBlockCacheInterface
) -> Optional[BlockGenerator]:
    """`create_block_generator` will returns None if it fails to look up any referenced block"""
    generator_arg_list: List[GeneratorArg] = []
    for i in block_heights_list:
        previous_generator = generator_block_cache.get_generator_for_block_height(
            i)
        if previous_generator is None:
            log.error(
                f"Failed to look up generator for block {i}. Ref List: {block_heights_list}"
            )
            return None
        generator_arg_list.append(GeneratorArg(i, previous_generator))
    return BlockGenerator(generator, generator_arg_list)
Exemplo n.º 3
0
def create_compressed_generator(
    original_generator: CompressorArg,
    compressed_cse_list: List[List[Union[List[uint64], List[Union[bytes, None,
                                                                  Program]]]]],
) -> BlockGenerator:
    """
    Bind the generator block program template to a particular reference block,
    template bytes offsets, and SpendBundle.
    """
    start = original_generator.start
    end = original_generator.end
    program = DECOMPRESS_BLOCK.curry(DECOMPRESS_PUZZLE,
                                     DECOMPRESS_CSE_WITH_PREFIX,
                                     Program.to(start), Program.to(end),
                                     compressed_cse_list)
    generator_arg = GeneratorArg(original_generator.block_height,
                                 original_generator.generator)
    return BlockGenerator(program, [generator_arg])
Exemplo n.º 4
0
def block_generator() -> BlockGenerator:
    generator_args = [
        GeneratorArg(uint32(0), to_sp(FIRST_GENERATOR)),
        GeneratorArg(uint32(1), to_sp(SECOND_GENERATOR))
    ]
    return BlockGenerator(to_sp(COMPILED_GENERATOR_CODE), generator_args)
Exemplo n.º 5
0
    async def get_block_generator(
        self, block: Union[FullBlock, UnfinishedBlock], additional_blocks=None
    ) -> Optional[BlockGenerator]:
        if additional_blocks is None:
            additional_blocks = {}
        ref_list = block.transactions_generator_ref_list
        if block.transactions_generator is None:
            assert len(ref_list) == 0
            return None
        if len(ref_list) == 0:
            return BlockGenerator(block.transactions_generator, [])

        result: List[GeneratorArg] = []
        previous_block_hash = block.prev_header_hash
        if (
            self.try_block_record(previous_block_hash)
            and self.height_to_hash(self.block_record(previous_block_hash).height) == previous_block_hash
        ):
            # We are not in a reorg, no need to look up alternate header hashes (we can get them from height_to_hash)
            for ref_height in block.transactions_generator_ref_list:
                header_hash = self.height_to_hash(ref_height)
                ref_block = await self.get_full_block(header_hash)
                assert ref_block is not None
                if ref_block.transactions_generator is None:
                    raise ValueError(Err.GENERATOR_REF_HAS_NO_GENERATOR)
                result.append(GeneratorArg(ref_block.height, ref_block.transactions_generator))
        else:
            # First tries to find the blocks in additional_blocks
            reorg_chain: Dict[uint32, FullBlock] = {}
            curr: Union[FullBlock, UnfinishedBlock] = block
            additional_height_dict = {}
            while curr.prev_header_hash in additional_blocks:
                prev: FullBlock = additional_blocks[curr.prev_header_hash]
                additional_height_dict[prev.height] = prev
                if isinstance(curr, FullBlock):
                    assert curr.height == prev.height + 1
                reorg_chain[prev.height] = prev
                curr = prev

            peak: Optional[BlockRecord] = self.get_peak()
            if self.contains_block(curr.prev_header_hash) and peak is not None:
                # Then we look up blocks up to fork point one at a time, backtracking
                previous_block_hash = curr.prev_header_hash
                prev_block_record = await self.block_store.get_block_record(previous_block_hash)
                prev_block = await self.block_store.get_full_block(previous_block_hash)
                assert prev_block is not None
                assert prev_block_record is not None
                fork = find_fork_point_in_chain(self, peak, prev_block_record)
                curr_2: Optional[FullBlock] = prev_block
                assert curr_2 is not None and isinstance(curr_2, FullBlock)
                reorg_chain[curr_2.height] = curr_2
                while curr_2.height > fork and curr_2.height > 0:
                    curr_2 = await self.block_store.get_full_block(curr_2.prev_header_hash)
                    assert curr_2 is not None
                    reorg_chain[curr_2.height] = curr_2

            for ref_height in block.transactions_generator_ref_list:
                if ref_height in reorg_chain:
                    ref_block = reorg_chain[ref_height]
                    assert ref_block is not None
                    if ref_block.transactions_generator is None:
                        raise ValueError(Err.GENERATOR_REF_HAS_NO_GENERATOR)
                    result.append(GeneratorArg(ref_block.height, ref_block.transactions_generator))
                else:
                    if ref_height in additional_height_dict:
                        ref_block = additional_height_dict[ref_height]
                    else:
                        header_hash = self.height_to_hash(ref_height)
                        ref_block = await self.get_full_block(header_hash)
                    assert ref_block is not None
                    if ref_block.transactions_generator is None:
                        raise ValueError(Err.GENERATOR_REF_HAS_NO_GENERATOR)
                    result.append(GeneratorArg(ref_block.height, ref_block.transactions_generator))
        assert len(result) == len(ref_list)
        return BlockGenerator(block.transactions_generator, result)