From c254a72e5f0b1a547c52725589ea1ce5821c488f Mon Sep 17 00:00:00 2001 From: Nischal Sharma Date: Wed, 22 Nov 2023 11:25:28 +0530 Subject: [PATCH] added EIP1559 signed tx decoding --- .../eea/crypto/PrivateTransactionDecoder.java | 109 +++++++++++++----- .../crypto/SignedRawPrivateTransaction.java | 28 +++++ .../crypto/PrivateTransactionDecoderTest.java | 56 +++++++++ 3 files changed, 163 insertions(+), 30 deletions(-) diff --git a/eea/src/main/java/org/web3j/protocol/eea/crypto/PrivateTransactionDecoder.java b/eea/src/main/java/org/web3j/protocol/eea/crypto/PrivateTransactionDecoder.java index 1a21ec0f1..36167ab06 100644 --- a/eea/src/main/java/org/web3j/protocol/eea/crypto/PrivateTransactionDecoder.java +++ b/eea/src/main/java/org/web3j/protocol/eea/crypto/PrivateTransactionDecoder.java @@ -18,6 +18,7 @@ import java.util.stream.Collectors; import org.web3j.crypto.RawTransaction; +import org.web3j.crypto.Sign; import org.web3j.crypto.SignedRawTransaction; import org.web3j.crypto.TransactionDecoder; import org.web3j.crypto.transaction.type.TransactionType; @@ -69,37 +70,85 @@ private static RawPrivateTransaction decodePrivateTransaction1559(final byte[] t final String to = ((RlpString) temp.getValues().get(5)).asString(); final String data = ((RlpString) temp.getValues().get(7)).asString(); - final Base64String privateFrom = extractBase64(values.get(8)); - final Restriction restriction = extractRestriction(values.get(10)); - - if (values.get(9) instanceof RlpList) { - List privateForList = extractBase64List(values.get(9)); - return RawPrivateTransaction.createTransaction( - chainId, - nonce, - maxPriorityFeePerGas, - maxFeePerGas, - gasLimit, - to, - data, - privateFrom, - privateForList, - null, - restriction); + if (values.size() == 11) { + final Base64String privateFrom = extractBase64(values.get(8)); + final Restriction restriction = extractRestriction(values.get(10)); + + if (values.get(9) instanceof RlpList) { + List privateForList = extractBase64List(values.get(9)); + return RawPrivateTransaction.createTransaction( + chainId, + nonce, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + to, + data, + privateFrom, + privateForList, + null, + restriction); + } else { + Base64String privacyGroupId = extractBase64(values.get(9)); + return RawPrivateTransaction.createTransaction( + chainId, + nonce, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + to, + data, + privateFrom, + null, + privacyGroupId, + restriction); + } } else { - Base64String privacyGroupId = extractBase64(values.get(9)); - return RawPrivateTransaction.createTransaction( - chainId, - nonce, - maxPriorityFeePerGas, - maxFeePerGas, - gasLimit, - to, - data, - privateFrom, - null, - privacyGroupId, - restriction); + final Base64String privateFrom = extractBase64(values.get(11)); + final Restriction restriction = extractRestriction(values.get(13)); + + final byte[] v = + Sign.getVFromRecId( + Numeric.toBigInt(((RlpString) values.get(8)).getBytes()).intValue()); + final byte[] r = + Numeric.toBytesPadded( + Numeric.toBigInt(((RlpString) values.get(9)).getBytes()), 32); + final byte[] s = + Numeric.toBytesPadded( + Numeric.toBigInt(((RlpString) values.get(10)).getBytes()), 32); + final Sign.SignatureData signatureData = new Sign.SignatureData(v, r, s); + + if (values.get(12) instanceof RlpList) { + List privateForList = extractBase64List(values.get(12)); + return new SignedRawPrivateTransaction( + chainId, + nonce, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + to, + data, + signatureData, + privateFrom, + privateForList, + null, + restriction); + } else { + Base64String privacyGroupId = extractBase64(values.get(12)); + return new SignedRawPrivateTransaction( + chainId, + nonce, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + to, + data, + signatureData, + privateFrom, + null, + privacyGroupId, + restriction); + } } } diff --git a/eea/src/main/java/org/web3j/protocol/eea/crypto/SignedRawPrivateTransaction.java b/eea/src/main/java/org/web3j/protocol/eea/crypto/SignedRawPrivateTransaction.java index 109455933..7a056b279 100644 --- a/eea/src/main/java/org/web3j/protocol/eea/crypto/SignedRawPrivateTransaction.java +++ b/eea/src/main/java/org/web3j/protocol/eea/crypto/SignedRawPrivateTransaction.java @@ -86,6 +86,34 @@ public SignedRawPrivateTransaction( restriction); } + public SignedRawPrivateTransaction( + final long chainId, + final BigInteger nonce, + final BigInteger maxPriorityFeePerGas, + final BigInteger maxFeePerGas, + final BigInteger gasLimit, + final String to, + final String data, + final Sign.SignatureData signatureData, + final Base64String privateFrom, + final List privateFor, + final Base64String privacyGroupId, + final Restriction restriction) { + super( + chainId, + nonce, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + to, + data, + privateFrom, + privateFor, + privacyGroupId, + restriction); + this.signatureData = signatureData; + } + public Sign.SignatureData getSignatureData() { return signatureData; } diff --git a/eea/src/test/java/org/web3j/protocol/eea/crypto/PrivateTransactionDecoderTest.java b/eea/src/test/java/org/web3j/protocol/eea/crypto/PrivateTransactionDecoderTest.java index 3c5d35f0b..41a941ef2 100644 --- a/eea/src/test/java/org/web3j/protocol/eea/crypto/PrivateTransactionDecoderTest.java +++ b/eea/src/test/java/org/web3j/protocol/eea/crypto/PrivateTransactionDecoderTest.java @@ -187,6 +187,62 @@ public void testDecodingSigned() throws Exception { assertNull(signedResult.getChainId()); } + @Test + public void testDecodingSigned1559() throws Exception { + final BigInteger nonce = BigInteger.ZERO; + final long chainId = 2018; + final BigInteger gasLimit = BigInteger.TEN; + final BigInteger maxPriorityFeePerGas = BigInteger.ONE; + final BigInteger maxFeePerGas = BigInteger.ONE; + final String to = "0x0add5355"; + + final RawPrivateTransaction rawTransaction = + RawPrivateTransaction.createTransaction( + chainId, + nonce, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + to, + "", + MOCK_ENCLAVE_KEY, + MOCK_PRIVATE_FOR, + RESTRICTED); + final String privateKey = + "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"; + final Credentials credentials = Credentials.create(privateKey); + final byte[] encodedMessage = + PrivateTransactionEncoder.signMessage(rawTransaction, credentials); + final String hexMessage = Numeric.toHexString(encodedMessage); + + final RawPrivateTransaction result = PrivateTransactionDecoder.decode(hexMessage); + + final PrivateTransaction1559 result1559 = + (PrivateTransaction1559) result.getPrivateTransaction(); + assertNotNull(result1559); + assertEquals(nonce, result1559.getNonce()); + assertEquals(chainId, result1559.getChainId()); + assertEquals(maxPriorityFeePerGas, result1559.getMaxPriorityFeePerGas()); + assertEquals(maxFeePerGas, result1559.getMaxFeePerGas()); + assertEquals(gasLimit, result1559.getGasLimit()); + assertEquals(to, result1559.getTo()); + assertEquals("0x", result1559.getData()); + assertEquals(MOCK_ENCLAVE_KEY, result1559.getPrivateFrom()); + assertEquals(MOCK_PRIVATE_FOR, result1559.getPrivateFor().get()); + assertEquals(RESTRICTED, result1559.getRestriction()); + + assertTrue(result instanceof SignedRawPrivateTransaction); + final SignedRawPrivateTransaction signedResult = (SignedRawPrivateTransaction) result; + assertNotNull(signedResult.getSignatureData()); + Sign.SignatureData signatureData = signedResult.getSignatureData(); + final byte[] encodedTransaction = PrivateTransactionEncoder.encode(rawTransaction); + final BigInteger key = Sign.signedMessageToKey(encodedTransaction, signatureData); + assertEquals(key, credentials.getEcKeyPair().getPublicKey()); + assertEquals(credentials.getAddress(), signedResult.getFrom()); + signedResult.verify(credentials.getAddress()); + assertNull(signedResult.getChainId()); + } + @Test public void testDecodingSignedPrivacyGroup() throws Exception { final BigInteger nonce = BigInteger.ZERO;