Пример #1
0
def blockchain_state_20(treasury_initial_balance, treasury_account, user_account):
    user_balance = 2000
    return models.BlockchainState(
        last_block_number=20,
        account_states={
            treasury_account:
                AccountState(balance=treasury_initial_balance - user_balance, balance_lock=treasury_account),
            user_account:
                AccountState(balance=user_balance, balance_lock=user_account),
        },
    )
Пример #2
0
 def get_account_state(self, account: hexstr) -> AccountState:
     block_number = self.get_current_block_number()  # type: ignore
     return AccountState(
         balance=self.get_account_balance(account, block_number),
         balance_lock=self.get_account_balance_lock(account, block_number),
         node=self.get_node(account, block_number),
     )
Пример #3
0
    def generate_blockchain_state(self, last_block_number: Optional[int] = None) -> BlockchainState:
        last_blockchain_state_snapshot = self.get_closest_blockchain_state_snapshot(last_block_number)
        assert last_blockchain_state_snapshot is not None
        logger.debug(
            'Generating blockchain state snapshot based on blockchain state with last_block_number=%s',
            last_blockchain_state_snapshot.last_block_number
        )

        blockchain_state = deepcopy(last_blockchain_state_snapshot)
        account_states = blockchain_state.account_states

        block = None
        for block in self.yield_blocks_from(blockchain_state.get_next_block_number()):  # type: ignore
            if last_block_number is not None and block.message.block_number > last_block_number:
                logger.debug('Traversed all blocks of interest')
                break

            logger.debug('Traversing block number %s', block.message.block_number)
            for account_number, block_account_state in block.message.updated_account_states.items():
                logger.debug('Found %s account state: %s', account_number, block_account_state)
                blockchain_state_account_state = account_states.get(account_number)
                if blockchain_state_account_state is None:
                    logger.debug('Account %s is met for the first time (empty lock is expected)', account_number)
                    assert block_account_state.balance_lock is None
                    blockchain_state_account_state = AccountState()
                    account_states[account_number] = blockchain_state_account_state

                for attribute in AccountState.get_field_names():  # type: ignore
                    value = getattr(block_account_state, attribute)
                    if value is not None:
                        setattr(blockchain_state_account_state, attribute, deepcopy(value))

        if block is not None:
            blockchain_state.last_block_number = block.message.block_number
            blockchain_state.last_block_identifier = block.message.block_identifier
            blockchain_state.last_block_timestamp = block.message.timestamp
            blockchain_state.next_block_identifier = block.hash

        return blockchain_state
def generate_blockchain(blockchain: BlockchainBase,
                        size,
                        add_blockchain_genesis_state=True,
                        validate=True,
                        treasury_account_key_pair=None):
    treasury_account_key_pair = treasury_account_key_pair or generate_key_pair(
    )
    treasury_account = treasury_account_key_pair.public
    logger.info('Using treasury account: %s', treasury_account_key_pair)

    if add_blockchain_genesis_state and blockchain.get_blockchain_states_count(
    ) == 0:
        blockchain_genesis_state = BlockchainState(
            account_states={
                treasury_account:
                AccountState(balance=281474976710656,
                             balance_lock=treasury_account)
            })
        blockchain.add_blockchain_state(blockchain_genesis_state)

    primary_validator = PrimaryValidator(identifier=get_node_identifier(),
                                         fee_amount=4,
                                         network_addresses=[])
    pv_fee = primary_validator.fee_amount

    preferred_node = RegularNode(identifier=generate_key_pair().public,
                                 fee_amount=1,
                                 network_addresses=[])
    node_fee = preferred_node.fee_amount

    balances = get_initial_balances(blockchain)
    accounts = list(balances)

    assert len(balances) == 1
    assert treasury_account in balances
    assert balances[treasury_account] >= MAX_AMOUNT

    account_private_keys = {
        treasury_account: treasury_account_key_pair.private
    }
    sender_candidates = {treasury_account}
    min_sender_amount = MAX_AMOUNT + pv_fee + node_fee

    for _ in tqdm(range(size)):
        amount = random.randint(1, MAX_AMOUNT)
        # TODO(dmu) MEDIUM: Improve performance at tuple(sender_candidates)
        sender = random.choice(tuple(sender_candidates))
        sender_private_key = account_private_keys[sender]

        recipient, recipient_private_key = pick_recipient(accounts,
                                                          exclude=(sender, ))
        if recipient_private_key:
            # We got new recipient
            accounts.append(recipient)
            account_private_keys[recipient] = recipient_private_key

        signed_change_request = CoinTransferSignedChangeRequest.from_main_transaction(
            blockchain=blockchain,
            recipient=recipient,
            amount=amount,
            signing_key=sender_private_key,
            primary_validator=primary_validator,
            node=preferred_node)

        sender_new_balance = balances[sender] - (amount + pv_fee + node_fee)
        balances[sender] = sender_new_balance
        if sender_new_balance < min_sender_amount:
            sender_candidates.discard(sender)

        recipient_new_balance = balances.get(recipient, 0) + amount
        balances[recipient] = recipient_new_balance
        if recipient_new_balance >= min_sender_amount:
            sender_candidates.add(recipient)

        blockchain.add_block_from_signed_change_request(signed_change_request,
                                                        validate=validate)
