Skip to content

Energy parity: gate NEW_ACCT_CALL on value transfer + bill SSTORE 0->nonzero as RESET - #4

Merged
Gingerbreadfork merged 1 commit into
masterfrom
energy-fee-parity
Jun 13, 2026
Merged

Energy parity: gate NEW_ACCT_CALL on value transfer + bill SSTORE 0->nonzero as RESET#4
Gingerbreadfork merged 1 commit into
masterfrom
energy-fee-parity

Conversation

@Gingerbreadfork

Copy link
Copy Markdown
Owner

No description provided.

@Gingerbreadfork
Gingerbreadfork merged commit a6ebdd7 into master Jun 13, 2026
@Gingerbreadfork
Gingerbreadfork deleted the energy-fee-parity branch June 13, 2026 05:09
Gingerbreadfork added a commit that referenced this pull request Jun 21, 2026
…udit fixes

A proactive java-tron 4.8.1.1 parity audit (resource, actuator, TVM
opcode/precompile, tx/block subsystems) plus a fresh re-sync divergence
turned up the following. All verified: workspace builds clean; tron-proto,
tron-actuator, tron-executor, and tron-tvm suites green.

Decode-leniency (divergence #4, block 83,449,286 tx 295eab54):
- Add tron_proto::decode_lenient<T>, a java-compatible contract-message decoder
  that mirrors protobuf-java's parser: fields with a known number AND matching
  wire type are merged, any other well-formed field is skipped by its wire type
  (java's parseUnknownField -> skipField), and truncation / invalid wire type /
  unbalanced groups still error (never looser than java). A strict-decode fast
  path keeps well-formed txs (the vast majority) at a single decode.
- Apply it at every contract-parameter decode site (owner extraction, VM exec,
  bandwidth, RPC/index/eventer previews). Fixes a TriggerSmartContract whose
  calldata was mis-encoded under field 3 (wire type 2): java skips the stray
  field and runs an empty-data call (REVERT), where prost hard-errored and we
  rejected the tx pre-VM (DEFAULT, no VM energy).

Actuator parity:
- burn_trx after the fee debit in WitnessCreate / CreateAccount /
  AccountPermissionUpdate (java burns every actuator fee; BURN_TRX_AMOUNT was
  drifting).
- ExchangeTransaction validation ported in full (closed-exchange + balance-limit
  + below-expected, shared Bancor helper so validate/execute can't drift).
- UpdateAccount accepts an empty account name (java validBytes allowEmpty=true).
- Proposal expiration uses java's truncating cmt+(round+1)*interval.
- ProposalCreate per-parameter validation ported (ProposalType map + value-range
  / dependency checks).
- UpdateEnergyLimit fork gate; UnfreezeAsset V1-key selection under
  allowSameTokenName==0.

TVM opcode / precompile / context parity:
- Per-frame contractVersion now gates the 63/64 gas-forwarding retention
  (java keeps 1/64 only for allowTvmCompatibleEvm && contractVersion==1):
  version-0 legacy contracts forward all energy on sub-calls. Threaded the
  executing frame's version through the call/create energy path.
- DELEGATERESOURCE rejects balance < 1 TRX and a Contract-type receiver.
- STATICCALL guard added to the 9 staking opcodes + WITHDRAWREWARD (before the
  nonce bump / state mutation), matching java's StaticCallModificationException.
- Blake2F / MerkleHash malformed input now spends all energy (java refundEnergy(0));
  MerkleHash accepts input length >= 96 (ignoring the tail).
- GASLIMIT pushes 0; BASEFEE pushes energyFee; GASPRICE pushes energyFee for
  version-1 contracts (else 0).
- FREEZEEXPIRETIME delegate path implemented; delegatable_frozen_v2 weight uses
  java's integer-first grouping; precompile cost no longer takes the dynamic-
  energy penalty.

The tx/block + maintenance audit findings (empty-vote re-rank guard,
future-expiration / dup-tx / tx-size validation, OUT_OF_MEMORY contractRet,
legacy standby tie-break, expiration timestamp source) are implemented in a
follow-up. All fixes here are pending one batch re-sync verification.
Gingerbreadfork added a commit that referenced this pull request Jun 21, 2026
Round-2 audit (storage + state serialization) follow-up. TRON commits no state
root over persisted bytes, so #2-#4 are snapshot-diff (RocksDB) parity; #1 is a
genuine future-tx consensus divergence. Workspace builds + suites green.

- CALLTOKEN to a fresh address now gives the recipient java's default
  owner(id=0)+active(id=2) permission when ALLOW_MULTI_SIGN is on (java
  Program.callToAddress endowment>0 -> createAccountIfNotExist ->
  createNormalAccount withDefaultPermission). The value-CALL and SELFDESTRUCT-
  inheritor paths already did this; the CALLTOKEN path missed it, leaving the
  account without the permission java persists -- a later multisig tx from that
  account would validate on java and reject on us.
- SSTORE to zero deletes the storage row instead of persisting a 32-byte-zero
  row (java Storage.commit: isZero -> delete). Adds StorageRowStore::delete.
  No VM-read/refund consequence (both read back zero); persisted-byte parity.
- Deployed contract rows carry code_hash = keccak256(runtime_code) eagerly, on
  both the top-level and nested-CREATE deploy paths (java RepositoryImpl.saveCode
  under allowTvmConstantinople). No VM impact; row + getcontract RPC parity.
- AssetIssue writes the V2 asset-issue store only when ALLOW_SAME_TOKEN_NAME is
  on (mainnet), matching AssetIssueActuator.execute; the legacy V1+V2 path is
  preserved for the flag-off case.

Deferred (separate, larger): re-splitting inline TRC-10 balances back to the
account-asset store with asset_optimized=true on flush (java SnapshotRoot.put) —
the dominant remaining snapshot-diff source; functionally correct as-is.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant