Esempio n. 1
0
 def __init__(self, str_signing_key=None):
     if str_signing_key is None:
         self._context = Secp256k1Context()
         self._signing_key = self._context.new_random_private_key()
         self._verifying_key = self._context.get_public_key(
             self._signing_key)
     else:
         self._context = Secp256k1Context()
         hexed_string = str_signing_key.encode()
         self._signing_key = Secp256k1PrivateKey.from_hex(hexed_string)
         self._verifying_key = self._context.get_public_key(
             self._signing_key)
def test_store_public_key_for_other_not_der_public_key_format():
    """
    Case: send transaction request to store certificate public key not in DER format for other.
    Expect: invalid transaction error is raised with public key is already registered error message.
    """
    not_der_format_public_key_to_store = b'h8ybuhtvrofpckejfhgubicojslmkghvbiuokl'

    address_from_public_key_to_store = generate_address('pub_key', not_der_format_public_key_to_store)

    inputs = outputs = [
        address_from_public_key_to_store,
        OWNER_ADDRESS,
        ZERO_ADDRESS,
        IS_NODE_ECONOMY_ENABLED_ADDRESS,
    ]

    new_public_key_payload = generate_rsa_payload(key=not_der_format_public_key_to_store)
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(
        serialized_transaction_payload, inputs, outputs, signer_public_key=PAYER_PUBLIC_KEY,
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    mock_context = StubContext(inputs=inputs, outputs=outputs, initial_state={})

    with pytest.raises(InvalidTransaction) as error:
        PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    assert 'Cannot deserialize the provided public key. Check if it is in DER format.' == str(error.value)
def test_store_public_key_for_other_no_payer_account():
    """
    Case: send transaction request, to store certificate public key for other, when payer account does not exist.
    Expect: invalid transaction error is raised with not enough transferable balance error message.
    """
    new_public_key_payload = generate_rsa_payload(key=CERTIFICATE_PUBLIC_KEY)
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(
        serialized_transaction_payload, INPUTS, OUTPUTS, signer_public_key=PAYER_PUBLIC_KEY,
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    owner_account = Account()
    owner_account.pub_keys.append(RANDOM_ALREADY_STORED_OWNER_PUBLIC_KEY_ADDRESS)
    serialized_owner_account = owner_account.SerializeToString()

    zero_account = Account()
    zero_account.balance = 0
    serialized_zero_account = zero_account.SerializeToString()

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={
        OWNER_ADDRESS: serialized_owner_account,
        ZERO_ADDRESS: serialized_zero_account,
    })

    with pytest.raises(InvalidTransaction) as error:
        PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    assert 'Not enough transferable balance. Sender\'s current balance: 0.' == str(error.value)
def test_store_public_key_for_other_already_registered_public_key():
    """
    Case: send transaction request to store already registered certificate public key for other.
    Expect: invalid transaction error is raised with public key is already registered error message.
    """
    new_public_key_payload = generate_rsa_payload(key=CERTIFICATE_PUBLIC_KEY)
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(
        serialized_transaction_payload, INPUTS, OUTPUTS, signer_public_key=PAYER_PUBLIC_KEY,
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    already_registered_public_key = PubKeyStorage()
    already_registered_public_key.owner = OWNER_PUBLIC_KEY
    already_registered_public_key.payload.CopyFrom(new_public_key_payload)
    already_registered_public_key.is_revoked = False
    serialized_already_registered_public_key = already_registered_public_key.SerializeToString()

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={
        ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY: serialized_already_registered_public_key,
    })

    with pytest.raises(InvalidTransaction) as error:
        PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    assert 'This public key is already registered.' == str(error.value)
Esempio n. 5
0
def create_context(algorithm_name):
    """Returns an algorithm instance by name.

    Args:
        algorithm_name (str): the algorithm name

    Returns:
        (:obj:`Context`): a context instance for the given algorithm

    Raises:
        NoSuchAlgorithmError if the algorithm is unknown
    """
    if algorithm_name == 'secp256k1':
        return Secp256k1Context()

    raise NoSuchAlgorithmError("no such algorithm: {}".format(algorithm_name))
def test_store_public_key_for_other_invalid_certificate_signature():
    """
    Case: send transaction request, to store certificate public for other, when certificate signature_by_owner is invalid.
    Expect: invalid transaction error is raised with public key is already registered error message.
    """
    not_user_certificate_private_key = rsa.generate_private_key(
        public_exponent=65537, key_size=2048, backend=default_backend(),
    )

    entity_hash_signature = generate_rsa_signature(b'w', not_user_certificate_private_key)

    new_public_key_payload = generate_rsa_payload(
        key=CERTIFICATE_PUBLIC_KEY, entity_hash_signature=entity_hash_signature,
    )
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()
    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(serialized_transaction_payload, INPUTS, OUTPUTS)
    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={})

    with pytest.raises(InvalidTransaction) as error:
        PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    assert 'Payed public key has invalid signature.' == str(error.value)
