Skip to content

Commit 6da7fbc

Browse files
authored
Merge pull request #51 from 317787106/fix/jsonrpc_pq
fix(jsonrpc): add column pqAuthSigList to TransactionResult
2 parents 3436cd2 + 0d8bbae commit 6da7fbc

3 files changed

Lines changed: 147 additions & 13 deletions

File tree

framework/src/main/java/org/tron/core/services/jsonrpc/types/TransactionResult.java

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.getToAddress;
44
import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.getTransactionAmount;
55

6+
import com.fasterxml.jackson.annotation.JsonInclude;
67
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
78
import com.google.protobuf.ByteString;
9+
import java.util.ArrayList;
10+
import java.util.List;
811
import lombok.Getter;
912
import lombok.ToString;
1013
import org.tron.common.crypto.Rsv;
@@ -13,6 +16,7 @@
1316
import org.tron.core.capsule.BlockCapsule;
1417
import org.tron.core.capsule.TransactionCapsule;
1518
import org.tron.protos.Protocol;
19+
import org.tron.protos.Protocol.PQAuthSig;
1620
import org.tron.protos.Protocol.Transaction;
1721
import org.tron.protos.Protocol.Transaction.Contract;
1822
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
@@ -55,20 +59,47 @@ public class TransactionResult {
5559
@Getter
5660
private String s;
5761

58-
private void parseSignature(Transaction tx) {
62+
@Getter
63+
@JsonInclude(JsonInclude.Include.NON_NULL)
64+
private List<PQAuthSigResult> pqAuthSigList;
65+
66+
@JsonPropertyOrder(alphabetic = true)
67+
@ToString
68+
public static class PQAuthSigResult {
69+
70+
@Getter
71+
private final String scheme;
72+
@Getter
73+
private final String publicKey;
74+
@Getter
75+
private final String signature;
76+
77+
public PQAuthSigResult(PQAuthSig pqAuthSig) {
78+
this.scheme = pqAuthSig.getScheme().name();
79+
this.publicKey = ByteArray.toJsonHex(pqAuthSig.getPublicKey().toByteArray());
80+
this.signature = ByteArray.toJsonHex(pqAuthSig.getSignature().toByteArray());
81+
}
82+
}
5983

84+
private void parseSignature(Transaction tx) {
6085
if (tx.getSignatureCount() == 0) {
6186
v = ByteArray.toJsonHex(new byte[1]);
6287
r = ByteArray.toJsonHex(new byte[32]);
6388
s = ByteArray.toJsonHex(new byte[32]);
64-
return;
89+
} else {
90+
ByteString signature = tx.getSignature(0); // r[32] + s[32] + v[1]
91+
Rsv rsv = Rsv.fromSignature(signature.toByteArray());
92+
r = ByteArray.toJsonHex(rsv.getR());
93+
s = ByteArray.toJsonHex(rsv.getS());
94+
v = ByteArray.toJsonHex(rsv.getV());
6595
}
6696

67-
ByteString signature = tx.getSignature(0); // r[32] + s[32] + v[1]
68-
Rsv rsv = Rsv.fromSignature(signature.toByteArray());
69-
r = ByteArray.toJsonHex(rsv.getR());
70-
s = ByteArray.toJsonHex(rsv.getS());
71-
v = ByteArray.toJsonHex(rsv.getV());
97+
if (tx.getPqAuthSigCount() > 0) {
98+
pqAuthSigList = new ArrayList<>();
99+
for (PQAuthSig pqAuthSig : tx.getPqAuthSigList()) {
100+
pqAuthSigList.add(new PQAuthSigResult(pqAuthSig));
101+
}
102+
}
72103
}
73104

74105
private String parseInput(Transaction tx) {

framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -816,9 +816,8 @@ public void validateAllowFnDsa512() {
816816
long maintenanceTimeInterval = forkUtils.getManager().getDynamicPropertiesStore()
817817
.getMaintenanceTimeInterval();
818818
long hardForkTime =
819-
((ForkBlockVersionEnum.VERSION_4_8_2_PQ1.getHardForkTime() - 1) / maintenanceTimeInterval +
820-
1)
821-
* maintenanceTimeInterval;
819+
((ForkBlockVersionEnum.VERSION_4_8_2_PQ1.getHardForkTime() - 1) / maintenanceTimeInterval
820+
+ 1) * maintenanceTimeInterval;
822821
forkUtils.getManager().getDynamicPropertiesStore()
823822
.saveLatestBlockHeaderTimestamp(hardForkTime - 1);
824823

@@ -879,9 +878,8 @@ public void validateAllowMlDsa44() {
879878
long maintenanceTimeInterval = forkUtils.getManager().getDynamicPropertiesStore()
880879
.getMaintenanceTimeInterval();
881880
long hardForkTime =
882-
((ForkBlockVersionEnum.VERSION_4_8_2_PQ1.getHardForkTime() - 1) / maintenanceTimeInterval +
883-
1)
884-
* maintenanceTimeInterval;
881+
((ForkBlockVersionEnum.VERSION_4_8_2_PQ1.getHardForkTime() - 1) / maintenanceTimeInterval
882+
+ 1) * maintenanceTimeInterval;
885883
forkUtils.getManager().getDynamicPropertiesStore()
886884
.saveLatestBlockHeaderTimestamp(hardForkTime - 1);
887885

framework/src/test/java/org/tron/core/services/jsonrpc/TransactionResultTest.java

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,109 @@ public void testBuildTransactionResult() {
7979
assertQuantity(transactionResult.getNonce());
8080
}
8181

82+
private Protocol.Transaction buildBaseTransaction() {
83+
SmartContractOuterClass.TriggerSmartContract.Builder builder =
84+
SmartContractOuterClass.TriggerSmartContract.newBuilder()
85+
.setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(OWNER_ADDRESS)))
86+
.setContractAddress(ByteString.copyFrom(ByteArray.fromHexString(CONTRACT_ADDRESS)));
87+
return new TransactionCapsule(builder.build(),
88+
Protocol.Transaction.Contract.ContractType.TriggerSmartContract).getInstance();
89+
}
90+
91+
// r[0..32] + s[32..64] + v[64], v stored as revId 0 so parseSignature normalizes it to 27.
92+
private byte[] buildSignature() {
93+
byte[] sign = new byte[65];
94+
for (int i = 0; i < 32; i++) {
95+
sign[i] = (byte) (i + 1); // r
96+
}
97+
for (int i = 32; i < 64; i++) {
98+
sign[i] = (byte) (i + 1); // s
99+
}
100+
sign[64] = 0;
101+
return sign;
102+
}
103+
104+
private Protocol.PQAuthSig buildPqAuthSig() {
105+
return Protocol.PQAuthSig.newBuilder()
106+
.setScheme(Protocol.PQScheme.ML_DSA_44)
107+
.setPublicKey(ByteString.copyFrom(new byte[] {1, 2, 3}))
108+
.setSignature(ByteString.copyFrom(new byte[] {4, 5, 6}))
109+
.build();
110+
}
111+
112+
@Test
113+
public void testParseSignatureWithNoSignature() {
114+
TransactionResult transactionResult =
115+
new TransactionResult(buildBaseTransaction(), wallet);
116+
// No ECDSA signature and no PQ signature: v/r/s fall back to zero padding.
117+
Assert.assertEquals(ByteArray.toJsonHex(new byte[1]), transactionResult.getV());
118+
Assert.assertEquals(ByteArray.toJsonHex(new byte[32]), transactionResult.getR());
119+
Assert.assertEquals(ByteArray.toJsonHex(new byte[32]), transactionResult.getS());
120+
Assert.assertNull(transactionResult.getPqAuthSigList());
121+
}
122+
123+
@Test
124+
public void testParseSignatureWithEcdsaSignatureOnly() {
125+
byte[] sign = buildSignature();
126+
Protocol.Transaction transaction = buildBaseTransaction().toBuilder()
127+
.addSignature(ByteString.copyFrom(sign))
128+
.build();
129+
130+
TransactionResult transactionResult = new TransactionResult(transaction, wallet);
131+
Assert.assertEquals(ByteArray.toJsonHex(java.util.Arrays.copyOfRange(sign, 0, 32)),
132+
transactionResult.getR());
133+
Assert.assertEquals(ByteArray.toJsonHex(java.util.Arrays.copyOfRange(sign, 32, 64)),
134+
transactionResult.getS());
135+
// revId 0 is normalized to 27 (0x1b).
136+
Assert.assertEquals(ByteArray.toJsonHex(new byte[] {27}), transactionResult.getV());
137+
Assert.assertNull(transactionResult.getPqAuthSigList());
138+
}
139+
140+
@Test
141+
public void testParseSignatureWithPqAuthSigOnly() {
142+
Protocol.PQAuthSig pqAuthSig = buildPqAuthSig();
143+
Protocol.Transaction transaction = buildBaseTransaction().toBuilder()
144+
.addPqAuthSig(pqAuthSig)
145+
.build();
146+
147+
TransactionResult transactionResult = new TransactionResult(transaction, wallet);
148+
// No ECDSA signature: v/r/s fall back to zero padding.
149+
Assert.assertEquals(ByteArray.toJsonHex(new byte[1]), transactionResult.getV());
150+
Assert.assertEquals(ByteArray.toJsonHex(new byte[32]), transactionResult.getR());
151+
Assert.assertEquals(ByteArray.toJsonHex(new byte[32]), transactionResult.getS());
152+
Assert.assertNotNull(transactionResult.getPqAuthSigList());
153+
Assert.assertEquals(1, transactionResult.getPqAuthSigList().size());
154+
TransactionResult.PQAuthSigResult result = transactionResult.getPqAuthSigList().get(0);
155+
Assert.assertEquals(pqAuthSig.getScheme().name(), result.getScheme());
156+
Assert.assertEquals(ByteArray.toJsonHex(pqAuthSig.getPublicKey().toByteArray()),
157+
result.getPublicKey());
158+
Assert.assertEquals(ByteArray.toJsonHex(pqAuthSig.getSignature().toByteArray()),
159+
result.getSignature());
160+
}
161+
162+
@Test
163+
public void testParseSignatureWithEcdsaAndPqAuthSig() {
164+
byte[] sign = buildSignature();
165+
Protocol.PQAuthSig pqAuthSig = buildPqAuthSig();
166+
Protocol.Transaction transaction = buildBaseTransaction().toBuilder()
167+
.addSignature(ByteString.copyFrom(sign))
168+
.addPqAuthSig(pqAuthSig)
169+
.build();
170+
171+
TransactionResult transactionResult = new TransactionResult(transaction, wallet);
172+
Assert.assertEquals(ByteArray.toJsonHex(java.util.Arrays.copyOfRange(sign, 0, 32)),
173+
transactionResult.getR());
174+
Assert.assertEquals(ByteArray.toJsonHex(java.util.Arrays.copyOfRange(sign, 32, 64)),
175+
transactionResult.getS());
176+
Assert.assertEquals(ByteArray.toJsonHex(new byte[] {27}), transactionResult.getV());
177+
Assert.assertNotNull(transactionResult.getPqAuthSigList());
178+
Assert.assertEquals(1, transactionResult.getPqAuthSigList().size());
179+
TransactionResult.PQAuthSigResult result = transactionResult.getPqAuthSigList().get(0);
180+
Assert.assertEquals(pqAuthSig.getScheme().name(), result.getScheme());
181+
Assert.assertEquals(ByteArray.toJsonHex(pqAuthSig.getPublicKey().toByteArray()),
182+
result.getPublicKey());
183+
Assert.assertEquals(ByteArray.toJsonHex(pqAuthSig.getSignature().toByteArray()),
184+
result.getSignature());
185+
}
186+
82187
}

0 commit comments

Comments
 (0)