Transaction

Transactions are cryptographically signed instructions from accounts. An account will initiate a transaction to update the state of the TRON network. The simplest transaction is transferring TRX from one account to another.

Transactions, which change the state of the chain, need to be broadcast to the whole network. Any node can broadcast a request for a transaction. After the super node receives the transaction, it executes the transaction and includes it in a block, then propagates the block to the whole network.

Only after the transaction is packed into a block by the super node, and the block is confirmed, the transaction is finally confirmed.

The format of a transaction is as below:

{
    "raw_data": 
    {
        "contract": [{<-->}],
        "ref_block_bytes": "c145",
        "ref_block_hash": "c56bd8a3b3341d9d",
        "expiration": 1646796363000,
        "timestamp": 1646796304152,
        "fee_limit":10000000000
    },
    "signature":["47b1f77b3e30cfbbfa41d795dd34475865240617dd1c5a7bad526f5fd89e52cd057c80b665cc2431efab53520e2b1b92a0425033baee915df858ca1c588b0a1800" ] 
}

A submitted transaction mainly includes the following fields:

  • raw_data.contract - The main content of the transaction,contract is a list, but only one element is used at present. Different types of transactions have different contract contents. For example, for a TRX transfer type transaction, the contract will include the transfer amount, receiver address and other information. TRON supports multiple types of contracts , please refer to the Types of Transaction section below for details.
  • raw_data.ref_block_bytes - The height of the transaction reference block, using the 6th to 8th (exclusive) bytes of the reference block height, a total of 2 bytes. The reference block is used in the TRON TAPOS mechanism, which can prevent a replay of a transaction on forks that do not include the referenced block. Generally the latest solidified block is used as the reference block.
  • raw_data.ref_block_hash - The hash of the transaction reference block, using the 8th to 16th (exclusive) bytes of the reference block hash, a total of 8 bytes. The reference block is used in the TRON TAPOS mechanism, which can prevent a replay of a transaction on forks that do not include the referenced block. Generally the latest solidified block is used as the reference block.
  • raw_data.expiration - Transaction expiration time, beyond which the transaction will no longer be packed. If the transaction is created by calling the java-tron API, its expiration time will be automatically set by node to the value of adding 60 seconds to the timestamp of the node's latest block. The expiration time interval can be modified in the node's configuration file, the maximum value cannot exceed 24 hours.
  • raw_data.timestamp - Transaction timestamp, set as the transaction creation time.
  • raw_data.fee_limit - The maximum energy cost allowed for the execution of smart contract transaction. Only deploying and triggering smart contract transactions need to be set, others not.
  • signature - The sender's signature for the transaction. This proves that the transaction could only have come from the sender and was not sent fraudulently.

Types of Transaction

On TRON there are many different types of transactions, such as TRX transfer transactions, TRC10 transfer transactions, deploying smart contract transactions, triggering smart contract transactions, staking TRX transactions, and so on.

To create different types of transactions, you need to call different APIs. For example, the type of smart contract deployment transaction is CreateSmartContract, you need to call the wallet/deploycontract API to create a transaction, and the type of the staking TRX transaction is FreezeBalanceContract, you need to call wallet/freezebalance API to create transactions.

$ curl -X POST https://api.shasta.trongrid.io/wallet/freezebalance -d '{"owner_address":"TCrkRWJuHP4VgQF3xwLNBAjVVXvxRRGpbA","frozen_balance": 2100000,"frozen_duration": 3,"resource" : "BANDWIDTH","visible":true}' | jq
{
  "visible": true,
  "txID": "e54bab34838a59e85d5684e46a2e8e512cd11dfb07b35a9728adeaf3d2666fa6",
  "raw_data": {
    "contract": [
      {
        "parameter": {
          "value": {
            "frozen_duration": 3,
            "frozen_balance": 2100000,
            "owner_address": "TCrkRWJuHP4VgQF3xwLNBAjVVXvxRRGpbA"
          },
          "type_url": "type.googleapis.com/protocol.FreezeBalanceContract"
        },
        "type": "FreezeBalanceContract"
      }
    ],
    "ref_block_bytes": "7139",
    "ref_block_hash": "d291dee525445093",
    "expiration": 1646902209000,
    "timestamp": 1646902151591
  },
  "raw_data_hex": "0a0271392208d291dee52544509340e8d39598f72f5a58080b12540a32747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e467265657a6542616c616e6365436f6e7472616374121e0a15411fafb1e96dfe4f609e2259bfaf8c77b60c535b9310a0968001180370a7939298f72f"
}

For more transaction types, please refer to:Types of transactions on TRON,For more HTTP APIs, please refer to:HTTP API

Transaction Lifecycle

A transaction goes through the following stages in its life cycle:

  1. Transaction's creation and signature.
  2. The transaction is broadcast to the TRON network, it will be included in a transaction pool after passing the verification and execution by node.
  3. The block producing node takes the transaction from the transaction pool, includes it in a new block, and then broadcasts the block to the TRON network.
  4. The transaction will be "confirmed". Whether a transaction is confirmed depends on whether the block in which the transaction is included is confirmed. TRON's block confirmation mechanism is that after a block is produced, 19 different super nodes produce subsequent blocks based on this block, then the block is confirmed.

Create Transaction

A variety of libraries and tools are available to create transactions. The following takes tronweb to create a TRX transfer transaction as an example to illustrate how to create a transaction:

