We build TRONORIGIN, a tool that answers a deceptively simple question about a TRON address: where did this come from, and who controls it? Funds arrive from somewhere. Control is granted by someone. For an investigator, a compliance team, or anyone doing diligence on a counterparty, those two answers are the whole game.
The easy way to build this is to train a model, feed it labelled addresses, and emit a number. We didn’t do that — and the reason is the subject of this post. For forensic work, a score you can’t defend is worse than no score at all. So TRONORIGIN shows its work: every point in every result traces back to a named signal computed over public on-chain data, and the UI shows you the arithmetic.
The constraint that shaped everything
Before any design decision, one constraint: TRONORIGIN runs on free public data only — TronGrid and TronScan, no paid providers, no proprietary clustering feeds. That’s a product decision (the tool should be reproducible by anyone) and it’s a forcing function. When your inputs are all public and your math is all visible, your output is something a third party can check. And as long as every signal stays one a third party can re-derive, the result stays auditable — something people can check, not a claim you’re asking them to trust.
So the engine is built from observable facts: transfers in and out, contract calls, energy and bandwidth delegation, multisig permission updates. Each fact either fires a named signal or it doesn’t.
Signals, not vibes
A “signal” in TRONORIGIN is a small, testable predicate over an address’s history with a fixed weight. A few real ones:
funding_primary_source— the dominant inbound funder, weighted by share of total received.control_active_delegation— an address actively delegating resources (energy/bandwidth) to the target, which is a strong control tell on TRON.control_permission_handoff— anAccountPermissionUpdateContractthat granted keys to another address. We decode the contract, convert the granted keys from hex to base58, and credit the address that gained control — not the transaction’sfrom, which is usually the target signing away its own keys.control_delegation_consumed— the target actually ran on someone else’s energy (we sample its outbound receipts forenergyUsage > 0withenergyFee === 0), which corroborates an active delegator as a real controller rather than a bystander.
Each candidate address accumulates a score from the signals it triggers. Nothing fires that we can’t point at on-chain. There is no learned weight, no embedding, no “the model felt strongly about this one.”

A candidate card from a live TRONORIGIN analysis. The top funding candidate’s share is the sum of four named signals, each one checkable on-chain.
Why auditable beats black-box here
Three reasons, all of which we hit in practice.
You can correct it. When a result looks wrong, the breakdown tells you which
signal is responsible. During our heuristic audit we found that one fee-provider
signal was permanently dead — it keyed on a field (feeInfo.ownerAddress) that
TRON returns as null, so it never fired in production. In a black box that’s an
invisible weight quietly contributing nothing. Here it was a signal that visibly
never appeared in any breakdown, which is exactly how we found and
removed it. We could prove the removal changed zero results because no golden
fixture had ever set the flag.
You can defend it. Attribution gets used to make decisions about people and money. “The model scored it 0.82” is not a finding anyone should act on. “This address is credited as a controller because it granted itself signing keys in this permission-update transaction, decoded here, and the target subsequently ran 14 of 16 sampled transactions on energy this address delegated” — that’s a finding. The second one survives scrutiny because every clause is a link.
You can keep it honest under change. Every signal change runs against a set of golden fixtures — real addresses with known-correct expected outputs. When we added permission-handoff decoding, all twelve prior goldens stayed byte-identical because the new logic is purely additive: it only fires on addresses that have a permission-update history. That’s a property you can state and test precisely because the contribution of each signal is isolated and named.
Showing the work in the UI
The internal architecture only matters to a user if the product surfaces it, so the result view is a breakdown, not a verdict. For each candidate we render the signals that fired, the points each contributed, and — where the signal decoded something — the decoded artifact itself (a base58 address, a delegation amount, a transaction hash you can open on a block explorer). The score is the sum you can see, not a sealed number handed down.

The same analysis’s current controller. Its signals are control evidence — an owner key held now, and the decoded permission handoff that granted it — not funding volume.
The hardest discipline here is refusing to round off the uncertainty. Several signals are corroborating rather than attributive — they raise confidence in a candidate that another signal already surfaced, but they don’t nominate a candidate on their own. We keep that distinction visible instead of blending everything into one figure, because collapsing “this is the funder” and “this is consistent with the funder” into a single number is exactly how a tool starts lying politely.
We also keep the negative space visible. An address with no permission history simply doesn’t trigger the control signals — and the breakdown shows that absence rather than inventing a low-confidence guess to fill the gap. A black box has no honest way to say “I don’t have evidence for this.” An itemized breakdown does: the list of fired signals is short, and the reader can see for themselves that the chain stops where the public data stops. On TRON specifically, that matters because control and funding genuinely diverge — the address that paid for an account is often not the one that holds its signing keys — and a tool that papers over the difference is actively misleading. Separating those axes, and showing each one’s evidence independently, is the difference between an answer and a guess dressed up as one.

Funding and control answered separately. The activator and the current controller are different addresses — control changed hands once since activation — and the timeline shows exactly when the keys moved.
The takeaway
Explainability isn’t a feature we bolted onto a forensic tool — it’s the architecture. Constrain yourself to data anyone can fetch, express every judgment as a named signal with a fixed weight, isolate those signals so each can be tested and corrected independently, and then show the arithmetic. The result is a number a stranger can check, which for attribution work is the only kind of number worth producing.
If you’re building analytics or forensic tooling where the output has to hold up — to a regulator, a court, or just a skeptical colleague — this is the bar. That’s the standard we hold our own products to; TRONORIGIN is the case study.