def create_from_signed_change_request_message( cls: Type[T], message: SignedChangeRequestMessage, signing_key: hexstr) -> T: request = cls(signer=derive_public_key(signing_key), message=copy.deepcopy(message)) request.sign(signing_key) return request
def test_generate_key_pair(): key_pair = generate_key_pair() assert isinstance(key_pair.private, str) assert len(key_pair.private) == 64 assert isinstance(key_pair.public, str) assert len(key_pair.public) == 64 derived_public = derive_public_key(key_pair.private) assert derived_public == key_pair.public assert derived_public is not key_pair.public
def test_can_create_block_from_signed_change_request( forced_mock_blockchain, sample_signed_change_request: CoinTransferSignedChangeRequest ): sender = sample_signed_change_request.signer assert sender def get_account_balance(self, account, on_block_number): return 450 if account == sender else 0 with patch.object(MockBlockchain, 'get_account_balance', new=get_account_balance): block = Block.create_from_signed_change_request( forced_mock_blockchain, sample_signed_change_request, get_node_signing_key() ) assert block.message assert block.hash assert block.signature block.validate_signature() assert block.signer assert block.signer == derive_public_key(get_node_signing_key()) block_message = block.message signed_change_request = block_message.signed_change_request assert signed_change_request == sample_signed_change_request assert signed_change_request is not sample_signed_change_request # test that a copy of it was made assert isinstance(block_message.timestamp, datetime) assert block_message.timestamp.tzinfo is None assert block_message.timestamp - datetime.utcnow() < timedelta(seconds=1) assert block_message.block_number == 0 assert block_message.block_identifier == 'next-block-identifier' updated_account_states = block_message.updated_account_states assert isinstance(updated_account_states, dict) assert len(updated_account_states) == 4 assert updated_account_states[sender].balance == 450 - 425 - 4 - 1 assert updated_account_states[sender].balance_lock assert updated_account_states['484b3176c63d5f37d808404af1a12c4b9649cd6f6769f35bdf5a816133623fbc'].balance == 425 assert updated_account_states['484b3176c63d5f37d808404af1a12c4b9649cd6f6769f35bdf5a816133623fbc' ].balance_lock is None assert updated_account_states['ad1f8845c6a1abb6011a2a434a079a087c460657aad54329a84b406dce8bf314'].balance == 4 assert updated_account_states['ad1f8845c6a1abb6011a2a434a079a087c460657aad54329a84b406dce8bf314' ].balance_lock is None assert updated_account_states['5e12967707909e62b2bb2036c209085a784fabbc3deccefee70052b6181c8ed8'].balance == 1 assert updated_account_states['5e12967707909e62b2bb2036c209085a784fabbc3deccefee70052b6181c8ed8' ].balance_lock is None
def add_blocks_to_blockchain(blockchain, block_count, treasury_account_private_key): treasury_account_key_pair = KeyPair( public=derive_public_key(treasury_account_private_key), private=treasury_account_private_key ) generate_blockchain( blockchain, block_count, get_node_signing_key(), add_blockchain_genesis_state=False, validate=False, treasury_account_key_pair=treasury_account_key_pair )
def create_from_signed_change_request( cls: Type[T], blockchain, signed_change_request: SignedChangeRequest, pv_signing_key, ) -> T: block = cls( signer=derive_public_key(pv_signing_key), message=BlockMessage.from_signed_change_request(blockchain, signed_change_request) ) block.sign(pv_signing_key) block.hash_message() return block
def create(cls: Type[T], *, network_addresses: list[str], fee_amount: int, signing_key: hexstr, fee_account: Optional[hexstr] = None) -> T: message = NodeDeclarationSignedChangeRequestMessage.create( identifier=derive_public_key(signing_key), network_addresses=network_addresses, fee_amount=fee_amount, fee_account=fee_account, ) return cls.create_from_signed_change_request_message( message, signing_key)
def sign(self, signing_key): verify_key = derive_public_key(signing_key) stored_verify_key = self.signer if not stored_verify_key: logger.warning('Signing message with an empty signer') elif stored_verify_key != verify_key: logger.warning('Signer does not match with signing key') message_signature = self.message.generate_signature(signing_key) stored_message_signature = self.signature if stored_message_signature and stored_message_signature != message_signature: logger.warning('Overwriting existing message signature') self.signature = message_signature
def from_main_transaction(cls: Type[T], *, blockchain, recipient: hexstr, amount: int, signing_key: hexstr, primary_validator: PrimaryValidator, node: RegularNode, memo: str = None) -> T: message = CoinTransferSignedChangeRequestMessage.from_main_transaction( blockchain=blockchain, coin_sender=derive_public_key(signing_key), recipient=recipient, amount=amount, primary_validator=primary_validator, node=node, memo=memo, ) return cls.create_from_signed_change_request_message( message, signing_key)
def test_can_get_self_node(forced_memory_blockchain, api_client): blockchain = forced_memory_blockchain signing_key = get_node_signing_key() node_id = derive_public_key(signing_key) node_declaration_request = NodeDeclarationSignedChangeRequest.create( network_addresses=['http://my.domain.com/'], fee_amount=3, signing_key=signing_key, ) block = Block.create_from_signed_change_request( blockchain, signed_change_request=node_declaration_request, pv_signing_key=signing_key, ) blockchain.add_block(block) response = api_client.get(f'{API_V1_NODES_PREFIX}/self/') assert response.status_code == 200 data = response.json() assert data['identifier'] == node_id assert data['fee_amount'] == 3
def get_node_identifier() -> hexstr: return derive_public_key(get_node_signing_key())
def test_can_create_block_from_main_transaction( forced_mock_blockchain, treasury_account_key_pair: KeyPair, user_account_key_pair: KeyPair, primary_validator_key_pair: KeyPair, node_key_pair: KeyPair ): def get_account_balance(self, account, on_block_number): return 430 if account == treasury_account_key_pair.public else 0 with patch.object(MockBlockchain, 'get_account_balance', new=get_account_balance): block = Block.create_from_main_transaction( blockchain=forced_mock_blockchain, recipient=user_account_key_pair.public, amount=20, request_signing_key=treasury_account_key_pair.private, pv_signing_key=get_node_signing_key(), ) # Assert block assert block.message assert block.hash assert block.signature block.validate_signature() assert block.signer assert block.signer == derive_public_key(get_node_signing_key()) # Assert block.message block_message = block.message assert block_message assert isinstance(block_message.timestamp, datetime) assert block_message.timestamp.tzinfo is None assert block_message.timestamp - datetime.utcnow() < timedelta(seconds=1) assert block_message.block_number == 0 assert block_message.block_identifier == 'next-block-identifier' updated_account_states = block_message.updated_account_states assert isinstance(updated_account_states, dict) assert len(updated_account_states) == 4 assert updated_account_states[treasury_account_key_pair.public].balance == 430 - 25 assert updated_account_states[treasury_account_key_pair.public].balance_lock assert updated_account_states[user_account_key_pair.public].balance == 20 assert updated_account_states[user_account_key_pair.public].balance_lock is None assert updated_account_states[primary_validator_key_pair.public].balance == 4 assert updated_account_states[primary_validator_key_pair.public].balance_lock is None assert updated_account_states[node_key_pair.public].balance == 1 assert updated_account_states[node_key_pair.public].balance_lock is None # Assert block_message.signed_change_request signed_change_request = block_message.signed_change_request assert signed_change_request.signer == treasury_account_key_pair.public assert signed_change_request.signature # Assert block_message.signed_change_request.message coin_transfer_signed_request_message = signed_change_request.message assert isinstance(coin_transfer_signed_request_message, CoinTransferSignedChangeRequestMessage) assert coin_transfer_signed_request_message.balance_lock assert len(coin_transfer_signed_request_message.txs) == 3 txs_dict = {tx.recipient: tx for tx in coin_transfer_signed_request_message.txs} assert len(txs_dict) == 3 assert txs_dict[user_account_key_pair.public].amount == 20 assert txs_dict[user_account_key_pair.public].is_fee is False assert txs_dict[primary_validator_key_pair.public].amount == 4 assert txs_dict[primary_validator_key_pair.public].is_fee assert txs_dict[node_key_pair.public].amount == 1 assert txs_dict[node_key_pair.public].is_fee assert coin_transfer_signed_request_message.get_total_amount() == 25