Exemple #1
0
 def _rlptx_to_txobject(self, rlp_data: bytes) -> TxObject:
     """
     Transform an rlp encoded byte array transaction to a transaction object
     """
     # decode the rlp
     raw = rlp.decode(rlp_data)
     tag = _int_decode(raw[0])
     vsn = _int_decode(raw[1])
     # TODO: verify that the schema is there
     descriptor = tx_descriptors.get((tag, vsn))
     if descriptor is None:
         # the transaction is not defined
         raise TypeError(f"Unknown transaction tag/version: {tag}/{vsn}")
     schema = descriptor.get("schema")
     tx_data = {"tag": tag, "type": idf.TRANSACTION_TAG_TO_TYPE.get(tag)}
     for label, fn in schema.items():
         if fn.field_type == _INT:
             tx_data[label] = _int_decode(raw[fn.index])
         if fn.field_type == _ID:
             tx_data[label] = _id_decode(raw[fn.index])
         elif fn.field_type == _ENC:
             tx_data[label] = encode(fn.encoding_prefix, raw[fn.index])
         elif fn.field_type == _OTTL_TYPE:
             ttl_type = _int_decode(raw[fn.index])
             tx_data[fn.index] = idf.ORACLE_TTL_TYPES_REV.get(ttl_type)
         elif fn.field_type == _SG:
             # signatures are always a list
             tx_data[label] = [
                 encode(idf.SIGNATURE, sg) for sg in raw[fn.index]
             ]
         elif fn.field_type == _VM_ABI:
             vml = len(raw[fn.index])
             # vm/abi are encoded in the same 32bit length block
             tx_data["vm_version"] = _int_decode(raw[fn.index][0:vml - 2])
             tx_data["abi_version"] = _int_decode(raw[fn.index][vml - 2:])
         elif fn.field_type == _BIN:
             # this are byte arrays
             tx_data[label] = _binary_decode(raw[fn.index],
                                             data_type=fn.data_type)
         elif fn.field_type == _PTR:
             # this are name pointers
             tx_data[label] = [{
                 "key": _binary_decode(p[0], data_type=str),
                 "id": _id_decode(p[1])
             } for p in raw[fn.index]]
         elif fn.field_type == _TX:
             # this can be raw or tx object
             tx_data[label] = self._rlptx_to_txobject(raw[fn.index])
     # re-encode the decode object
     compute_hash = True if tag == idf.OBJECT_TAG_SIGNED_TRANSACTION else False
     return self._txdata_to_txobject(tx_data,
                                     descriptor,
                                     compute_hash=compute_hash)
 def encode_signed_transaction(self, transaction, signature):
     """prepare a signed transaction message"""
     tag = bytes([idf.OBJECT_TAG_SIGNED_TRANSACTION])
     vsn = bytes([idf.VSN])
     encoded_signed_tx = encode_rlp(idf.TRANSACTION, [tag, vsn, [signature], transaction])
     encoded_signature = encode(idf.SIGNATURE, signature)
     return encoded_signed_tx, encoded_signature
Exemple #3
0
 def tx_spend(self, sender_id, recipient_id, amount, payload, fee, ttl,
              nonce) -> TxObject:
     """
     create a spend transaction
     :param sender_id: the public key of the sender
     :param recipient_id: the public key of the recipient
     :param amount: the amount to send
     :param payload: the payload associated with the data
     :param fee: the fee for the transaction
     :param ttl: the absolute ttl of the transaction
     :param nonce: the nonce of the transaction
     """
     # use internal endpoints transaction
     body = dict(
         tag=idf.OBJECT_TAG_SPEND_TRANSACTION,
         version=idf.VSN,
         recipient_id=recipient_id,
         amount=amount,
         fee=fee,
         sender_id=sender_id,
         payload=encode(idf.BYTE_ARRAY, payload),
         ttl=ttl,
         nonce=nonce,
     )
     return self._build_txobject(body)
