예제 #1
0
def get_updated_account_states_for_coin_transfer(
        signed_change_request: CoinTransferSignedChangeRequest,
        blockchain: BlockchainBase) -> dict[str, AccountState]:
    updated_account_states: dict[str, AccountState] = {}
    sent_amount = 0
    for transaction in signed_change_request.message.txs:
        recipient = transaction.recipient
        amount = transaction.amount

        account_state = updated_account_states.get(recipient)
        if account_state is None:
            account_state = AccountState(
                balance=blockchain.get_account_current_balance(recipient))
            updated_account_states[recipient] = account_state

        assert account_state.balance is not None
        account_state.balance += amount
        sent_amount += amount
    assert sent_amount > 0

    coin_sender = signed_change_request.signer
    sender_balance = blockchain.get_account_current_balance(coin_sender)
    assert sender_balance > 0
    assert sender_balance >= sent_amount

    updated_account_states[coin_sender] = AccountState(
        balance=sender_balance - sent_amount,
        balance_lock=make_balance_lock(signed_change_request))

    return updated_account_states
예제 #2
0
def yield_forced_blockchain(class_, class_kwargs=None):
    blockchain_settings = {'class': class_, 'kwargs': class_kwargs or {}}

    BlockchainBase.clear_instance_cache()
    with override_settings(BLOCKCHAIN=blockchain_settings):
        blockchain = BlockchainBase.get_instance()
        yield blockchain
    BlockchainBase.clear_instance_cache()
예제 #3
0
    def retrieve(self, request, pk=None):
        # TODO(dmu) MEDIUM: There is a room for performance optimization use something like `?fields=` to
        #                   retrieval of unneeded fields using get_account_balance() and get_account_balance_lock() directly.
        #                   Also see `drf-flex-fields` and `django-restql`.
        assert pk is not None

        blockchain = BlockchainBase.get_instance()
        serializer = AccountBalanceSerializer(blockchain.get_account_state(pk))
        return Response(serializer.data)
예제 #4
0
def test_make_blockchain_state_from_account_root_file(
        sample_account_root_file_dict):
    BlockchainBase.clear_instance_cache()
    with tempfile.NamedTemporaryFile('w') as fp:
        json.dump(sample_account_root_file_dict, fp)
        fp.flush()
        make_blockchain_state_from_account_root_file(fp.name)

    blockchain = BlockchainBase.get_instance()

    blockchain_state = blockchain.get_last_blockchain_state()
    for key, value in sample_account_root_file_dict.items():
        account_state = blockchain_state.get_account_state(key)
        assert account_state.balance == value['balance']
        assert account_state.get_balance_lock(key) == value['balance_lock']
        if value['balance_lock'] == key:
            assert account_state.balance_lock is None

        assert account_state.node is None
예제 #5
0
 def handle(self, *args, **options):
     blockchain = BlockchainBase.get_instance()
     if blockchain.is_empty():
         blockchain_genesis_state_source = options[
             'blockchain_genesis_state_source']
         logger.info('Empty blockchain detected: initializing with %s',
                     blockchain_genesis_state_source)
         initialize_blockchain(
             blockchain_genesis_state_source,
             failover_source=options[
                 'failover_blockchain_genesis_state_source'])
예제 #6
0
def large_blockchain(treasury_account_key_pair):
    blockchain = BlockchainBase.get_instance()

    accounts = blockchain.get_first_blockchain_state().account_states
    assert len(accounts) == 1
    treasury_account, account_state = list(accounts.items())[0]
    assert treasury_account_key_pair.public == treasury_account
    assert account_state.balance > 10000000000  # tons of money present

    add_blocks_to_blockchain(blockchain, 100, treasury_account_key_pair.private)
    yield blockchain
예제 #7
0
    def get_latest_blockchain_state_meta_by_node_identifier(
            self, blockchain: BlockchainBase,
            node_identifier: hexstr) -> Optional[dict]:
        node = blockchain.get_node_by_identifier(node_identifier)
        if node is None:
            return None

        network_addresses = node.network_addresses
        if not network_addresses:
            return None

        return self.get_latest_blockchain_state_meta_by_network_addresses(
            network_addresses)
예제 #8
0
    def handle(self, *args, **options):
        blockchain = BlockchainBase.get_instance()
        if not blockchain.is_empty() and options['force']:
            logger.info('Clearing existing blockchain')
            blockchain.clear()

        if not blockchain.is_empty():
            logger.info('Blockchain is already initialized')
            return

        sources = options['sources']
        has_added = add_blockchain_state_from_sources(blockchain, sources)
        if not has_added:
            logger.error('Was unable to get blockchain source from %s', sources)
예제 #9
0
    def retrieve(self, request, pk: str = None):
        assert pk is not None
        blockchain = BlockchainBase.get_instance()

        node_id = hexstr(pk.lower())
        if node_id == PRIMARY_VALIDATOR_NODE_ID:
            node = blockchain.get_primary_validator()
        elif node_id == SELF_NODE_ID:
            node = blockchain.get_node_by_identifier(
                identifier=get_node_identifier())
        else:
            node = blockchain.get_node_by_identifier(identifier=node_id)

        if node is None:
            raise NotFound(detail='Node not found')

        serializer = self.serializer_class(node)
        return Response(serializer.data)
def test_can_force_memory_blockchain():
    assert isinstance(BlockchainBase.get_instance(), MemoryBlockchain)
def write_default_blockchain(blockchain_state):
    blockchain = BlockchainBase.get_instance()
    blockchain.add_blockchain_state(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)
예제 #13
0
def blockchain_base(blockchain_genesis_state):
    blockchain = BlockchainBase()
    with patch.object(blockchain, 'yield_blockchain_states', get_generator([blockchain_genesis_state])):
        yield blockchain
 def handle(self, *args, **options):
     BlockchainBase.get_instance().clear()
예제 #15
0
 def handle(self, *args, **options):
     BlockchainBase.get_instance()
     raise NotImplementedError(
         'Blockchain has nodes workflow is not implemented yet')