def test_store_public_key_for_other_public_key_exceeded_validity():
    """
    Case: send transaction request to store certificate public key with exceeded validity for other.
    Expect: invalid transaction error is raised with validity exceeds the maximum value error message.
    """
    new_public_key_payload = generate_rsa_payload(
        key=CERTIFICATE_PUBLIC_KEY, valid_to=int(EXCEEDED_PUBLIC_KEY_VALIDITY_TIMESTAMP),
    )
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(
        serialized_transaction_payload, INPUTS, OUTPUTS, signer_public_key=PAYER_PUBLIC_KEY,
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={})

    with pytest.raises(InvalidTransaction) as error:
        PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    assert 'The public key validity exceeds the maximum value.' == str(error.value)
Esempio n. 8
0
    def sign(self, data, rsa_signature_padding=None):
        """
        Sign provided data with selected key implementation.

        Args:
            data (str): data string which will be signed
            rsa_signature_padding (RsaSignaturePadding, optional): not used in ECDSA

        Returns:
            Hex string of signature.
        """
        if self._private_key is None:
            raise Exception('Private key is not provided!')

        if isinstance(data, str):
            data = utf8_to_bytes(data)

        sig = Secp256k1Context().sign(message=data,
                                      private_key=self._private_key_obj)
        return sig
Esempio n. 9
0
    def verify(self, data, signature, rsa_signature_padding=None):
        """
        Verify signature for selected key implementation.

        Args:
            data (str): data string which will be verified
            signature (str): hex string of signature
            rsa_signature_padding (RsaSignaturePadding, optional): not used in ECDSA

        Returns:
            Boolean ``True`` if signature is correct, or ``False`` if invalid.
        """
        if isinstance(data, str):
            data = utf8_to_bytes(data)

        try:
            if isinstance(signature, bytes):
                signature = binascii.hexlify(signature).decode('utf-8')

            return Secp256k1Context().verify(signature, data,
                                             self._public_key_obj)

        except Exception:
            return False
 def verify(self, product_id, product_name, signature):
     msg = bytes("{}:{}".format(product_id, product_name), 'utf-8')
     return Secp256k1Context().verify(signature, msg,
                                      self._signer.get_public_key())