Exemple #4
0
 def encode_signed_transaction(self, transaction, signature):
     """prepare a signed transaction message"""
     tag = bytes([OBJECT_TAG_SIGNED_TRANSACTION])
     vsn = bytes([VSN])
     encoded_signed_tx = hashing.encode_rlp(
         "tx", [tag, vsn, [signature], transaction])
     encoded_signature = hashing.encode("sg", signature)
     return encoded_signed_tx, encoded_signature
 def _txdata_to_txobject(self, data: dict, descriptor: dict, metadata: dict = {}, compute_hash=True) -> TxObject:
     # initialize the right data size
     # this is PYTHON to POSTBODY
     schema = descriptor.get("schema", [])
     raw_data = [0] * (len(schema) + 1)  # the +1 is for the tag
     # set the tx tag first
     raw_data[0] = _int(data.get("tag"))
     # parse fields and encode them
     for label, fn in schema.items():
         if fn.field_type == _INT:
             raw_data[fn.index] = _int(data.get(label, 0))
         elif fn.field_type == _ID:
             raw_data[fn.index] = _id(data.get(label))
         elif fn.field_type == _ENC:
             raw_data[fn.index] = decode(data.get(label))
         elif fn.field_type == _OTTL_TYPE:
             raw_data[fn.index] = _int(idf.ORACLE_TTL_TYPES.get(data.get(label)))
         elif fn.field_type == _SG:
             # signatures are always a list
             raw_data[fn.index] = [decode(sg) for sg in data.get(label, [])]
         elif fn.field_type == _VM_ABI:
             # vm/abi are encoded in the same 32bit length block
             raw_data[fn.index] = _int(data.get("vm_version")) + _int(data.get("abi_version"), 2)
         elif fn.field_type == _BIN:
             # this are binary string #TODO: may be byte array
             raw_data[fn.index] = _binary(data.get(label))
         elif fn.field_type == _PTR:
             # this are name pointers
             raw_data[fn.index] = [[_binary(p.get("key")), _id(p.get("id"))] for p in data.get(label, [])]
         elif fn.field_type == _TX:
             # this can be raw or tx object
             tx = data.get(label).tx if hasattr(data.get(label), "tx") else data.get(label)
             raw_data[fn.index] = decode(tx)
     # encode the transaction in rlp
     rlp_tx = rlp.encode(raw_data)
     # encode the tx in base64
     rlp_b64_tx = encode(idf.TRANSACTION, rlp_tx)
     # copy the data before modifying
     tx_data = copy.deepcopy(data)
     # build the tx object
     txo = TxObject(
         data=namedtupled.map(tx_data, _nt_name="TxData"),
         tx=rlp_b64_tx,
     )
     # compute the tx hash
     if compute_hash:
         txo.hash = hash_encode(idf.TRANSACTION_HASH, rlp_tx)
     # copy the metadata if exists or initialize it if None
     tx_meta = copy.deepcopy(metadata) if metadata is not None else {}
     # compute the minimum fee
     if descriptor.get("fee") is not None:
         tx_meta["min_fee"] = self.compute_min_fee(data, descriptor, raw_data)
     # only set the metadata if it is not empty
     txo.set_metadata(tx_meta)
     return txo
Exemple #6
0
def signed_tx_to_obj(tx_str):
    tx = hashing.decode_rlp(tx_str)

    if hashing._int_decode(tx[0]) != 11:
        raise Exception("invalid tag")

    if len(tx) != 4:
        raise Exception("invalid tx")

    return transactions._tx_native(op=transactions.UNPACK_TX,
                                   tx=hashing.encode("tx", tx[3]))
 def sign_transaction(self, transaction: TxObject, metadata: dict = None) -> str:
     """
     Sign, encode and compute the hash of a transaction
     :param tx: the TxObject to be signed
     :param metadata: additional data to include in the output of the signed transaction object
     :return: encoded_signed_tx, encoded_signature, tx_hash
     """
     # get the transaction as byte list
     tx_raw = decode(transaction.tx)
     # sign the transaction
     signature = self.account.sign(_binary(self.network_id) + tx_raw)
     # pack and encode the transaction
     return encode(idf.SIGNATURE, signature)
