def __init__(self, unspent_store: CoinStore, override_constants: Dict = {}):
        # Allow passing in custom overrides
        self.constants: Dict = consensus_constants.copy()
        for key, value in override_constants.items():
            self.constants[key] = value

        # Transactions that were unable to enter mempool, used for retry. (they were invalid)
        self.potential_txs: Dict[bytes32, SpendBundle] = {}
        # Keep track of seen spend_bundles
        self.seen_bundle_hashes: Dict[bytes32, bytes32] = {}
        # Mempool for each tip
        self.mempools: Dict[bytes32, Mempool] = {}

        # old_mempools will contain transactions that were removed in the last 10 blocks
        self.old_mempools: SortedDict[uint32, Dict[bytes32, MempoolItem]] = SortedDict()
        self.unspent_store = unspent_store

        tx_per_sec = self.constants["TX_PER_SEC"]
        sec_per_block = self.constants["BLOCK_TIME_TARGET"]
        block_buffer_count = self.constants["MEMPOOL_BLOCK_BUFFER"]

        # MEMPOOL_SIZE = 60000
        self.mempool_size = tx_per_sec * sec_per_block * block_buffer_count
        self.potential_cache_size = 300
        self.seen_cache_size = 10000
        self.coinbase_freeze = self.constants["COINBASE_FREEZE_PERIOD"]
    def create_genesis_block(
        self,
        input_constants: Dict,
        challenge_hash=bytes([0] * 32),
        seed: bytes = b"",
        reward_puzzlehash: Optional[bytes32] = None,
    ) -> FullBlock:
        """
        Creates the genesis block with the specified details.
        """
        test_constants: Dict[str, Any] = constants.copy()
        for key, value in input_constants.items():
            test_constants[key] = value

        return self._create_block(
            test_constants,
            challenge_hash,
            uint32(0),
            bytes([0] * 32),
            uint64(0),
            uint128(0),
            uint64(int(time.time())),
            uint64(test_constants["DIFFICULTY_STARTING"]),
            uint64(test_constants["MIN_ITERS_STARTING"]),
            seed,
            True,
            reward_puzzlehash,
        )
 def __init__(self,
              farmer_config: Dict,
              key_config: Dict,
              override_constants={}):
     self.config = farmer_config
     self.key_config = key_config
     self.harvester_responses_header_hash: Dict[bytes32, bytes32] = {}
     self.harvester_responses_challenge: Dict[bytes32, bytes32] = {}
     self.harvester_responses_proofs: Dict[bytes32, ProofOfSpace] = {}
     self.harvester_responses_proof_hash_to_qual: Dict[bytes32,
                                                       bytes32] = {}
     self.challenges: Dict[
         uint128, List[farmer_protocol.ProofOfSpaceFinalized]] = {}
     self.challenge_to_weight: Dict[bytes32, uint128] = {}
     self.challenge_to_height: Dict[bytes32, uint32] = {}
     self.challenge_to_best_iters: Dict[bytes32, uint64] = {}
     self.seen_challenges: Set[bytes32] = set()
     self.unfinished_challenges: Dict[uint128, List[bytes32]] = {}
     self.current_weight: uint128 = uint128(0)
     self.coinbase_rewards: Dict[uint32, Any] = {}
     self.proof_of_time_estimate_ips: uint64 = uint64(10000)
     self.constants = consensus_constants.copy()
     self.server = None
     self._shut_down = False
     for key, value in override_constants.items():
         self.constants[key] = value
Exemple #4
0
 async def create(
     coin_store: CoinStore,
     block_store: BlockStore,
     override_constants: Dict = {},
 ):
     """
     Initializes a blockchain with the header blocks from disk, assuming they have all been
     validated. Uses the genesis block given in override_constants, or as a fallback,
     in the consensus constants config.
     """
     self = Blockchain()
     self.lock = asyncio.Lock()  # External lock handled by full node
     cpu_count = multiprocessing.cpu_count()
     self.pool = concurrent.futures.ProcessPoolExecutor(
         max_workers=max(cpu_count - 1, 1))
     self.constants = consensus_constants.copy()
     for key, value in override_constants.items():
         self.constants[key] = value
     self.tips = []
     self.height_to_hash = {}
     self.headers = {}
     self.coin_store = coin_store
     self.block_store = block_store
     self._shut_down = False
     self.genesis = FullBlock.from_bytes(self.constants["GENESIS_BLOCK"])
     self.coinbase_freeze = self.constants["COINBASE_FREEZE_PERIOD"]
     await self._load_chain_from_store()
     return self
