Example #1
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,
         ))
Example #2
0
    def serialize(self) -> bytes:
        """Serialize message to bytes.

        >>> from solana.blockhash import Blockhash
        >>> account_keys = [str(PublicKey(i + 1)) for i in range(5)]
        >>> msg = Message(
        ...     MessageArgs(
        ...         account_keys=account_keys,
        ...         header=MessageHeader(
        ...             num_readonly_signed_accounts=0, num_readonly_unsigned_accounts=3, num_required_signatures=2
        ...         ),
        ...         instructions=[
        ...             CompiledInstruction(accounts=[1, 2, 3], data=b58encode(bytes([9] * 5)), program_id_index=4)],
        ...         recent_blockhash=Blockhash("EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k"),
        ...     )
        ... )
        >>> msg.serialize().hex()
        '0200030500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000005c49ae77603782054f17a9decea43b444eba0edb12c6f1d31c6e0e4a84bf052eb010403010203050909090909'
        """  # pylint: disable=line-too-long
        message_buffer = bytearray()
        # Message body
        message_buffer.extend(self.__encode_message())
        # Instructions
        instruction_count = shortvec.encode_length(len(self.instructions))
        message_buffer.extend(instruction_count)
        for instr in self.instructions:
            message_buffer.extend(Message.__encode_instruction(instr))
        return bytes(message_buffer)
Example #3
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")),
         ))
Example #4
0
    def __serialize(self, signed_data: bytes) -> bytes:
        if len(self.signatures) >= SIG_LENGTH * 4:
            raise AttributeError("too many singatures to encode")
        wire_transaction = bytearray()
        # Encode signature count
        signature_count = shortvec.encode_length(len(self.signatures))
        wire_transaction.extend(signature_count)
        # Encode signatures
        for sig_pair in self.signatures:
            if sig_pair.signature and len(sig_pair.signature) != SIG_LENGTH:
                raise RuntimeError("signature has invalid length",
                                   sig_pair.signature)

            if not sig_pair.signature:
                wire_transaction.extend(bytearray(SIG_LENGTH))
            else:
                wire_transaction.extend(sig_pair.signature)
        # Encode signed data
        wire_transaction.extend(signed_data)

        if len(wire_transaction) > PACKET_DATA_SIZE:
            raise RuntimeError(
                f"transaction too large: {len(wire_transaction)} > {PACKET_DATA_SIZE}"
            )

        return bytes(wire_transaction)
Example #5
0
def assert_encoded_array(buffer: bytearray, length: int, prev_length: int, expected: List[int]) -> None:
    """Helper to encode length of an array."""
    assert len(buffer) == prev_length
    actual = encode_length(length)
    buffer.extend(actual)
    assert len(buffer) == prev_length + len(expected)
    assert bytes(buffer[-len(expected) :]) == bytes(expected)  # noqa: 203
Example #6
0
def assert_encoded_array(buffer: bytearray, length: int, prev_length: int,
                         expected: List[int]) -> bytearray:
    assert len(buffer) == prev_length
    actual = encode_length(length)
    buffer.extend(actual)
    assert len(buffer) == prev_length + len(expected)
    assert bytes(buffer[-len(expected):]) == bytes(expected)  # noqa: 203
    return buffer