Exemple #8
0
 def __init__(self, signing_key, verifying_key, **kwargs):
     # distinguish from poa / ga
     # TODO: handle the case that they are not set
     self.nonce = kwargs.get("nonce", 0)
     self.balance = kwargs.get("balance", 0)
     self.kind = kwargs.get("kind", ACCOUNT_KIND_BASIC)
     self.contract_id = kwargs.get("contract_id")
     self.auth_fun = kwargs.get("auth_fun")
     self.address = kwargs.get("id")
     self.signing_key = signing_key
     self.verifying_key = verifying_key
     if verifying_key is not None:
         pub_key = self.verifying_key.encode(encoder=RawEncoder)
         self.address = hashing.encode(ACCOUNT_ID, pub_key)
Exemple #9
0
    def sign_transaction(self,
                         transaction: TxObject,
                         metadata: dict = None) -> str:
        """
        Sign, encode and compute the hash of a transaction

        Args:
            tx (TxObject): the TxObject to be signed

        Returns:
            the encoded and prefixed signature
        """
        # get the transaction as byte list
        tx_raw = decode(transaction.tx)
        # sign the transaction
        signature = self.account.sign(_binary(self.network_id) + tx_raw)
        # pack and encode the transaction
        return encode(idf.SIGNATURE, signature)
def test_hashing_base58_encode():

    inputs = [
        {
            "data": "test".encode("utf-8"),
            "prefix": "tt",
            "hash": "LUC1eAJa5jW",
            "match": True,
            "raise_error": False,
        },
        {
            "data": "test".encode("utf-8"),
            "prefix": "tt",
            "hash": "LUC1eAJa",
            "match": False,
            "raise_error": True,

        },
        {
            "data": "aeternity".encode("utf-8"),
            "prefix": "aa",
            "hash": "97Wv2fcowb3y3qVnDC",
            "match": True,
            "raise_error": False,
        },
    ]

    for i in inputs:
        try:
            h = hashing._base58_encode(i.get("data"))
            assert (h == i.get("hash")) is i.get("match")
            e = hashing.encode(i.get("prefix"), i.get("data"))
            assert (e == f'{i.get("prefix")}_{i.get("hash")}') is i.get("match")
            o = hashing._base58_decode(i.get("hash"))
            assert (o == i.get("data")) is i.get("match")
        except Exception as e:
            assert i.get("raise_error") is True
def test_evm_encode_calldata():
    contract = EPOCH_CLI.Contract(aer_identity_contract, abi=Contract.EVM)
    result = contract.encode_calldata('main', '1')
    assert result is not None
    assert result == hashing.encode('cb', 'main1')
Exemple #12
0
 def __init__(self, signing_key, verifying_key):
     self.signing_key = signing_key
     self.verifying_key = verifying_key
     pub_key = self.verifying_key.encode(encoder=RawEncoder)
     self.address = hashing.encode("ak", pub_key)