Esempio n. 11
0
    def _store_public_key_for_other(self, context, signer_pubkey, transaction_payload):
        """
        Store public key for other account.

        The transaction for account which want to pay for other account public keys storing.

        A first account -> send payload -> A second account -> send transaction with first account's public key,
        but sign and pay for storing on own -> Remme-core.

        So Remme core charges tokens from a second account, but store a first account's public key.
        Public key owner here is a first account.

        Arguments:
            context (sawtooth_sdk.processor.context): context to store updated state (blockchain data).
            signer_pubkey: transaction sender public key.
            transaction_payload (pub_key_pb2.NewPubKeyStoreAndPayPayload): payload for storing public key for other.
        """
        new_public_key_payload = transaction_payload.pub_key_payload

        owner_public_key_as_bytes = transaction_payload.owner_public_key
        owner_public_key_as_hex = owner_public_key_as_bytes.hex()

        owner_secp256k1_public_key = Secp256k1PublicKey.from_hex(owner_public_key_as_hex)

        is_owner_public_key_payload_signature_valid = Secp256k1Context().verify(
            signature=transaction_payload.signature_by_owner.hex(),
            message=new_public_key_payload.SerializeToString(),
            public_key=owner_secp256k1_public_key,
        )
        if not is_owner_public_key_payload_signature_valid:
            raise InvalidTransaction('Public key owner\'s signature is invalid.')

        processor = self._get_public_key_processor(transaction_payload=transaction_payload.pub_key_payload)

        if not processor.verify():
            raise InvalidTransaction('Payed public key has invalid signature.')

        public_key = processor.get_public_key()
        public_key_to_store_address = self.make_address_from_data(public_key)

        public_key_to_store_owner_address = AccountHandler().make_address_from_data(owner_public_key_as_hex)
        payer_for_storing_address = AccountHandler().make_address_from_data(signer_pubkey)

        public_key_information, public_key_to_store_owner_account, payer_for_storing_account = get_multiple_data(context, [
            (public_key_to_store_address, PubKeyStorage),
            (public_key_to_store_owner_address, Account),
            (payer_for_storing_address, Account),
        ])

        if public_key_information:
            raise InvalidTransaction('This public key is already registered.')

        if public_key_to_store_owner_account is None:
            public_key_to_store_owner_account = Account()

        if payer_for_storing_account is None:
            payer_for_storing_account = Account()

        if not self._is_public_key_validity_exceeded(
            valid_from=new_public_key_payload.valid_from,
            valid_to=new_public_key_payload.valid_to,
        ):
            raise InvalidTransaction('The public key validity exceeds the maximum value.')

        public_key_information = PubKeyStorage()
        public_key_information.owner = owner_public_key_as_hex
        public_key_information.payload.CopyFrom(new_public_key_payload)
        public_key_information.is_revoked = False

        state = {
            public_key_to_store_owner_address: public_key_to_store_owner_account,
            payer_for_storing_address: payer_for_storing_account,
            public_key_to_store_address: public_key_information,
        }

        charging_state = self._charge_for_storing(context=context, address_from=payer_for_storing_address)
        if charging_state is not None:
            state.update(charging_state)

        public_key_to_store_owner_account = self._store_public_key_to_account(
            public_key_to_store_address=public_key_to_store_address,
            public_key_to_store_owner_account=public_key_to_store_owner_account,
        )

        state.update({
            public_key_to_store_owner_address: public_key_to_store_owner_account,
        })

        return state
    def _store_certificate(self, context, signer_pubkey, transaction_payload):
        address = self.make_address_from_data(transaction_payload.certificate_raw)
        data = get_data(context, CertificateStorage, address)
        if data:
            raise InvalidTransaction('This certificate is already registered.')

        certificate = x509.load_der_x509_certificate(bytes.fromhex(transaction_payload.certificate_raw),
                                                     default_backend())

        if transaction_payload.cert_signer_public_key:
            cert_signer_pubkey = load_pem_public_key(transaction_payload.cert_signer_public_key.encode('utf-8'),
                                                     backend=default_backend())
        else:
            cert_signer_pubkey = certificate.public_key()

        try:
            cert_signer_pubkey.verify(bytes.fromhex(transaction_payload.signature_crt),
                                      bytes.fromhex(transaction_payload.signature_rem),
                                      padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
                                                  salt_length=padding.PSS.MAX_LENGTH),
                                      hashes.SHA256())
        except InvalidSignature:
            raise InvalidTransaction('signature_crt mismatch')

        crt_hash = hashlib.sha512(transaction_payload.certificate_raw.encode('utf-8')).hexdigest().encode('utf-8')
        sawtooth_signing_ctx = Secp256k1Context()
        sawtooth_signing_pubkey = Secp256k1PublicKey.from_hex(signer_pubkey)
        sawtooth_signing_check_res = \
            sawtooth_signing_ctx.verify(transaction_payload.signature_rem,
                                        crt_hash,
                                        sawtooth_signing_pubkey)
        if not sawtooth_signing_check_res:
            raise InvalidTransaction('signature_rem mismatch with signer key {}'.format(signer_pubkey))

        subject = certificate.subject
        issuer = certificate.issuer

        organization = issuer.get_attributes_for_oid(NameOID.ORGANIZATION_NAME)[0].value
        uid = issuer.get_attributes_for_oid(NameOID.USER_ID)[0].value
        valid_from = certificate.not_valid_before
        valid_until = certificate.not_valid_after

        if organization != CERT_ORGANIZATION:
            raise InvalidTransaction('The organization name should be set to REMME. The actual name is {}'
                                     .format(organization))
        if uid != signer_pubkey:
            raise InvalidTransaction('The certificate should be sent by its signer. Certificate signed by {}. '
                                     'Transaction sent by {}.'.format(uid, signer_pubkey))

        if valid_until - valid_from > CERT_MAX_VALIDITY:
            raise InvalidTransaction('The certificate validity exceeds the maximum value.')

        fingerprint = certificate.fingerprint(hashes.SHA512()).hex()[:64]
        data = CertificateStorage()
        data.hash = fingerprint
        data.owner = signer_pubkey
        data.revoked = False

        account_address, account = TokenHandler.get_account_by_pub_key(context, signer_pubkey)
        if account.balance < CERT_STORE_PRICE:
            raise InvalidTransaction('Not enough tokens to register a new certificate. Current balance: {}'
                                     .format(account.balance))
        account.balance -= CERT_STORE_PRICE

        LOGGER.info('Registered a new certificate on address {}. Fingerprint: {}'.format(address, fingerprint))

        return {address: data,
                account_address: account}