Пример #5
0
def blockchain_genesis_state(treasury_account, treasury_initial_balance) -> BlockchainState:
    accounts = {treasury_account: AccountState(balance=treasury_initial_balance, balance_lock=treasury_account)}
    return BlockchainState(account_states=accounts)
Пример #6
0
def test_partial_blockchain(primary_validator, preferred_node):
    account1_key_pair = generate_key_pair()
    account2_key_pair = generate_key_pair()
    account3_key_pair = generate_key_pair()
    new_account_key_pair = generate_key_pair()

    fake_lock1, _ = generate_key_pair()
    fake_lock2, _ = generate_key_pair()
    fake_lock3, _ = generate_key_pair()

    base_account_root_file = BlockchainState(
        account_states={
            account1_key_pair.public: AccountState(balance=1000, balance_lock=fake_lock1),
            account2_key_pair.public: AccountState(balance=2000, balance_lock=fake_lock2),
            account3_key_pair.public: AccountState(balance=3000, balance_lock=fake_lock3),
        },
        last_block_number=1234,
        last_block_identifier='23203d245b5e128465669223b5220b3061af1e2e72b0429ef26b07ce3a2282e7',
        last_block_timestamp=datetime.utcnow(),
        next_block_identifier='626dea61c1a6480d6a4c9cd657c7d7be52ddc38e5f2ec590b609ac01edde62fd',
    )

    blockchain = MemoryBlockchain(account_root_files=[base_account_root_file])
    assert blockchain.get_block_count() == 0
    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 0
    blockchain.validate()

    signed_change_request1 = CoinTransferSignedChangeRequest.from_main_transaction(
        blockchain=blockchain,
        recipient=account2_key_pair.public,
        amount=10,
        signing_key=account1_key_pair.private,
        primary_validator=primary_validator,
        node=preferred_node
    )
    signed_change_request1.validate(blockchain, blockchain.get_next_block_number())
    blockchain.add_block_from_signed_change_request(signed_change_request1, get_node_signing_key())
    blockchain.validate()

    assert blockchain.get_block_count() == 1
    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000 - 10 - 4 - 1
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000 + 10
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 0

    signed_change_request2 = CoinTransferSignedChangeRequest.from_main_transaction(
        blockchain=blockchain,
        recipient=new_account_key_pair.public,
        amount=20,
        signing_key=account2_key_pair.private,
        primary_validator=primary_validator,
        node=preferred_node
    )
    signed_change_request2.validate(blockchain, blockchain.get_next_block_number())
    blockchain.add_block_from_signed_change_request(signed_change_request2, get_node_signing_key())
    blockchain.validate()

    assert blockchain.get_block_count() == 2
    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000 - 10 - 4 - 1
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000 + 10 - 20 - 4 - 1
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 20

    blockchain.snapshot_blockchain_state()
    blockchain.validate()

    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000 - 10 - 4 - 1
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000 + 10 - 20 - 4 - 1
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 20

    signed_change_request3 = CoinTransferSignedChangeRequest.from_main_transaction(
        blockchain=blockchain,
        recipient=account2_key_pair.public,
        amount=30,
        signing_key=account3_key_pair.private,
        primary_validator=primary_validator,
        node=preferred_node
    )
    signed_change_request3.validate(blockchain, blockchain.get_next_block_number())
    blockchain.add_block_from_signed_change_request(signed_change_request3, get_node_signing_key())
    blockchain.validate()

    assert blockchain.get_account_current_balance(account1_key_pair.public) == 1000 - 10 - 4 - 1
    assert blockchain.get_account_current_balance(account2_key_pair.public) == 2000 + 10 - 20 - 4 - 1 + 30
    assert blockchain.get_account_current_balance(account3_key_pair.public) == 3000 - 30 - 4 - 1
    assert blockchain.get_account_current_balance(new_account_key_pair.public) == 20