Esempio n. 1
0
    def populate(message: Message, signatures: List[bytes]) -> Transaction:
        """Populate Transaction object from message and signatures.

        Example:

            >>> raw_message = bytes.fromhex(
            ...     '0200030500000000000000000000000000000000000000000000'
            ...     '0000000000000000000100000000000000000000000000000000'
            ...     '0000000000000000000000000000000200000000000000000000'
            ...     '0000000000000000000000000000000000000000000300000000'
            ...     '0000000000000000000000000000000000000000000000000000'
            ...     '0004000000000000000000000000000000000000000000000000'
            ...     '0000000000000005c49ae77603782054f17a9decea43b444eba0'
            ...     'edb12c6f1d31c6e0e4a84bf052eb010403010203050909090909'
            ... )
            >>> from based58 import b58encode
            >>> from solana.message import Message
            >>> msg = Message.deserialize(raw_message)
            >>> signatures = [b58encode(bytes([1] * SIG_LENGTH)), b58encode(bytes([2] * SIG_LENGTH))]
            >>> type(Transaction.populate(msg, signatures))
            <class 'solana.transaction.Transaction'>

        Returns:
            The populated transaction.
        """
        transaction = Transaction(recent_blockhash=message.recent_blockhash)

        for idx, sig in enumerate(signatures):
            signature = None if sig == b58encode(
                Transaction.__DEFAULT_SIG) else b58decode(sig)
            transaction.signatures.append(
                SigPubkeyPair(pubkey=message.account_keys[idx],
                              signature=signature))

        for instr in message.instructions:
            account_metas: List[AccountMeta] = []
            for acc_idx in instr.accounts:
                pubkey = message.account_keys[acc_idx]
                is_signer = any((pubkey == sigkeypair.pubkey
                                 for sigkeypair in transaction.signatures))
                account_metas.append(
                    AccountMeta(
                        pubkey=pubkey,
                        is_signer=is_signer,
                        is_writable=message.is_account_writable(acc_idx)))
            program_id = message.account_keys[instr.program_id_index]
            transaction.instructions.append(
                TransactionInstruction(keys=account_metas,
                                       program_id=program_id,
                                       data=b58decode(instr.data)))

        return transaction
Esempio n. 2
0
def test_decode_nonce_account_data():
    b64_data = (
        "AAAAAAEAAADbpRzeSWD3B/Ei2SfSmwM6qTDlK5pCxRlx3Vsnr3+v14Bbu3aJmuW0cG"
        "J2BVvh7C9g5qNUM+I200HP5eSQ8MHBiBMAAAAAAAA=")

    raw_data = b64decode(b64_data)
    parsed = VERSIONS_LAYOUT.parse(raw_data)

    assert parsed.state.data.authority == b58decode(
        b"FnQK7qe8rkD3x2GrA8ERptTd7bp7KwqouvaQYtr1uuaE")
    assert parsed.state.data.blockhash == b58decode(
        b"9e4KCe4NTbA87aUVugjo6Yb1EVittdxy1RQu6AELCTL4")
    assert parsed.state.data.fee_calculator.lamports_per_signature == 5000
Esempio n. 3
0
 def __encode_instruction(
     instruction: "CompiledInstruction",
 ) -> bytes:  # TODO: Replace this with a construct struct.
     InstructionFormat = NamedTuple(
         "InstructionFormat",
         [
             ("program_idx", bytes),
             ("accounts_length", bytes),
             ("accounts", bytes),
             ("data_length", bytes),
             ("data", bytes),
         ],
     )
     data = b58decode(instruction.data)
     data_length = shortvec.encode_length(len(data))
     return b"".join(
         InstructionFormat(
             program_idx=helpers.to_uint8_bytes(
                 instruction.program_id_index),
             accounts_length=shortvec.encode_length(
                 len(instruction.accounts)),
             accounts=bytes(instruction.accounts),
             data_length=data_length,
             data=data,
         ))
Esempio n. 4
0
 def __encode_message(
         self) -> bytes:  # TODO: Replace this with a construct struct.
     MessageFormat = NamedTuple(
         "MessageFormat",
         [
             ("num_required_signatures", bytes),
             ("num_readonly_signed_accounts", bytes),
             ("num_readonly_unsigned_accounts", bytes),
             ("pubkeys_length", bytes),
             ("pubkeys", bytes),
             ("recent_blockhash", bytes),
         ],
     )
     return b"".join(
         MessageFormat(
             num_required_signatures=helpers.to_uint8_bytes(
                 self.header.num_required_signatures),
             num_readonly_signed_accounts=helpers.to_uint8_bytes(
                 self.header.num_readonly_signed_accounts),
             num_readonly_unsigned_accounts=helpers.to_uint8_bytes(
                 self.header.num_readonly_unsigned_accounts),
             pubkeys_length=shortvec.encode_length(len(self.account_keys)),
             pubkeys=b"".join(
                 [bytes(pubkey) for pubkey in self.account_keys]),
             recent_blockhash=b58decode(
                 self.recent_blockhash.encode("ascii")),
         ))
Esempio n. 5
0
def test_account_keypair():
    """Validate account keypair against account's private and public key."""
    expected_account = Account()
    keypair = expected_account.keypair()
    decoded_keypair = b58decode(keypair)

    actual_account = Account(decoded_keypair[:32])
    assert expected_account.public_key() == actual_account.public_key()
    assert expected_account.secret_key() == actual_account.secret_key()
Esempio n. 6
0
def decode_byte_string(byte_string: str, encoding: str = "base64") -> bytes:
    """Decode an encoded string from an RPC Response."""
    b_str = str.encode(byte_string)
    if encoding == "base64":
        return b64decode(b_str)
    if encoding == "base58":
        return b58decode(b_str)

    raise NotImplementedError(f"{encoding} decoding not currently supported.")
Esempio n. 7
0
    def _get_signature_statuses_args(
        signatures: List[Union[str, bytes]], search_transaction_history: bool
    ) -> Tuple[types.RPCMethod, List[str], Dict[str, bool]]:
        base58_sigs: List[str] = []
        for sig in signatures:
            if isinstance(sig, str):
                base58_sigs.append(
                    b58encode(b58decode(sig.encode("ascii"))).decode("utf-8"))
            else:
                base58_sigs.append(b58encode(sig).decode("utf-8"))

        return (
            types.RPCMethod("getSignatureStatuses"),
            base58_sigs,
            {
                "searchTransactionHistory": search_transaction_history
            },
        )
Esempio n. 8
0
    def __init__(self, value: Union[bytearray, bytes, int, str, List[int],
                                    VerifyKey]):
        """Init PublicKey object."""
        self._key: Optional[bytes] = None
        if isinstance(value, str):
            try:
                self._key = b58decode(value.encode("ascii"))
            except ValueError as err:
                raise ValueError("invalid public key input:", value) from err
            if len(self._key) != self.LENGTH:
                raise ValueError("invalid public key input:", value)
        elif isinstance(value, int):
            self._key = bytes([value])
        else:
            self._key = bytes(value)

        if len(self._key) > self.LENGTH:
            raise ValueError("invalid public key input:", value)