Exemple #5
0
    def create_next_block(
        self,
        input_constants: Dict,
        prev_block: FullBlock,
        timestamp: uint64,
        difficulty: uint64,
        ips: uint64,
        seed: bytes = b"",
    ) -> FullBlock:
        """
        Creates the next block with the specified details.
        """
        test_constants: Dict[str, Any] = constants.copy()
        for key, value in input_constants.items():
            test_constants[key] = value

        assert prev_block.header_block.challenge

        return self._create_block(
            test_constants,
            prev_block.header_block.challenge.get_hash(),
            uint32(prev_block.height + 1),
            prev_block.header_hash,
            prev_block.header_block.challenge.total_iters,
            prev_block.weight,
            timestamp,
            uint64(difficulty),
            ips,
            seed,
        )
    def create_next_block(
        self,
        input_constants: Dict,
        prev_block: FullBlock,
        timestamp: uint64,
        update_difficulty: bool,
        difficulty: uint64,
        min_iters: uint64,
        seed: bytes = b"",
        reward_puzzlehash: bytes32 = None,
        transactions: Program = None,
        aggsig: BLSSignature = None,
        fees: uint64 = uint64(0),
    ) -> FullBlock:
        """
        Creates the next block with the specified details.
        """
        test_constants: Dict[str, Any] = constants.copy()
        for key, value in input_constants.items():
            test_constants[key] = value
        assert prev_block.proof_of_time is not None
        if update_difficulty:
            challenge = Challenge(
                prev_block.proof_of_space.challenge_hash,
                std_hash(
                    prev_block.proof_of_space.get_hash()
                    + prev_block.proof_of_time.output.get_hash()
                ),
                difficulty,
            )
        else:
            challenge = Challenge(
                prev_block.proof_of_space.challenge_hash,
                std_hash(
                    prev_block.proof_of_space.get_hash()
                    + prev_block.proof_of_time.output.get_hash()
                ),
                None,
            )

        return self._create_block(
            test_constants,
            challenge.get_hash(),
            uint32(prev_block.height + 1),
            prev_block.header_hash,
            prev_block.header.data.total_iters,
            prev_block.weight,
            timestamp,
            uint64(difficulty),
            min_iters,
            seed,
            False,
            reward_puzzlehash,
            transactions,
            aggsig,
            fees,
        )
Exemple #7
0
    def __init__(
        self,
        farmer_config: Dict,
        pool_config: Dict,
        keychain: Keychain,
        override_constants={},
    ):
        self.config = farmer_config
        self.harvester_responses_header_hash: Dict[bytes32, bytes32] = {}
        self.harvester_responses_challenge: Dict[bytes32, bytes32] = {}
        self.harvester_responses_proofs: Dict[bytes32, ProofOfSpace] = {}
        self.harvester_responses_proof_hash_to_qual: Dict[bytes32,
                                                          bytes32] = {}
        self.challenges: Dict[
            uint128, List[farmer_protocol.ProofOfSpaceFinalized]] = {}
        self.challenge_to_weight: Dict[bytes32, uint128] = {}
        self.challenge_to_height: Dict[bytes32, uint32] = {}
        self.challenge_to_best_iters: Dict[bytes32, uint64] = {}
        self.challenge_to_estimates: Dict[bytes32, List[float]] = {}
        self.seen_challenges: Set[bytes32] = set()
        self.unfinished_challenges: Dict[uint128, List[bytes32]] = {}
        self.current_weight: uint128 = uint128(0)
        self.proof_of_time_estimate_ips: uint64 = uint64(10000)
        self.constants = consensus_constants.copy()
        self._shut_down = False
        self.server = None
        self.keychain = keychain
        self.state_changed_callback: Optional[Callable] = None

        # This is the farmer configuration
        self.wallet_target = bytes.fromhex(
            self.config["xch_target_puzzle_hash"])
        self.pool_public_keys = [
            PublicKey.from_bytes(bytes.fromhex(pk))
            for pk in self.config["pool_public_keys"]
        ]

        # This is the pool configuration, which should be moved out to the pool once it exists
        self.pool_target = bytes.fromhex(pool_config["xch_target_puzzle_hash"])
        self.pool_sks = [
            sk.get_private_key()
            for (sk, _) in self.keychain.get_all_private_keys()
        ]
        self.pool_sks_map: Dict = {}
        for key in self.pool_sks:
            self.pool_sks_map[bytes(key.get_public_key())] = key

        assert len(self.wallet_target) == 32
        assert len(self.pool_target) == 32
        if len(self.pool_sks) == 0:
            error_str = "No keys exist. Please run 'chia keys generate' or open the UI."
            raise RuntimeError(error_str)
        for key, value in override_constants.items():
            self.constants[key] = value