Esempio n. 13
0
def test_store_public_key_for_other_economy_is_not_enabled():
    """
    Case: send transaction request, to store certificate public key for other, when economy isn't enabled.
    Expect: public key information is stored to blockchain linked to owner address. Owner hasn't paid for storing.
    """
    new_public_key_payload = generate_rsa_payload(key=CERTIFICATE_PUBLIC_KEY)
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(
        serialized_transaction_payload, INPUTS, OUTPUTS, signer_public_key=PAYER_PUBLIC_KEY,
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    payer_account = Account()
    payer_account.balance = PAYER_INITIAL_BALANCE
    serialized_payer_account = payer_account.SerializeToString()

    owner_account = Account()
    owner_account.pub_keys.append(RANDOM_ALREADY_STORED_OWNER_PUBLIC_KEY_ADDRESS)
    serialized_owner_account = owner_account.SerializeToString()

    zero_account = Account()
    zero_account.balance = 0
    serialized_zero_account = zero_account.SerializeToString()

    is_economy_enabled_setting = Setting()
    is_economy_enabled_setting.entries.add(key='remme.economy_enabled', value='false')
    serialized_is_economy_enabled_setting = is_economy_enabled_setting.SerializeToString()

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={
        OWNER_ADDRESS: serialized_owner_account,
        PAYER_ADDRESS: serialized_payer_account,
        ZERO_ADDRESS: serialized_zero_account,
        IS_NODE_ECONOMY_ENABLED_ADDRESS: serialized_is_economy_enabled_setting,
    })

    expected_public_key_storage = PubKeyStorage()
    expected_public_key_storage.owner = OWNER_PUBLIC_KEY
    expected_public_key_storage.payload.CopyFrom(new_public_key_payload)
    expected_public_key_storage.is_revoked = False
    expected_serialized_public_key_storage = expected_public_key_storage.SerializeToString()

    expected_payer_account = Account()
    expected_payer_account.balance = PAYER_INITIAL_BALANCE
    serialized_expected_payer_account = expected_payer_account.SerializeToString()

    expected_owner_account = Account()
    expected_owner_account.pub_keys.append(RANDOM_ALREADY_STORED_OWNER_PUBLIC_KEY_ADDRESS)
    expected_owner_account.pub_keys.append(ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY)
    serialized_expected_owner_account = expected_owner_account.SerializeToString()

    expected_zero_account = Account()
    expected_zero_account.balance = 0
    expected_serialized_zero_account = expected_zero_account.SerializeToString()

    expected_state = {
        OWNER_ADDRESS: serialized_expected_owner_account,
        PAYER_ADDRESS: serialized_expected_payer_account,
        ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY: expected_serialized_public_key_storage,
        ZERO_ADDRESS: expected_serialized_zero_account,
    }

    PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    state_as_list = mock_context.get_state(addresses=[
        OWNER_ADDRESS, PAYER_ADDRESS, ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY, ZERO_ADDRESS,
    ])

    state_as_dict = {entry.address: entry.data for entry in state_as_list}

    assert expected_state == state_as_dict
