WalletSuite Transaction Compiler
Deterministic EVM and Tron unsigned-transaction compilation for Rust.
Crate name: walletsuite-tx-compiler
Deterministic transaction compilation for Ethereum (EVM) and Tron. Converts a
canonical PreparedTransaction payload into the signing pre-image bytes
and the corresponding pre-image digest a hardware wallet / HSM / signing
service can sign. Output is byte-exact and stable across versions; every
fixture case in tests/fixtures/canonical.json
is verified on every CI run.
Design goals
- Byte-exact determinism. Compiled output (unsigned tx bytes, pre-image
hash, metadata, review) is stable for every payload in
tests/fixtures/canonical.json. Any change that alters compiled bytes must update that fixture in the same PR and is treated as a hard regression by CI. - No surprises at the boundary. Payloads are validated against the full canonical invariant set (address shape, safe integer ranges, mode-specific fee fields, EIP-155 chain-id, Tron block header, ERC-20 calldata selector with the 20-byte embedded recipient, 0x41 Tron address prefix) before any irreversible work runs.
- Pure library. Does not sign, broadcast, fetch nonces, or read wallets. Output is the signing pre-image + its hash; the caller drives the signer.
- Semver-stable. Every public struct and enum is
#[non_exhaustive]; adding fields or variants is non-breaking. Construct via serde or the provided builder (CompileOptions::new().with_now(...)), never via struct literals. - No-unsafe.
unsafe_code = "forbid". Clippypedantic,nursery, andcargolint groups enabled. - Small dependency surface.
alloy-consensusfor EVM RLP + signature hashing,bs58for Tron base58check,sha2for Tron hashing, and a hand-rolled protobuf encoder forTransaction.raw_data.
Supported transaction shapes
| Chain | Intent | Envelope |
|---|---|---|
| EVM | TRANSFER_NATIVE |
EIP-1559 (type 2) or legacy EIP-155 |
| EVM | TRANSFER_TOKEN |
ERC-20 transfer(address,uint256) |
| Tron | TRANSFER_NATIVE |
TransferContract (type 1) |
| Tron | TRANSFER_TOKEN |
TriggerSmartContract (type 31), TRC-20 transfer |
Install
[]
= "0.1"
Usage
use ;
Reproducible Tron output
Tron timestamp and expiration default to SystemTime::now(), so
compiled bytes vary per call. For byte-exact reproducibility, pin the
wall clock (milliseconds since epoch):
let options = new.with_now;
let result = compile?;
Output contract
Per-chain semantics of CompilationResult::unsigned_tx:
- EVM: the EIP-2718 signing pre-image
(
0x02 || rlp([...])for EIP-1559;rlp([..., chainId, 0, 0])for legacy EIP-155). The caller hashes with keccak256 (already provided astx_hash), signs the hash, and reconstructs the signed envelope viaalloy_consensus::TxEnvelopeor an equivalent library. - Tron: the protobuf-encoded
Transaction.raw_databytes. The caller hashes with SHA-256 (already provided astx_hash), signs the hash, and wrapsraw_data+ signature into the outer TronTransactionmessage to broadcast.
Determinism guarantee
tests/canonical.rs iterates every case in tests/fixtures/canonical.json
and asserts four invariants per case:
unsigned_txmatches the pinned hex byte-for-byte.tx_hashmatches the expected keccak256 (EVM) or SHA-256 (Tron) pre-image digest.metadataserializes to identical JSON (same field set, same key order).reviewserializes to identical JSON.
If you change any code path that alters compiled bytes, update the fixture in the same PR — otherwise CI will block the merge.
Non-goals
- This crate does not manage keys, sign transactions, fetch nonces, or broadcast. Pair it with a signer (hardware wallet, HSM, signing service) and a node client.
- Chains other than Ethereum (EVM-compatible) and Tron are out of scope for this release.
Development
CI runs all of the above on Linux, macOS, and Windows, plus
cargo audit and a compile-only MSRV check (cargo check) against
Rust 1.91.
License
Licensed under the Apache License, Version 2.0.
Security
See SECURITY.md. Report vulnerabilities privately to
security@walletsuite.io.