Exemple #8
0
    async def create(
        config: Dict,
        private_key: ExtendedPrivateKey,
        root_path: Path,
        name: str = None,
        override_constants: Dict = {},
        local_test: bool = False,
    ):
        self = WalletNode()
        self.config = config
        self.constants = consensus_constants.copy()
        self.root_path = root_path
        self.local_test = local_test
        for key, value in override_constants.items():
            self.constants[key] = value
        if name:
            self.log = logging.getLogger(name)
        else:
            self.log = logging.getLogger(__name__)

        db_path_key_suffix = str(
            private_key.get_public_key().get_fingerprint())
        path = path_from_root(
            self.root_path, f"{config['database_path']}-{db_path_key_suffix}")
        mkdir(path.parent)

        self.wallet_state_manager = await WalletStateManager.create(
            private_key, config, path, self.constants)
        self.wallet_state_manager.set_pending_callback(
            self._pending_tx_handler)

        # Normal operation data
        self.cached_blocks = {}
        self.future_block_hashes = {}

        # Sync data
        self._shut_down = False
        self.proof_hashes = []
        self.header_hashes = []
        self.header_hashes_error = False
        self.short_sync_threshold = 15
        self.potential_blocks_received = {}
        self.potential_header_hashes = {}

        self.server = None

        self.tasks = []

        return self
    def __init__(self, root_path: Path, override_constants={}):
        self.root_path = root_path

        # From filename to prover
        self.provers = {}
        self.failed_to_open_filenames = set()
        self.no_key_filenames = set()

        self._is_shutdown = False
        self.global_connections: Optional[PeerConnections] = None
        self.farmer_public_keys = []
        self.pool_public_keys = []
        self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=10)
        self.state_changed_callback = None
        self.server = None
        self.constants = consensus_constants.copy()
        self.cached_challenges = []
        for key, value in override_constants.items():
            self.constants[key] = value
    async def create(
        config: Dict,
        key_config: Dict,
        name: str = None,
        override_constants: Dict = {},
    ):
        self = WalletNode()
        self.config = config
        self.key_config = key_config
        self.constants = consensus_constants.copy()
        for key, value in override_constants.items():
            self.constants[key] = value
        if name:
            self.log = logging.getLogger(name)
        else:
            self.log = logging.getLogger(__name__)

        path = path_from_root(DEFAULT_ROOT_PATH, config["database_path"])
        mkdir(path.parent)

        self.wallet_state_manager = await WalletStateManager.create(
            key_config, config, path, self.constants)
        self.wallet_state_manager.set_pending_callback(
            self._pending_tx_handler)

        # Normal operation data
        self.cached_blocks = {}
        self.future_block_hashes = {}

        # Sync data
        self._shut_down = False
        self.proof_hashes = []
        self.header_hashes = []
        self.header_hashes_error = False
        self.short_sync_threshold = 15
        self.potential_blocks_received = {}
        self.potential_header_hashes = {}

        self.server = None

        return self
Exemple #11
0
    def create_genesis_block(self,
                             input_constants: Dict,
                             challenge_hash=bytes([0] * 32),
                             seed: bytes = b"") -> FullBlock:
        """
        Creates the genesis block with the specified details.
        """
        test_constants: Dict[str, Any] = constants.copy()
        for key, value in input_constants.items():
            test_constants[key] = value

        return self._create_block(
            test_constants,
            challenge_hash,
            uint32(0),
            bytes([0] * 32),
            uint64(0),
            uint64(0),
            uint64(int(time.time())),
            uint64(test_constants["DIFFICULTY_STARTING"]),
            uint64(test_constants["VDF_IPS_STARTING"]),
            seed,
        )