Exemple #13
0
def _tx_native(op, **kwargs):

    def std_fee(tx_raw, fee_idx, base_gas_multiplier=1):
        # calculates the standard minimum transaction fee
        tx_copy = tx_raw  # create a copy of the input
        tx_copy[fee_idx] = _int(0, 8)  # replace fee with a byte array of lenght 8
        return (defaults.BASE_GAS * base_gas_multiplier + len(rlp.encode(tx_copy)) * defaults.GAS_PER_BYTE) * defaults.GAS_PRICE

    def contract_fee(tx_raw, fee_idx, gas, base_gas_multiplier=1):
        # estimate the contract creation fee
        tx_copy = tx_raw  # create a copy of the input
        tx_copy[fee_idx] = _int(0, 8)  # replace fee with a byte array of lenght 8
        return (defaults.BASE_GAS * base_gas_multiplier + gas + len(rlp.encode(tx_copy)) * defaults.GAS_PER_BYTE) * defaults.GAS_PRICE

    def oracle_fee(tx_raw, fee_idx, relative_ttl):
        # estimate oracle fees
        tx_copy = tx_raw  # create a copy of the input
        tx_copy[fee_idx] = _int(0, 8)  # replace fee with a byte array of lenght 8
        fee = (defaults.BASE_GAS + len(rlp.encode(tx_copy)) * defaults.GAS_PER_BYTE)
        fee += math.ceil(32000 * relative_ttl / math.floor(60 * 24 * 365 / defaults.KEY_BLOCK_INTERVAL))
        return fee * defaults.GAS_PRICE

    def build_tx_object(tx_data, tx_raw, fee_idx, min_fee):
        if tx_data.get("fee") < min_fee:
            tx_native[fee_idx] = _int(min_fee)
            tx_data["fee"] = min_fee
        tx_encoded = encode_rlp(idf.TRANSACTION, tx_native)
        tx = dict(
            data=tx_data,
            tx=tx_encoded,
            hash=TxBuilder.compute_tx_hash(tx_encoded),
        )
        return namedtupled.map(tx, _nt_name="TxObject")

    # prepare tag and version
    if op == PACK_TX:
        tag = kwargs.get("tag", 0)
        vsn = kwargs.get("vsn", 1)
        tx_data = kwargs
    elif op == UNPACK_TX:
        tx_native = decode_rlp(kwargs.get("tx", []))
        tag = _int_decode(tx_native[0])
    else:
        raise Exception("Invalid operation")

    # check the tags
    if tag == idf.OBJECT_TAG_SPEND_TRANSACTION:
        tx_field_fee_index = 5
        if op == PACK_TX:  # pack transaction
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("sender_id")),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("recipient_id")),
                _int(kwargs.get("amount")),
                _int(kwargs.get("fee")),  # index 5
                _int(kwargs.get("ttl")),
                _int(kwargs.get("nonce")),
                _binary(kwargs.get("payload"))
            ]
            min_fee = std_fee(tx_native, tx_field_fee_index)
        elif op == UNPACK_TX:  # unpack transaction
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                sender_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                recipient_id=encode(idf.ACCOUNT_ID, tx_native[3][1:]),
                amount=_int_decode(tx_native[4]),
                fee=_int_decode(tx_native[5]),
                ttl=_int_decode(tx_native[6]),
                nonce=_int_decode(tx_native[7]),
                payload=_binary_decode(tx_native[8]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)
    elif tag == idf.OBJECT_TAG_NAME_SERVICE_PRECLAIM_TRANSACTION:
        tx_field_fee_index = 5
        if op == PACK_TX:  # pack transaction
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("account_id")),
                _int(kwargs.get("nonce")),
                _id(idf.ID_TAG_COMMITMENT, kwargs.get("commitment_id")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl"))
            ]
            min_fee = std_fee(tx_native, tx_field_fee_index)
        elif op == UNPACK_TX:  # unpack transaction
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                account_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                commitment_id=encode(idf.COMMITMENT, tx_native[4][1:]),
                fee=_int_decode(tx_native[5]),
                ttl=_int_decode(tx_native[6]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_NAME_SERVICE_CLAIM_TRANSACTION:
        tx_field_fee_index = 6
        if op == PACK_TX:  # pack transaction
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("account_id")),
                _int(kwargs.get("nonce")),
                decode(kwargs.get("name")),
                _binary(kwargs.get("name_salt")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl"))
            ]
            min_fee = std_fee(tx_native, tx_field_fee_index)
        elif op == UNPACK_TX:  # unpack transaction
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                account_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                name=_binary_decode(tx_native[4], str),
                name_salt=_binary_decode(tx_native[5], int),
                fee=_int_decode(tx_native[6]),
                ttl=_int_decode(tx_native[7]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_NAME_SERVICE_UPDATE_TRANSACTION:
        tx_field_fee_index = 8
        if op == PACK_TX:  # pack transaction
            # first asseble the pointers
            def pointer_tag(pointer):
                return {
                    "account_pubkey": idf.ID_TAG_ACCOUNT,
                    "oracle_pubkey": idf.ID_TAG_ORACLE,
                    "contract_pubkey": idf.ID_TAG_CONTRACT,
                    "channel_pubkey": idf.ID_TAG_CHANNEL
                }.get(pointer.get("key"))
            ptrs = [[_binary(p.get("key")), _id(pointer_tag(p), p.get("id"))] for p in kwargs.get("pointers", [])]
            # then build the transaction
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("account_id")),
                _int(kwargs.get("nonce")),
                _id(idf.ID_TAG_NAME, kwargs.get("name_id")),
                _int(kwargs.get("name_ttl")),
                ptrs,
                _int(kwargs.get("client_ttl")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl"))
            ]
            min_fee = std_fee(tx_native, tx_field_fee_index)
        elif op == UNPACK_TX:  # unpack transaction
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                account_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                name=encode(idf.NAME, tx_native[4][1:]),
                name_ttl=_int_decode(tx_native[5]),
                pointers=[],  # TODO: decode pointers
                client_ttl=_int_decode(tx_native[7]),
                fee=_int_decode(tx_native[8]),
                ttl=_int_decode(tx_native[9]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_NAME_SERVICE_TRANSFER_TRANSACTION:
        tx_field_fee_index = 6
        if op == PACK_TX:  # pack transaction
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("account_id")),
                _int(kwargs.get("nonce")),
                _id(idf.ID_TAG_NAME, kwargs.get("name_id")),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("recipient_id")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl")),
            ]
            min_fee = std_fee(tx_native, tx_field_fee_index)
        elif op == UNPACK_TX:  # unpack transaction
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                account_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                name=encode(idf.NAME, tx_native[4][1:]),
                recipient_id=encode(idf.ACCOUNT_ID, tx_native[5][1:]),
                fee=_int_decode(tx_native[6]),
                ttl=_int_decode(tx_native[7]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_NAME_SERVICE_REVOKE_TRANSACTION:
        tx_field_fee_index = 5
        if op == PACK_TX:  # pack transaction
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("account_id")),
                _int(kwargs.get("nonce")),
                _id(idf.ID_TAG_NAME, kwargs.get("name_id")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl")),
            ]
            min_fee = std_fee(tx_native, tx_field_fee_index)
        elif op == UNPACK_TX:  # unpack transaction
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                account_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                name=encode(idf.NAME, tx_native[4][1:]),
                fee=_int_decode(tx_native[5]),
                ttl=_int_decode(tx_native[6]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_CONTRACT_CREATE_TRANSACTION:
        tx_field_fee_index = 6
        if op == PACK_TX:  # pack transaction
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("owner_id")),
                _int(kwargs.get("nonce")),
                _binary(decode(kwargs.get("code"))),
                _int(kwargs.get("vm_version")) + _int(kwargs.get("abi_version"), 2),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl")),
                _int(kwargs.get("deposit")),
                _int(kwargs.get("amount")),
                _int(kwargs.get("gas")),
                _int(kwargs.get("gas_price")),
                _binary(decode(kwargs.get("call_data"))),
            ]
            # TODO: verify the fee caluclation for the contract
            min_fee = contract_fee(tx_native, tx_field_fee_index, kwargs.get("gas"),  base_gas_multiplier=5)
        elif op == UNPACK_TX:  # unpack transaction
            vml = len(tx_native[5])  # this is used to extract the abi and vm version from the 5th field
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                owner_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                code=encode(idf.BYTECODE, tx_native[4][1:]),
                vm_version=_int_decode(tx_native[5][0:vml - 2]),
                abi_version=_int_decode(tx_native[5][vml - 2:]),
                fee=_int_decode(tx_native[6]),
                ttl=_int_decode(tx_native[7]),
                deposit=_int_decode(tx_native[8]),
                amount=_int_decode(tx_native[9]),
                gas=_int_decode(tx_native[10]),
                gas_price=_int_decode(tx_native[11]),
                call_data=encode(idf.BYTECODE, tx_native[12][1:]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_CONTRACT_CALL_TRANSACTION:
        tx_field_fee_index = 6
        if op == PACK_TX:  # pack transaction
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("caller_id")),
                _int(kwargs.get("nonce")),
                _id(idf.ID_TAG_CONTRACT, kwargs.get("contract_id")),
                _int(kwargs.get("abi_version")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl")),
                _int(kwargs.get("amount")),
                _int(kwargs.get("gas")),
                _int(kwargs.get("gas_price")),
                _binary(decode(kwargs.get("call_data"))),
            ]
            min_fee = contract_fee(tx_native, tx_field_fee_index, kwargs.get("gas"),  base_gas_multiplier=30)
        elif op == UNPACK_TX:  # unpack transaction
            vml = len(tx_native[5])  # this is used to extract the abi and vm version from the 5th field
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                caller_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                contract_id=encode(idf.CONTRACT_ID, tx_native[4][1:]),
                abi_version=_int_decode(tx_native[5]),
                fee=_int_decode(tx_native[6]),
                ttl=_int_decode(tx_native[7]),
                amount=_int_decode(tx_native[8]),
                gas=_int_decode(tx_native[9]),
                gas_price=_int_decode(tx_native[10]),
                call_data=encode(idf.BYTECODE, tx_native[11][1:]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_CHANNEL_CREATE_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("initiator")),
            _int(kwargs.get("initiator_amount")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("responder")),
            _int(kwargs.get("responder_amount")),
            _int(kwargs.get("channel_reserve")),
            _int(kwargs.get("lock_period")),
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            # _[id(delegate_ids)], TODO: handle delegate ids
            _binary(kwargs.get("state_hash")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 9
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_CHANNEL_DEPOSIT_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_CHANNEL, kwargs.get("channel_id")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("from_id")),
            _int(kwargs.get("amount")),
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            _binary(kwargs.get("state_hash")),
            _int(kwargs.get("round")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 6
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_CHANNEL_WITHDRAW_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_CHANNEL, kwargs.get("channel_id")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("to_id")),
            _int(kwargs.get("amount")),
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            _binary(kwargs.get("state_hash")),
            _int(kwargs.get("round")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 6
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_CHANNEL_CLOSE_MUTUAL_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_CHANNEL, kwargs.get("channel_id")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("from_id")),
            _int(kwargs.get("initiator_amount_final")),
            _int(kwargs.get("responder_amount_final")),
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 7
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_CHANNEL_CLOSE_SOLO_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_CHANNEL, kwargs.get("channel_id")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("from_id")),
            _binary(kwargs.get("payload")),
            # _poi(kwargs.get("poi")), TODO: implement support for _poi
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 7
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_CHANNEL_SLASH_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_CHANNEL, kwargs.get("channel_id")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("from_id")),
            _binary(kwargs.get("payload")),
            # _poi(kwargs.get("poi")), TODO: implement support for _poi
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 7
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_CHANNEL_SETTLE_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_CHANNEL, kwargs.get("channel_id")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("from_id")),
            _int(kwargs.get("initiator_amount_final")),
            _int(kwargs.get("responder_amount_final")),
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 7
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_CHANNEL_SNAPSHOT_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_CHANNEL, kwargs.get("channel_id")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("from_id")),
            _binary(kwargs.get("payload")),
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 6
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_CHANNEL_FORCE_PROGRESS_TRANSACTION:
        tx_native = [
            _int(tag),
            _int(vsn),
            _id(idf.ID_TAG_CHANNEL, kwargs.get("channel_id")),
            _id(idf.ID_TAG_ACCOUNT, kwargs.get("from_id")),
            _binary(kwargs.get("payload")),
            _int(kwargs.get("round")),
            _binary(kwargs.get("update")),
            _binary(kwargs.get("state_hash")),
            # _trees(kwargs.get("offchain_trees")), TODO: implement support for _trees
            _int(kwargs.get("ttl")),
            _int(kwargs.get("fee")),
            _int(kwargs.get("nonce")),
        ]
        tx_field_fee_index = 9
        min_fee = std_fee(tx_native, tx_field_fee_index)
    elif tag == idf.OBJECT_TAG_ORACLE_REGISTER_TRANSACTION:
        tx_field_fee_index = 9
        if op == PACK_TX:  # pack transaction
            oracle_ttl = kwargs.get("oracle_ttl", {})
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("account_id")),
                _int(kwargs.get("nonce")),
                _binary(kwargs.get("query_format")),
                _binary(kwargs.get("response_format")),
                _int(kwargs.get("query_fee")),
                _int(0 if oracle_ttl.get("type") == idf.ORACLE_TTL_TYPE_DELTA else 1),
                _int(oracle_ttl.get("value")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl")),
                _int(kwargs.get("vm_version")),
            ]
            min_fee = oracle_fee(tx_native, tx_field_fee_index, oracle_ttl.get("value"))
        elif op == UNPACK_TX:  # unpack transaction
            vml = len(tx_native[5])  # this is used to extract the abi and vm version from the 5th field
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                account_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                query_format=_binary_decode(tx_native[4]),
                response_format=_binary_decode(tx_native[5]),
                query_fee=_int_decode(tx_native[6]),
                oracle_ttl=dict(
                    type=idf.ORACLE_TTL_TYPE_DELTA if _int_decode(tx_native[7]) else idf.ORACLE_TTL_TYPE_BLOCK,
                    value=_int_decode(tx_native[8]),
                ),
                fee=_int_decode(tx_native[9]),
                ttl=_int_decode(tx_native[10]),
                vm_version=_int_decode(tx_native[11]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_ORACLE_QUERY_TRANSACTION:
        tx_field_fee_index = 11
        if op == PACK_TX:  # pack transaction
            query_ttl = kwargs.get("query_ttl", {})
            response_ttl = kwargs.get("response_ttl", {})
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ACCOUNT, kwargs.get("sender_id")),
                _int(kwargs.get("nonce")),
                _id(idf.ID_TAG_ORACLE, kwargs.get("oracle_id")),
                _binary(kwargs.get("query")),
                _int(kwargs.get("query_fee")),
                _int(0 if query_ttl.get("type") == idf.ORACLE_TTL_TYPE_DELTA else 1),
                _int(query_ttl.get("value")),
                _int(0 if response_ttl.get("type") == idf.ORACLE_TTL_TYPE_DELTA else 1),
                _int(response_ttl.get("value")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl")),
            ]
            min_fee = oracle_fee(tx_native, tx_field_fee_index, query_ttl.get("value"))
        elif op == UNPACK_TX:  # unpack transaction
            vml = len(tx_native[5])  # this is used to extract the abi and vm version from the 5th field
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                sender_id=encode(idf.ACCOUNT_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                oracle_id=encode(idf.ORACLE_ID, tx_native[4][1:]),
                query=_binary_decode(tx_native[5]),
                query_fee=_int_decode(tx_native[6]),
                query_ttl=dict(
                    type=idf.ORACLE_TTL_TYPE_DELTA if _int_decode(tx_native[7]) else idf.ORACLE_TTL_TYPE_BLOCK,
                    value=_int_decode(tx_native[8]),
                ),
                response_ttl=dict(
                    type=idf.ORACLE_TTL_TYPE_DELTA if _int_decode(tx_native[9]) else idf.ORACLE_TTL_TYPE_BLOCK,
                    value=_int_decode(tx_native[10]),
                ),
                fee=_int_decode(tx_native[11]),
                ttl=_int_decode(tx_native[12]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_ORACLE_RESPONSE_TRANSACTION:
        tx_field_fee_index = 8
        if op == PACK_TX:  # pack transaction
            response_ttl = kwargs.get("response_ttl", {})
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ORACLE, kwargs.get("oracle_id")),
                _int(kwargs.get("nonce")),
                decode(kwargs.get("query_id")),
                _binary(kwargs.get("response")),
                _int(0 if response_ttl.get("type") == idf.ORACLE_TTL_TYPE_DELTA else 1),
                _int(response_ttl.get("value")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl")),
            ]
            min_fee = oracle_fee(tx_native, tx_field_fee_index, response_ttl.get("value"))
        elif op == UNPACK_TX:  # unpack transaction
            vml = len(tx_native[5])  # this is used to extract the abi and vm version from the 5th field
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                oracle_id=encode(idf.ORACLE_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                query_id=encode(idf.ORACLE_QUERY_ID, tx_native[4][1:]),
                response=_binary(tx_native[5]),
                response_ttl=dict(
                    type=idf.ORACLE_TTL_TYPE_DELTA if _int_decode(tx_native[6]) else idf.ORACLE_TTL_TYPE_BLOCK,
                    value=_int_decode(tx_native[7]),
                ),
                fee=_int_decode(tx_native[8]),
                ttl=_int_decode(tx_native[9]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)

    elif tag == idf.OBJECT_TAG_ORACLE_EXTEND_TRANSACTION:
        tx_field_fee_index = 6
        if op == PACK_TX:  # pack transaction
            oracle_ttl = kwargs.get("oracle_ttl", {})
            tx_native = [
                _int(tag),
                _int(vsn),
                _id(idf.ID_TAG_ORACLE, kwargs.get("oracle_id")),
                _int(kwargs.get("nonce")),
                _int(0 if oracle_ttl.get("type", {}) == idf.ORACLE_TTL_TYPE_DELTA else 1),
                _int(oracle_ttl.get("value")),
                _int(kwargs.get("fee")),
                _int(kwargs.get("ttl")),
            ]
            min_fee = oracle_fee(tx_native, tx_field_fee_index, oracle_ttl.get("value"))
        elif op == UNPACK_TX:  # unpack transaction
            vml = len(tx_native[5])  # this is used to extract the abi and vm version from the 5th field
            tx_data = dict(
                tag=tag,
                vsn=_int_decode(tx_native[1]),
                oracle_id=encode(idf.ORACLE_ID, tx_native[2][1:]),
                nonce=_int_decode(tx_native[3]),
                oracle_ttl=dict(
                    type=idf.ORACLE_TTL_TYPE_DELTA if _int_decode(tx_native[4]) else idf.ORACLE_TTL_TYPE_BLOCK,
                    value=_int_decode(tx_native[5]),
                ),
                fee=_int_decode(tx_native[6]),
                ttl=_int_decode(tx_native[7]),
            )
            min_fee = tx_data.get("fee")
        else:
            raise Exception("Invalid operation")
        return build_tx_object(tx_data, tx_native, tx_field_fee_index, min_fee)
    else:
        raise UnsupportedTransactionType(f"Unusupported transaction tag {tag}")
Exemple #14
0
def _test_oracle_response(query, expected):
    r = query.get_response_object()
    assert r.oracle_id == query.oracle_id
    assert r.id == query.id
    assert r.response == hashing.encode("or", expected)
Exemple #15
0
 def __init__(self, signing_key, verifying_key):
     self.signing_key = signing_key
     self.verifying_key = verifying_key
     pub_key = self.verifying_key.encode(encoder=RawEncoder)
     self.address = hashing.encode(ACCOUNT_ID, pub_key)
     self.nonce = 0
Exemple #16
0
 def _encode_name(cls, name):
     if isinstance(name, str):
         name = name.encode('ascii')
     return hashing.encode('nm', name)