nearprotocolnear

NEAR transaction without receipt but with receipt_outcome


When querying archival node for transactions with EXPERIMENTAL_tx_status method, some transactions have no receipts while having receipts_outcome. How is that possible, and how is that transaction different from others?

If I understand correctly, receipts_outcome are the results of applying receipts. According to explorer, this transaction has Convert Transaction To Receipt part, so there should be some receipts generated.

According to documentation

A Receipt is the only actionable object in the system. When we talk about "processing a transaction" on the NEAR platform, this eventually means "applying receipts" at some point.

A good mental model is to think of a Receipt as a paid message to be executed at the destination (receiver). And a Transaction is an externally issued request to create the Receipt (there is a 1 to 1 relationship).

My query

{
  "jsonrpc": "2.0",
  "id": "2",
  "method": "EXPERIMENTAL_tx_status",
  "params": ["7beNxrbHxMRspJWT9NeEVwx719kVcmY9tRdPG9SYro26", "bumbleee99.near"]
}

Response

{
    "jsonrpc": "2.0",
    "result": {
        "status": {
            "SuccessValue": ""
        },
        "transaction": {
            "signer_id": "bumbleee99.near",
            "public_key": "ed25519:DFM5GRGbpNkk4XkhcFnRUFeKG8a3nzTH8NwZp754pC48",
            "nonce": 59080995000003,
            "receiver_id": "bumbleee99.near",
            "actions": [
                {
                    "AddKey": {
                        "public_key": "ed25519:CUoNs153GHrPZ9F8HpvhzFr1mwuUFUdGQsRNE2CTNjVH",
                        "access_key": {
                            "nonce": 0,
                            "permission": "FullAccess"
                        }
                    }
                }
            ],
            "signature": "ed25519:15v34qoyCHSvSL5uLcaPqD9vXvjcPrCaZVStCMms8e58C62z2UHiazwUXzHajPEgdHpwn7s4J9dd5UPmtvzbYgM",
            "hash": "7beNxrbHxMRspJWT9NeEVwx719kVcmY9tRdPG9SYro26"
        },
        "transaction_outcome": {
            "proof": [
                {
                    "hash": "ECKDm5FVhzit7Wqs9sEyBB9NtuTrVRZmWwcxkkg2yUh4",
                    "direction": "Right"
                },
                {
                    "hash": "E4VXdwsNj3fZCbP6y9YH3M5oZHPDcdArqU9kbZJa95Qp",
                    "direction": "Right"
                }
            ],
            "block_hash": "ASY6HgDUQUXUa99L7dPEfghKEnEk5SNkwQrx24u3Fobz",
            "id": "7beNxrbHxMRspJWT9NeEVwx719kVcmY9tRdPG9SYro26",
            "outcome": {
                "logs": [],
                "receipt_ids": [
                    "JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ"
                ],
                "gas_burnt": 209824625000,
                "tokens_burnt": "20982462500000000000",
                "executor_id": "bumbleee99.near",
                "status": {
                    "SuccessReceiptId": "JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ"
                },
                "metadata": {
                    "version": 1,
                    "gas_profile": null
                }
            }
        },
        "receipts_outcome": [
            {
                "proof": [
                    {
                        "hash": "8RwCWE9HgqenPKv8JW9eg2iSLMaQW82wvebYSfjPbdTY",
                        "direction": "Left"
                    },
                    {
                        "hash": "E4VXdwsNj3fZCbP6y9YH3M5oZHPDcdArqU9kbZJa95Qp",
                        "direction": "Right"
                    }
                ],
                "block_hash": "ASY6HgDUQUXUa99L7dPEfghKEnEk5SNkwQrx24u3Fobz",
                "id": "JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ",
                "outcome": {
                    "logs": [],
                    "receipt_ids": [],
                    "gas_burnt": 209824625000,
                    "tokens_burnt": "20982462500000000000",
                    "executor_id": "bumbleee99.near",
                    "status": {
                        "SuccessValue": ""
                    },
                    "metadata": {
                        "version": 1,
                        "gas_profile": []
                    }
                }
            }
        ],
        "receipts": []
    },
    "id": "2"
}

You could see that both transaction_outcome.outcome.receipt_ids and transaction_outcome.outcome.status are pointing to a receipt with ID JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ. I've tried querying node about this receipt with EXPERIMENTAL_receipt method like this

{
  "jsonrpc": "2.0",
  "id": "2",
  "method": "EXPERIMENTAL_receipt",
  "params": {"receipt_id": "JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ"}
}

yet the node returns error indicating, that there is no receipt with given ID

{
    "jsonrpc": "2.0",
    "error": {
        "name": "HANDLER_ERROR",
        "cause": {
            "name": "UNKNOWN_RECEIPT",
            "info": {
                "receipt_id": "JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ"
            }
        },
        "code": -32000,
        "message": "Server error",
        "data": {
            "name": "UNKNOWN_RECEIPT",
            "info": {
                "receipt_id": "JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ"
            }
        }
    },
    "id": "2"
}

Solution

  • TL;DR the receipt is a local receipt


    The transaction from your example is a simple AddKey action where the sender is the receiver (remember this, it's important)

    1. "Execute" transaction (means to convert the transaction into a Receipt)
    2. Apply the Receipts

    As the result of the conversion of the transaction into a receipt is your transaction_outcome

    "outcome": {
      "receipt_ids": [
        "JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ"
      ],
      "status": {
        "SuccessReceiptId": "JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ"
      },
    

    This receipt is about to be applied and the predecessor_id and the receiver_id are equal. In nearcore such receipts are called local receipts (sir - sender-is-receiver) and those receipts are not stored in the nearcore database.

    We emulate them on NEAR Indexer Framework side (that's why you can see Receipt JDnBrxh6L9KFgVUEg6U8d39rEUEmbvLQ5tZQUmJTMyFJ on the transaction details page on NEAR Explorer)

    And because nearcore doesn't store such receipts in the database you got UNKNOWN_RECEIPT from the RPC.