From ef27b6dff9fc57f763668b20c9a7992e580fe375 Mon Sep 17 00:00:00 2001 From: waynercheung Date: Thu, 30 Apr 2026 17:39:03 +0800 Subject: [PATCH] fix(jsonrpc): correct TransactionResult.nonce per JSON-RPC spec Per ethereum/execution-apis, TransactionInfo.nonce is `uint` (QUANTITY) and must match `^0x(0|[1-9a-f][0-9a-f]*)$`. java-tron emitted the field as `0x0000000000000000` via `ByteArray.toJsonHex(new byte[8])`, which violates the pattern. Both `TransactionResult` constructors now emit `"0x0"`. Block.nonce is intentionally left at `0x0000000000000000` because the Block schema defines it as `bytes8`, so that value is already compliant and shortening it would break conformance. Closes #6547 --- .../services/jsonrpc/types/TransactionResult.java | 4 ++-- .../services/jsonrpc/TransactionResultTest.java | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java index 57650355d46..4f11c1a5908 100644 --- a/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java +++ b/framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java @@ -98,7 +98,7 @@ public TransactionResult(BlockCapsule blockCapsule, int index, Protocol.Transact TransactionCapsule capsule = new TransactionCapsule(tx); byte[] txId = capsule.getTransactionId().getBytes(); hash = ByteArray.toJsonHex(txId); - nonce = ByteArray.toJsonHex(new byte[8]); // no value + nonce = "0x0"; // no value, QUANTITY type per Ethereum JSON-RPC spec blockHash = ByteArray.toJsonHex(blockCapsule.getBlockId().getBytes()); blockNumber = ByteArray.toJsonHex(blockCapsule.getNum()); transactionIndex = ByteArray.toJsonHex(index); @@ -133,7 +133,7 @@ public TransactionResult(Transaction tx, Wallet wallet) { TransactionCapsule capsule = new TransactionCapsule(tx); byte[] txId = capsule.getTransactionId().getBytes(); hash = ByteArray.toJsonHex(txId); - nonce = ByteArray.toJsonHex(new byte[8]); // no value + nonce = "0x0"; // no value, QUANTITY type per Ethereum JSON-RPC spec blockHash = "0x"; blockNumber = "0x"; transactionIndex = "0x"; diff --git a/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java b/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java index 4e1af06199c..19c2bb6c4d3 100644 --- a/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java +++ b/framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java @@ -23,10 +23,18 @@ public class TransactionResultTest extends BaseTest { private static final String OWNER_ADDRESS = "41548794500882809695a8a687866e76d4271a1abc"; private static final String CONTRACT_ADDRESS = "A0B4750E2CD76E19DCA331BF5D089B71C3C2798548"; + // QUANTITY pattern from ethereum/execution-apis base-types schema (uint). + private static final String QUANTITY_PATTERN = "^0x(0|[1-9a-f][0-9a-f]*)$"; + static { Args.setParam(new String[] {"-d", dbPath()}, TestConstants.TEST_CONF); } + private static void assertQuantity(String value) { + Assert.assertNotNull(value); + Assert.assertTrue("not a valid QUANTITY: " + value, value.matches(QUANTITY_PATTERN)); + } + @Test public void testBuildTransactionResultWithBlock() { SmartContractOuterClass.TriggerSmartContract.Builder builder2 = @@ -49,6 +57,8 @@ public void testBuildTransactionResultWithBlock() { transactionResult.getHash()); Assert.assertEquals(transactionResult.getGasPrice(), "0x1"); Assert.assertEquals(transactionResult.getGas(), "0x64"); + Assert.assertEquals("0x0", transactionResult.getNonce()); + assertQuantity(transactionResult.getNonce()); } @Test @@ -65,7 +75,8 @@ public void testBuildTransactionResult() { Assert.assertEquals("0x5691531881bc44adbc722060d85fdf29265823db8e884b0d104fcfbba253cf11", transactionResult.getHash()); Assert.assertEquals(transactionResult.getGasPrice(), "0x"); - Assert.assertEquals(transactionResult.getNonce(), "0x0000000000000000"); + Assert.assertEquals("0x0", transactionResult.getNonce()); + assertQuantity(transactionResult.getNonce()); } }