|
cryptnox-pos 1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
|
Tron HTTP API client implementation. More...
#include "tron_rpc.h"#include "tron_tx.h"#include "eth_json.h"#include "https_post.h"#include <stdio.h>#include <string.h>#include <strings.h>#include <inttypes.h>#include "CW_Utils.h"#include "esp_log.h"#include "mbedtls/sha256.h"#include <sys/time.h>#include "cJSON.h"Go to the source code of this file.
Macros | |
| #define | RESP_BUF_SIZE 3072U |
| #define | RESP_LOG_MAX 120 |
| #define | RAW_BYTES_MAX (TRON_RAW_HEX_MAX / 2U) |
Functions | |
| static char | nibble_hex (unsigned n) |
| static int | nibble_val (char c) |
| static size_t | hex_to_bytes (const char *hex, uint8_t *out, size_t out_size) |
| Decode a hex string into bytes. | |
| static void | bytes_to_hex (const uint8_t *data, size_t len, char *out) |
Hex-encode len bytes into out (NUL-terminated). | |
| static bool | tron_post (const char *path, const char *body, char *resp, size_t resp_size) |
POST body to path under the configured base URL. | |
| static uint64_t | now_ms (void) |
| Unix time in ms, 0 if the clock is unset (the checks then refuse). | |
| static bool | tx_ctx_from_json (const cJSON *txobj, tron_tx_ctx_t *out) |
| Take a node-built transaction object apart into a tron_tx_ctx_t. | |
| void | tron_rpc_init (const char *base_url) |
| Set the Tron HTTP API base URL (no trailing slash). | |
| void | tron_rpc_set_ca_cert (const char *ca_pem) |
| Optional: pin the Tron endpoint's TLS certificate. | |
| static uint64_t | json_u64 (const cJSON *n) |
| A cJSON number as a uint64, clamped at both ends. | |
| bool | tron_rpc_get_balance (const char *owner_hex, uint64_t *sun_out) |
| Read an account's TRX balance, in sun. | |
| bool | tron_rpc_get_energy (const char *owner_hex, uint64_t *energy_out) |
| Read the energy an account still has available. | |
| bool | tron_rpc_get_trc20_balance (const char *owner_hex, const char *contract_hex, uint64_t *units_out) |
Read an account's TRC-20 balance via a constant balanceOf call. | |
| bool | tron_rpc_get_trc20_decimals (const char *contract_hex, uint64_t *dec_out) |
Read a TRC-20 contract's decimals() — see eth_rpc_get_token_decimals for why it has to be 6. | |
| bool | tron_rpc_create_transfer (const char *owner_hex, const char *to_hex, uint64_t amount_sun, tron_tx_ctx_t *out) |
| Create a TRX transfer and verify what the node serialised for us. | |
| bool | tron_rpc_create_trc20_transfer (const char *owner_hex, const char *contract_hex, const char *to_hex, uint64_t amount, uint64_t fee_limit_sun, tron_tx_ctx_t *out) |
Create a TRC-20 transfer (USDT, USDC, …) and verify what the node serialised for us. | |
| bool | tron_rpc_broadcast (const tron_tx_ctx_t *tx, const uint8_t sig[65]) |
| Broadcast a created transfer with its 65-byte signature. | |
| tron_receipt_t | tron_rpc_get_receipt (const char *txid_hex) |
| Poll a broadcast transaction's receipt (one shot). | |
Variables | |
| static const char *const | TAG = "tron_rpc" |
| static const char * | s_base_url = NULL |
| static const char * | s_ca_cert = NULL |
Tron HTTP API client implementation.
Definition in file tron_rpc.cpp.
| #define RAW_BYTES_MAX (TRON_RAW_HEX_MAX / 2U) |
Definition at line 42 of file tron_rpc.cpp.
Referenced by tx_ctx_from_json().
| #define RESP_BUF_SIZE 3072U |
Definition at line 38 of file tron_rpc.cpp.
| #define RESP_LOG_MAX 120 |
Definition at line 39 of file tron_rpc.cpp.
|
static |
Hex-encode len bytes into out (NUL-terminated).
Definition at line 89 of file tron_rpc.cpp.
References nibble_hex().
Referenced by tron_rpc_broadcast(), and tx_ctx_from_json().
|
static |
Decode a hex string into bytes.
| [in] | hex | NUL-terminated hex, even length. |
| [out] | out | Destination bytes. |
| [in] | out_size | Capacity of out. |
Definition at line 73 of file tron_rpc.cpp.
References nibble_val().
Referenced by tx_ctx_from_json().
|
static |
A cJSON number as a uint64, clamped at both ends.
Tron reports sun and energy as JSON integers and cJSON hands them back as doubles, so past 2^53 the low digits are lost. For a balance that is a rounding error in the last drop of TRX; it is never the difference between funded and empty, which is the only question asked of these numbers.
A missing or non-numeric field reads as zero — for an account the chain has never seen, that is the answer rather than an error.
Definition at line 211 of file tron_rpc.cpp.
Referenced by tron_rpc_get_balance(), and tron_rpc_get_energy().
|
static |
Definition at line 51 of file tron_rpc.cpp.
Referenced by bytes_to_hex().
|
static |
Definition at line 57 of file tron_rpc.cpp.
Referenced by hex_to_bytes().
|
static |
Unix time in ms, 0 if the clock is unset (the checks then refuse).
Definition at line 117 of file tron_rpc.cpp.
Referenced by raw_ok(), tron_rpc_create_transfer(), tron_rpc_create_trc20_transfer(), tron_tx_contract_ok(), and tron_tx_trc20_ok().
|
static |
POST body to path under the configured base URL.
Definition at line 99 of file tron_rpc.cpp.
References https_post_json(), s_base_url, s_ca_cert, and TAG.
Referenced by tron_rpc_broadcast(), tron_rpc_create_transfer(), tron_rpc_create_trc20_transfer(), tron_rpc_get_balance(), tron_rpc_get_energy(), tron_rpc_get_receipt(), tron_rpc_get_trc20_balance(), and tron_rpc_get_trc20_decimals().
| bool tron_rpc_broadcast | ( | const tron_tx_ctx_t * | tx, |
| const uint8_t | sig[65] ) |
Broadcast a created transfer with its 65-byte signature.
| [in] | tx | Context returned by tron_rpc_create_transfer. |
| [in] | sig | Signature bytes: r(32) || s(32) || recovery id(1). |
Definition at line 471 of file tron_rpc.cpp.
References bytes_to_hex(), ok(), tron_tx_ctx_t::raw_hex, RESP_BUF_SIZE, RESP_LOG_MAX, TAG, tron_post(), TRON_RAW_HEX_MAX, TRON_SIG_HEX_LEN, and tron_tx_envelope_hex().
Referenced by sign_and_broadcast_tron().
| bool tron_rpc_create_transfer | ( | const char * | owner_hex, |
| const char * | to_hex, | ||
| uint64_t | amount_sun, | ||
| tron_tx_ctx_t * | out ) |
Create a TRX transfer and verify what the node serialised for us.
| [in] | owner_hex | Sender address, "41"-prefixed 42-char hex. |
| [in] | to_hex | Recipient address, same form. |
| [in] | amount_sun | Amount in sun (1 TRX = 1e6 sun); must be non-zero. |
| [out] | out | Filled on success; contents undefined on failure. |
Definition at line 366 of file tron_rpc.cpp.
References tron_tx_ctx_t::expiration_ms, now_ms(), ok(), tron_tx_ctx_t::raw_hex, RESP_BUF_SIZE, RESP_LOG_MAX, TAG, tron_post(), tron_tx_contract_ok(), tx_ctx_from_json(), and tron_tx_ctx_t::txid_hex.
Referenced by sign_and_broadcast_tron().
| bool tron_rpc_create_trc20_transfer | ( | const char * | owner_hex, |
| const char * | contract_hex, | ||
| const char * | to_hex, | ||
| uint64_t | amount, | ||
| uint64_t | fee_limit_sun, | ||
| tron_tx_ctx_t * | out ) |
Create a TRC-20 transfer (USDT, USDC, …) and verify what the node serialised for us.
Same trust model as tron_rpc_create_transfer, with one more thing to get wrong: the token contract. A node free to choose it could have the card sign a transfer of a worthless token — or of a different one entirely — so the contract address is pinned by the check just like the recipient is, and so is the fee limit (see tron_tx_trc20_ok).
| [in] | owner_hex | Sender address, "41"-prefixed 42-char hex. |
| [in] | contract_hex | Token contract address, same form. |
| [in] | to_hex | Recipient address, same form. |
| [in] | amount | Amount in token base units; must be non-zero. |
| [in] | fee_limit_sun | Max TRX (in sun) the call may burn; must be non-zero, or a failed call has no cap at all. |
| [out] | out | Filled on success; contents undefined on failure. |
Definition at line 411 of file tron_rpc.cpp.
References tron_tx_ctx_t::expiration_ms, now_ms(), ok(), tron_tx_ctx_t::raw_hex, RESP_BUF_SIZE, RESP_LOG_MAX, TAG, tron_post(), tron_trc20_param_hex(), TRON_TRC20_PARAM_HEX_LEN, tron_tx_trc20_ok(), tx_ctx_from_json(), and tron_tx_ctx_t::txid_hex.
Referenced by sign_and_broadcast_tron().
| bool tron_rpc_get_balance | ( | const char * | owner_hex, |
| uint64_t * | sun_out ) |
Read an account's TRX balance, in sun.
For the pre-flight check that refuses a sale the tapped card cannot fund, before it signs anything — see tron_balance_ok in main.cpp.
An account the chain has never seen answers with an empty object. That is reported as a balance of zero and not as an error, because it is the true answer and it is the case a terminal most needs to catch.
| [in] | owner_hex | Account address, "41"-prefixed 42-char hex. |
| [out] | sun_out | Balance in sun on success; untouched on failure. |
Definition at line 218 of file tron_rpc.cpp.
References json_u64(), RESP_BUF_SIZE, RESP_LOG_MAX, TAG, and tron_post().
Referenced by tron_balance_ok().
| bool tron_rpc_get_energy | ( | const char * | owner_hex, |
| uint64_t * | energy_out ) |
Read the energy an account still has available.
EnergyLimit minus EnergyUsed from /wallet/getaccountresource. Only the distinction between none and some is used: a TRC-20 transfer burns energy paid for out of a stake or out of TRX, so an account with zero TRX can still pay if it has frozen some — and refusing that sale would be worse than the late failure the check exists to avoid.
| [in] | owner_hex | Account address, "41"-prefixed 42-char hex. |
| [out] | energy_out | Energy available on success; untouched on failure. |
Definition at line 241 of file tron_rpc.cpp.
References json_u64(), RESP_BUF_SIZE, RESP_LOG_MAX, TAG, and tron_post().
Referenced by tron_balance_ok().
| tron_receipt_t tron_rpc_get_receipt | ( | const char * | txid_hex | ) |
Poll a broadcast transaction's receipt (one shot).
| [in] | txid_hex | 64-char transaction id hex. |
Definition at line 511 of file tron_rpc.cpp.
References RESP_BUF_SIZE, TAG, tron_post(), TRON_RECEIPT_FAILED, TRON_RECEIPT_PENDING, TRON_RECEIPT_RPC_ERROR, and TRON_RECEIPT_SUCCESS.
Referenced by settle_inflight().
| bool tron_rpc_get_trc20_balance | ( | const char * | owner_hex, |
| const char * | contract_hex, | ||
| uint64_t * | units_out ) |
Read an account's TRC-20 balance via a constant balanceOf call.
The check that tron_rpc_create_trc20_transfer cannot make: creating a TriggerSmartContract is only serialisation, and a node will serialise a transfer of tokens the account does not hold just as readily as one it does. Without this the card signs it, it broadcasts, it reverts on-chain, and the customer is declined after the full wait — having paid the energy for it.
| [in] | owner_hex | Account address, "41"-prefixed 42-char hex. |
| [in] | contract_hex | Token contract address, same form. |
| [out] | units_out | Balance in the token's base units on success; untouched on failure. Saturating, as for the EVM side (see eth_json_hex_quantity). |
Definition at line 269 of file tron_rpc.cpp.
References eth_json_hex_quantity(), ok(), RESP_BUF_SIZE, RESP_LOG_MAX, TAG, TRON_ADDR_HEX_LEN, and tron_post().
Referenced by tron_balance_ok().
| bool tron_rpc_get_trc20_decimals | ( | const char * | contract_hex, |
| uint64_t * | dec_out ) |
Read a TRC-20 contract's decimals() — see eth_rpc_get_token_decimals for why it has to be 6.
| [in] | contract_hex | Contract, TRON_ADDR_HEX_LEN hex chars, "41"-prefixed. |
| [out] | dec_out | decimals() on success; untouched on failure. |
Definition at line 330 of file tron_rpc.cpp.
References eth_json_hex_quantity(), ok(), RESP_BUF_SIZE, RESP_LOG_MAX, TAG, TRON_ADDR_HEX_LEN, and tron_post().
Referenced by token_decimals_ok().
| void tron_rpc_init | ( | const char * | base_url | ) |
Set the Tron HTTP API base URL (no trailing slash).
Lifetime: the pointer is stored as-is — pass a literal or static storage.
| [in] | base_url | e.g. "https://nile.trongrid.io". |
Definition at line 190 of file tron_rpc.cpp.
References s_base_url.
Referenced by pos_boot().
| void tron_rpc_set_ca_cert | ( | const char * | ca_pem | ) |
Optional: pin the Tron endpoint's TLS certificate.
The sibling of eth_rpc_set_ca_cert, and for the same reason: unset, the connection is validated against the whole Mozilla CA bundle, so any one of ~150 CAs can stand in for the node. That is survivable here — tron_tx_contract_ok re-derives the bytes a transfer must contain, so a node (or anything impersonating one) cannot redirect a payment — but it is the difference between one check standing between an attacker and the funds and two. Pin it in production.
Pointer stored as-is (must outlive every call). NULL keeps the CA bundle.
| [in] | ca_pem | NUL-terminated PEM certificate, or NULL for the bundle. |
Definition at line 195 of file tron_rpc.cpp.
References s_ca_cert.
Referenced by pos_boot().
|
static |
Take a node-built transaction object apart into a tron_tx_ctx_t.
Shared by both create paths. Proves txID == sha256(raw_data): without it the node could hand us the hash of an unrelated transaction and get it blind-signed by the card, and no amount of checking raw_data would notice, since the signature covers the hash and not the bytes.
The caller still has to check that raw_data pays what it asked for — that check differs per contract type, and it runs on out->raw_hex once this has established that raw_data is the thing being signed.
| [in] | txobj | cJSON object carrying txID and raw_data_hex. |
| [out] | out | Filled on success. |
Definition at line 141 of file tron_rpc.cpp.
References bytes_to_hex(), hex_to_bytes(), RAW_BYTES_MAX, tron_tx_ctx_t::raw_hex, TAG, TRON_RAW_HEX_MAX, tron_tx_ctx_t::txid, and tron_tx_ctx_t::txid_hex.
Referenced by tron_rpc_create_transfer(), and tron_rpc_create_trc20_transfer().
|
static |
Definition at line 44 of file tron_rpc.cpp.
Referenced by tron_post(), and tron_rpc_init().
|
static |
Definition at line 45 of file tron_rpc.cpp.
|
static |
Definition at line 34 of file tron_rpc.cpp.