Esempio n. 14
0
def test_store_rsa_public_key_no_owner_account():
    """
    Case: send transaction request, to store certificate public key (RSA) for other, when owner account does not exist.
    Expect: public key information is stored to blockchain linked to the newly created owner account's address.
    """
    new_public_key_payload = generate_rsa_payload(key=CERTIFICATE_PUBLIC_KEY)
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(
        serialized_transaction_payload, INPUTS, OUTPUTS, signer_public_key=PAYER_PUBLIC_KEY,
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    payer_account = Account()
    payer_account.balance = PAYER_INITIAL_BALANCE
    serialized_payer_account = payer_account.SerializeToString()

    zero_account = Account()
    zero_account.balance = 0
    serialized_zero_account = zero_account.SerializeToString()

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={
        PAYER_ADDRESS: serialized_payer_account,
        ZERO_ADDRESS: serialized_zero_account,
    })

    expected_public_key_storage = PubKeyStorage()
    expected_public_key_storage.owner = OWNER_PUBLIC_KEY
    expected_public_key_storage.payload.CopyFrom(new_public_key_payload)
    expected_public_key_storage.is_revoked = False
    expected_serialized_public_key_storage = expected_public_key_storage.SerializeToString()

    expected_payer_account = Account()
    expected_payer_account.balance = PAYER_INITIAL_BALANCE - PUB_KEY_STORE_PRICE
    serialized_expected_payer_account = expected_payer_account.SerializeToString()

    expected_owner_account = Account()
    expected_owner_account.pub_keys.append(ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY)
    serialized_expected_owner_account = expected_owner_account.SerializeToString()

    expected_zero_account = Account()
    expected_zero_account.balance = 0 + PUB_KEY_STORE_PRICE
    expected_serialized_zero_account = expected_zero_account.SerializeToString()

    expected_state = {
        OWNER_ADDRESS: serialized_expected_owner_account,
        PAYER_ADDRESS: serialized_expected_payer_account,
        ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY: expected_serialized_public_key_storage,
        ZERO_ADDRESS: expected_serialized_zero_account,
    }

    PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    state_as_list = mock_context.get_state(addresses=[
        OWNER_ADDRESS, PAYER_ADDRESS, ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY, ZERO_ADDRESS,
    ])

    state_as_dict = {entry.address: entry.data for entry in state_as_list}

    assert expected_state == state_as_dict
Esempio n. 15
0
def test_store_ecdsa_public_key():
    """
    Case: send transaction request to store certificate public key (ECDSA) for other.
    Expect: public key information is stored to blockchain linked to owner address. Transaction sender paid for storing.
    """
    inputs = outputs = [
        ADDRESS_FROM_ECDSA_PUBLIC_KEY,
        OWNER_ADDRESS,
        PAYER_ADDRESS,
        ZERO_ADDRESS,
        IS_NODE_ECONOMY_ENABLED_ADDRESS,
    ]

    new_public_key_payload = generate_ecdsa_payload(key=ECDSA_PUBLIC_KEY)
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(
        serialized_transaction_payload, inputs, outputs, signer_public_key=PAYER_PUBLIC_KEY,
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    payer_account = Account()
    payer_account.balance = PAYER_INITIAL_BALANCE
    serialized_payer_account = payer_account.SerializeToString()

    owner_account = Account()
    owner_account.pub_keys.append(RANDOM_ALREADY_STORED_OWNER_PUBLIC_KEY_ADDRESS)
    serialized_owner_account = owner_account.SerializeToString()

    zero_account = Account()
    zero_account.balance = 0
    serialized_zero_account = zero_account.SerializeToString()

    mock_context = StubContext(inputs=inputs, outputs=outputs, initial_state={
        OWNER_ADDRESS: serialized_owner_account,
        PAYER_ADDRESS: serialized_payer_account,
        ZERO_ADDRESS: serialized_zero_account,
    })

    expected_public_key_storage = PubKeyStorage()
    expected_public_key_storage.owner = OWNER_PUBLIC_KEY
    expected_public_key_storage.payload.CopyFrom(new_public_key_payload)
    expected_public_key_storage.is_revoked = False
    expected_serialized_public_key_storage = expected_public_key_storage.SerializeToString()

    expected_payer_account = Account()
    expected_payer_account.balance = PAYER_INITIAL_BALANCE - PUB_KEY_STORE_PRICE
    serialized_expected_payer_account = expected_payer_account.SerializeToString()

    expected_owner_account = Account()
    expected_owner_account.pub_keys.append(RANDOM_ALREADY_STORED_OWNER_PUBLIC_KEY_ADDRESS)
    expected_owner_account.pub_keys.append(ADDRESS_FROM_ECDSA_PUBLIC_KEY)
    serialized_expected_owner_account = expected_owner_account.SerializeToString()

    expected_zero_account = Account()
    expected_zero_account.balance = 0 + PUB_KEY_STORE_PRICE
    expected_serialized_zero_account = expected_zero_account.SerializeToString()

    expected_state = {
        OWNER_ADDRESS: serialized_expected_owner_account,
        PAYER_ADDRESS: serialized_expected_payer_account,
        ADDRESS_FROM_ECDSA_PUBLIC_KEY: expected_serialized_public_key_storage,
        ZERO_ADDRESS: expected_serialized_zero_account,
    }

    PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    state_as_list = mock_context.get_state(addresses=[
        OWNER_ADDRESS, PAYER_ADDRESS, ADDRESS_FROM_ECDSA_PUBLIC_KEY, ZERO_ADDRESS,
    ])

    state_as_dict = {entry.address: entry.data for entry in state_as_list}

    assert expected_state == state_as_dict