const unsignedTxn = await tronWeb.transactionBuilder.sendTrx("TVDGpn4hCSzJ5nkHPLetk8KQBtwaTppnkr", 100, "TNPeeaaFB7K9cmo4uQpcU32zGK8G1NYqeL");
 >{
    "visible": false,
    "txID": "9f62a65d0616c749643c4e2620b7877efd0f04dd5b2b4cd14004570d39858d7e",
    "raw_data": {
        "contract": [
            {
                "parameter": {
                    "value": {
                        "amount": 100,
                        "owner_address": "418840e6c55b9ada326d211d818c34a994aeced808",
                        "to_address": "41d3136787e667d1e055d2cd5db4b5f6c880563049"
                    },
                    "type_url": "type.googleapis.com/protocol.TransferContract"
                },
                "type": "TransferContract"
            }
        ],
        "ref_block_bytes": "0add",
        "ref_block_hash": "6c2763abadf9ed29",
        "expiration": 1581308685000,
        "timestamp": 1581308626092
    },
    "raw_data_hex": "0a020add22086c2763abadf9ed2940c8d5deea822e5a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a15418840e6c55b9ada326d211d818c34a994aeced808121541d3136787e667d1e055d2cd5db4b5f6c880563049186470ac89dbea822e"
}

Sign Transaction

A transaction needs to be signed using the sender's private key before sending it.

Transaction signature generating process

  1. Calculate the hash of the transaction.
  2. Sign the transaction hash with the sender's private key.
  3. Add the generated signature to the transaction instance.

Most SDKs implement the above transaction signature generating process and encapsulate them into an interface for developers to call. Taking tronweb as an example, users can directly call the sign method to complete the transaction signature.

Example of signature using tronweb
Use tronweb to sign the transaction created above:

const signedTxn = await tronWeb.trx.sign(unsignedTxn, privateKey);
>{
    "visible": false,
    "txID":"9f62a65d0616c749643c4e2620b7877efd0f04dd5b2b4cd14004570d39858d7e",
    "raw_data":
    {
        "contract": [{<-->}],
        "ref_block_bytes": "0add",
        "ref_block_hash": "6c2763abadf9ed29",
        "expiration": 1581308685000,
        "timestamp": 1581308626092 
    },
    "raw_data_hex": "0a020add22086c2763abadf9ed2940c8d5deea822e5a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a15418840e6c55b9ada326d211d818c34a994aeced808121541d3136787e667d1e055d2cd5db4b5f6c880563049186470ac89dbea822e",
    "signature": [ "47b1f77b3e30cfbbfa41d795dd34475865240617dd1c5a7bad526f5fd89e52cd057c80b665cc2431efab53520e2b1b92a0425033baee915df858ca1c588b0a1800" ] 
 }

Broadcast Transaction

After the node receives a transaction sent by a user, it will try to verify and execute the transaction locally, and broadcasts valid transactions to other nodes, discards invalid transactions, which will effectively prevent spam transactions from invalid broadcast in the network.

To broadcast a signed transaction using tronweb:

const receipt = await tronWeb.trx.sendRawTransaction(signedTxn);
>{ 
    "result": true,
    "transaction":
    { 
        "visible": false,
        "txID": "9f62a65d0616c749643c4e2620b7877efd0f04dd5b2b4cd14004570d39858d7e",
        "raw_data":
        {
            "contract": [{<-->}],
            "ref_block_bytes": "0add",
            "ref_block_hash": "6c2763abadf9ed29",
            "expiration": 1581308685000,
            "timestamp": 1581308626092 
        },
        "raw_data_hex": "0a020add22086c2763abadf9ed2940c8d5deea822e5a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a15418840e6c55b9ada326d211d818c34a994aeced808121541d3136787e667d1e055d2cd5db4b5f6c880563049186470ac89dbea822e",
        "signature": [ "47b1f77b3e30cfbbfa41d795dd34475865240617dd1c5a7bad526f5fd89e52cd057c80b665cc2431efab53520e2b1b92a0425033baee915df858ca1c588b0a1800" ] 
    } 
 }

Transaction confirmation

Whether a transaction is confirmed depends on whether the block in which the transaction is included is confirmed. TRON's block confirmation mechanism is that after a block is produced, 19 different super nodes produce subsequent blocks based on this block, then the block is confirmed.

java-tron node provides /walletsolidty/* API, which is convenient for users to query confirmed transactions. The difference between /walletsolidty/* and /wallet/* is that the transaction queried by /wallet/* indicates that it has been on the chain but not necessarily confirmed. The transaction queried by /walletsolidty/* indicates that it has been on the chain and solidified, that is, the transaction has been confirmed.

For different transactions,there are different ways to determine whether it is confirmed:

  • System Contract Transaction
    All types of transactions other than creating smart contract types and triggering smart contract types are system contract transactions. System contract transaction confirmation method:
    • As long as the transaction can be queried through /walletsolidity/gettransactioninfobyid or /walletsolidity/gettransactionbyid API, it is confirmmed.
  • Smart Contract Transaction
    Including creating smart contract and triggering smart contract transactions. Because they need to be executed in TRON virtual machine, some exceptions may be thrown during the execution. These transactions are on the chain, but it does not mean that the transactions are successfully executed. And there are two ways to determine whether the smart contract transaction is successfully executed:
    • Find transactionInfo.receipt.result equals success via calling the /walletsolidity/gettransactioninfobyid API
    • Find transaction.ret.contractRet equalssuccess via calling /walletsolidity/gettransactionbyidAPI
  • Internal Transaction
    An internal transaction is a transaction that transfers tokens to other external addresses or contract addresses in a contract. First, the internal transactions can be queried through /walletsolidity/gettransactioninfobyid API, and the rejected field in the internal transaction is used to determine whether the internal transaction is confirmed, but differs for HTTP and GRPC API:
    • HTTP API:For successful transactions, the rejected field is not returned by default. For failed transactions, rejected equals true.
    • GRPC API:For successful transactions, rejected equals false, indicating that the current internalTransaction has not been discarded, For failed transactions, rejected equals true.