import asyncio
import pytest
import time
from typing import Dict, Any
from tests.setup_nodes import setup_full_system
from tests.block_tools import BlockTools
from src.consensus.constants import constants as consensus_constants

bt = BlockTools()
test_constants: Dict[str, Any] = consensus_constants.copy()
test_constants.update({
    "DIFFICULTY_STARTING": 500,
    "MIN_ITERS_STARTING": 2**15
})

test_constants["GENESIS_BLOCK"] = bytes(
    bt.create_genesis_block(test_constants, bytes([0] * 32), b"0"))


@pytest.fixture(scope="module")
def event_loop():
    loop = asyncio.get_event_loop()
    yield loop


class TestSimulation:
    @pytest.fixture(scope="function")
    async def simulation(self):
        async for _ in setup_full_system(test_constants):
            yield _
    def get_consecutive_blocks(
        self,
        input_constants: Dict,
        num_blocks: int,
        block_list: List[FullBlock] = [],
        seconds_per_block=None,
        seed: bytes = b"",
        reward_puzzlehash: bytes32 = None,
        transaction_data_at_height: Dict[int, Tuple[Program, BLSSignature]] = None,
        fees: uint64 = uint64(0),
    ) -> List[FullBlock]:
        if transaction_data_at_height is None:
            transaction_data_at_height = {}
        test_constants: Dict[str, Any] = constants.copy()
        for key, value in input_constants.items():
            test_constants[key] = value
        if seconds_per_block is None:
            seconds_per_block = test_constants["BLOCK_TIME_TARGET"]

        if len(block_list) == 0:
            if "GENESIS_BLOCK" in test_constants:
                block_list.append(FullBlock.from_bytes(test_constants["GENESIS_BLOCK"]))
            else:
                block_list.append(
                    self.create_genesis_block(test_constants, std_hash(seed), seed)
                )
            prev_difficulty = test_constants["DIFFICULTY_STARTING"]
            curr_difficulty = prev_difficulty
            curr_min_iters = test_constants["MIN_ITERS_STARTING"]
        elif len(block_list) < (
            test_constants["DIFFICULTY_EPOCH"] + test_constants["DIFFICULTY_DELAY"]
        ):
            # First epoch (+delay), so just get first difficulty
            prev_difficulty = block_list[0].weight
            curr_difficulty = block_list[0].weight
            assert test_constants["DIFFICULTY_STARTING"] == prev_difficulty
            curr_min_iters = test_constants["MIN_ITERS_STARTING"]
        else:
            curr_difficulty = block_list[-1].weight - block_list[-2].weight
            prev_difficulty = (
                block_list[-1 - test_constants["DIFFICULTY_EPOCH"]].weight
                - block_list[-2 - test_constants["DIFFICULTY_EPOCH"]].weight
            )
            assert block_list[-1].proof_of_time is not None
            curr_min_iters = calculate_min_iters_from_iterations(
                block_list[-1].proof_of_space,
                curr_difficulty,
                block_list[-1].proof_of_time.number_of_iterations,
            )

        starting_height = block_list[-1].height + 1
        timestamp = block_list[-1].header.data.timestamp
        for next_height in range(starting_height, starting_height + num_blocks):
            if (
                next_height > test_constants["DIFFICULTY_EPOCH"]
                and next_height % test_constants["DIFFICULTY_EPOCH"]
                == test_constants["DIFFICULTY_DELAY"]
            ):
                # Calculates new difficulty
                height1 = uint64(
                    next_height
                    - (
                        test_constants["DIFFICULTY_EPOCH"]
                        + test_constants["DIFFICULTY_DELAY"]
                    )
                    - 1
                )
                height2 = uint64(next_height - (test_constants["DIFFICULTY_EPOCH"]) - 1)
                height3 = uint64(next_height - (test_constants["DIFFICULTY_DELAY"]) - 1)
                if height1 >= 0:
                    block1 = block_list[height1]
                    iters1 = block1.header.data.total_iters
                    timestamp1 = block1.header.data.timestamp
                else:
                    block1 = block_list[0]
                    timestamp1 = (
                        block1.header.data.timestamp
                        - test_constants["BLOCK_TIME_TARGET"]
                    )
                    iters1 = uint64(0)
                timestamp2 = block_list[height2].header.data.timestamp
                timestamp3 = block_list[height3].header.data.timestamp

                block3 = block_list[height3]
                iters3 = block3.header.data.total_iters
                term1 = (
                    test_constants["DIFFICULTY_DELAY"]
                    * prev_difficulty
                    * (timestamp3 - timestamp2)
                    * test_constants["BLOCK_TIME_TARGET"]
                )

                term2 = (
                    (test_constants["DIFFICULTY_WARP_FACTOR"] - 1)
                    * (
                        test_constants["DIFFICULTY_EPOCH"]
                        - test_constants["DIFFICULTY_DELAY"]
                    )
                    * curr_difficulty
                    * (timestamp2 - timestamp1)
                    * test_constants["BLOCK_TIME_TARGET"]
                )

                # Round down after the division
                new_difficulty_precise: uint64 = uint64(
                    (term1 + term2)
                    // (
                        test_constants["DIFFICULTY_WARP_FACTOR"]
                        * (timestamp3 - timestamp2)
                        * (timestamp2 - timestamp1)
                    )
                )
                new_difficulty = uint64(
                    truncate_to_significant_bits(
                        new_difficulty_precise, test_constants["SIGNIFICANT_BITS"]
                    )
                )
                max_diff = uint64(
                    truncate_to_significant_bits(
                        test_constants["DIFFICULTY_FACTOR"] * curr_difficulty,
                        test_constants["SIGNIFICANT_BITS"],
                    )
                )
                min_diff = uint64(
                    truncate_to_significant_bits(
                        curr_difficulty // test_constants["DIFFICULTY_FACTOR"],
                        test_constants["SIGNIFICANT_BITS"],
                    )
                )
                if new_difficulty >= curr_difficulty:
                    new_difficulty = min(new_difficulty, max_diff,)
                else:
                    new_difficulty = max([uint64(1), new_difficulty, min_diff])

                min_iters_precise = uint64(
                    (iters3 - iters1)
                    // (
                        test_constants["DIFFICULTY_EPOCH"]
                        * test_constants["MIN_ITERS_PROPORTION"]
                    )
                )
                curr_min_iters = uint64(
                    truncate_to_significant_bits(
                        min_iters_precise, test_constants["SIGNIFICANT_BITS"]
                    )
                )
                prev_difficulty = curr_difficulty
                curr_difficulty = new_difficulty
            time_taken = seconds_per_block
            timestamp += time_taken

            transactions: Optional[Program] = None
            aggsig: Optional[BLSSignature] = None
            if next_height in transaction_data_at_height:
                transactions, aggsig = transaction_data_at_height[next_height]

            update_difficulty = (
                next_height % test_constants["DIFFICULTY_EPOCH"]
                == test_constants["DIFFICULTY_DELAY"]
            )
            block_list.append(
                self.create_next_block(
                    test_constants,
                    block_list[-1],
                    timestamp,
                    update_difficulty,
                    curr_difficulty,
                    curr_min_iters,
                    seed,
                    reward_puzzlehash,
                    transactions,
                    aggsig,
                    fees,
                )
            )
        return block_list
Exemple #14
0
    def get_consecutive_blocks(
        self,
        input_constants: Dict,
        num_blocks: int,
        block_list: List[FullBlock] = [],
        seconds_per_block=constants["BLOCK_TIME_TARGET"],
        seed: bytes = b"",
    ) -> List[FullBlock]:
        test_constants: Dict[str, Any] = constants.copy()
        for key, value in input_constants.items():
            test_constants[key] = value

        if len(block_list) == 0:
            if "GENESIS_BLOCK" in test_constants:
                block_list.append(
                    FullBlock.from_bytes(test_constants["GENESIS_BLOCK"]))
            else:
                block_list.append(
                    self.create_genesis_block(test_constants,
                                              sha256(seed).digest(), seed))
            prev_difficulty = test_constants["DIFFICULTY_STARTING"]
            curr_difficulty = prev_difficulty
            curr_ips = test_constants["VDF_IPS_STARTING"]
        elif len(block_list) < (test_constants["DIFFICULTY_EPOCH"] +
                                test_constants["DIFFICULTY_DELAY"]):
            # First epoch (+delay), so just get first difficulty
            prev_difficulty = block_list[0].weight
            curr_difficulty = block_list[0].weight
            assert test_constants["DIFFICULTY_STARTING"] == prev_difficulty
            curr_ips = test_constants["VDF_IPS_STARTING"]
        else:
            curr_difficulty = block_list[-1].weight - block_list[-2].weight
            prev_difficulty = (
                block_list[-1 - test_constants["DIFFICULTY_EPOCH"]].weight -
                block_list[-2 - test_constants["DIFFICULTY_EPOCH"]].weight)
            assert block_list[-1].header_block.proof_of_time
            curr_ips = calculate_ips_from_iterations(
                block_list[-1].header_block.proof_of_space,
                curr_difficulty,
                block_list[-1].header_block.proof_of_time.number_of_iterations,
                test_constants["MIN_BLOCK_TIME"],
            )

        starting_height = block_list[-1].height + 1
        timestamp = block_list[-1].header_block.header.data.timestamp
        for next_height in range(starting_height,
                                 starting_height + num_blocks):
            if (next_height > test_constants["DIFFICULTY_EPOCH"]
                    and next_height % test_constants["DIFFICULTY_EPOCH"]
                    == test_constants["DIFFICULTY_DELAY"]):
                # Calculates new difficulty
                height1 = uint64(next_height -
                                 (test_constants["DIFFICULTY_EPOCH"] +
                                  test_constants["DIFFICULTY_DELAY"]) - 1)
                height2 = uint64(next_height -
                                 (test_constants["DIFFICULTY_EPOCH"]) - 1)
                height3 = uint64(next_height -
                                 (test_constants["DIFFICULTY_DELAY"]) - 1)
                if height1 >= 0:
                    block1 = block_list[height1]
                    assert block1.header_block.challenge
                    iters1 = block1.header_block.challenge.total_iters
                    timestamp1 = block1.header_block.header.data.timestamp
                else:
                    block1 = block_list[0]
                    assert block1.header_block.challenge
                    timestamp1 = (block1.header_block.header.data.timestamp -
                                  test_constants["BLOCK_TIME_TARGET"])
                    iters1 = block1.header_block.challenge.total_iters
                timestamp2 = block_list[
                    height2].header_block.header.data.timestamp
                timestamp3 = block_list[
                    height3].header_block.header.data.timestamp

                block3 = block_list[height3]
                assert block3.header_block.challenge
                iters3 = block3.header_block.challenge.total_iters
                term1 = (test_constants["DIFFICULTY_DELAY"] * prev_difficulty *
                         (timestamp3 - timestamp2) *
                         test_constants["BLOCK_TIME_TARGET"])

                term2 = ((test_constants["DIFFICULTY_WARP_FACTOR"] - 1) *
                         (test_constants["DIFFICULTY_EPOCH"] -
                          test_constants["DIFFICULTY_DELAY"]) *
                         curr_difficulty * (timestamp2 - timestamp1) *
                         test_constants["BLOCK_TIME_TARGET"])

                # Round down after the division
                new_difficulty: uint64 = uint64(
                    (term1 + term2) //
                    (test_constants["DIFFICULTY_WARP_FACTOR"] *
                     (timestamp3 - timestamp2) * (timestamp2 - timestamp1)))

                if new_difficulty >= curr_difficulty:
                    new_difficulty = min(
                        new_difficulty,
                        uint64(test_constants["DIFFICULTY_FACTOR"] *
                               curr_difficulty),
                    )
                else:
                    new_difficulty = max([
                        uint64(1),
                        new_difficulty,
                        uint64(curr_difficulty //
                               test_constants["DIFFICULTY_FACTOR"]),
                    ])

                new_ips = uint64(
                    (iters3 - iters1) // (timestamp3 - timestamp1))
                if new_ips >= curr_ips:
                    curr_ips = min(
                        new_ips,
                        uint64(test_constants["IPS_FACTOR"] * new_ips))
                else:
                    curr_ips = max([
                        uint64(1),
                        new_ips,
                        uint64(curr_ips // test_constants["IPS_FACTOR"]),
                    ])

                prev_difficulty = curr_difficulty
                curr_difficulty = new_difficulty
            time_taken = seconds_per_block
            timestamp += time_taken
            block_list.append(
                self.create_next_block(
                    test_constants,
                    block_list[-1],
                    timestamp,
                    curr_difficulty,
                    curr_ips,
                    seed,
                ))
        return block_list