Skip to content

Commit

Permalink
Merge pull request #1992 from liewhite/master
Browse files Browse the repository at this point in the history
Add AccessList to 1559 transaction rlp encoding
  • Loading branch information
NickSneo authored Feb 13, 2024
2 parents e02c56a + 53c8ae2 commit 01c003f
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 23 deletions.
28 changes: 27 additions & 1 deletion crypto/src/main/java/org/web3j/crypto/RawTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.web3j.crypto;

import java.math.BigInteger;
import java.util.Collections;
import java.util.List;

import org.web3j.crypto.transaction.type.ITransaction;
Expand Down Expand Up @@ -115,7 +116,32 @@ public static RawTransaction createTransaction(
value,
data,
maxPriorityFeePerGas,
maxFeePerGas));
maxFeePerGas,
Collections.emptyList()));
}

public static RawTransaction createTransaction(
long chainId,
BigInteger nonce,
BigInteger gasLimit,
String to,
BigInteger value,
String data,
BigInteger maxPriorityFeePerGas,
BigInteger maxFeePerGas,
List<AccessListObject> accessList) {

return new RawTransaction(
Transaction1559.createTransaction(
chainId,
nonce,
gasLimit,
to,
value,
data,
maxPriorityFeePerGas,
maxFeePerGas,
accessList));
}

public static RawTransaction createTransaction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ private static RawTransaction decodeEIP1559Transaction(final byte[] transaction)

final BigInteger value = ((RlpString) values.getValues().get(6)).asPositiveBigInteger();
final String data = ((RlpString) values.getValues().get(7)).asString();
List<AccessListObject> accessList =
decodeAccessList(((RlpList) values.getValues().get(8)).getValues());

final RawTransaction rawTransaction =
RawTransaction.createTransaction(
Expand All @@ -74,7 +76,8 @@ private static RawTransaction decodeEIP1559Transaction(final byte[] transaction)
value,
data,
maxPriorityFeePerGas,
maxFeePerGas);
maxFeePerGas,
accessList);

if (values.getValues().size() == UNSIGNED_EIP1559TX_RLP_LIST_SIZE) {
return rawTransaction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,24 @@

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.web3j.crypto.AccessListObject;
import org.web3j.crypto.Sign;
import org.web3j.rlp.RlpList;
import org.web3j.rlp.RlpString;
import org.web3j.rlp.RlpType;
import org.web3j.utils.Bytes;
import org.web3j.utils.Numeric;

import static org.web3j.crypto.transaction.type.TransactionType.EIP1559;

/**
* Transaction class used for signing 1559 transactions locally.<br>
* For the specification, refer to p4 of the <a href="http://gavwood.com/paper.pdf">yellow
* paper</a>.
*/
public class Transaction1559 extends LegacyTransaction implements ITransaction {
public class Transaction1559 extends Transaction2930 implements ITransaction {

private long chainId;
private BigInteger maxPriorityFeePerGas;
private BigInteger maxFeePerGas;

Expand All @@ -45,8 +44,22 @@ public Transaction1559(
String data,
BigInteger maxPriorityFeePerGas,
BigInteger maxFeePerGas) {
super(EIP1559, nonce, null, gasLimit, to, value, data);
this.chainId = chainId;
super(chainId, nonce, null, gasLimit, to, value, data, Collections.emptyList());
this.maxPriorityFeePerGas = maxPriorityFeePerGas;
this.maxFeePerGas = maxFeePerGas;
}

public Transaction1559(
long chainId,
BigInteger nonce,
BigInteger gasLimit,
String to,
BigInteger value,
String data,
BigInteger maxPriorityFeePerGas,
BigInteger maxFeePerGas,
List<AccessListObject> accessList) {
super(chainId, nonce, null, gasLimit, to, value, data, accessList);
this.maxPriorityFeePerGas = maxPriorityFeePerGas;
this.maxFeePerGas = maxFeePerGas;
}
Expand Down Expand Up @@ -83,7 +96,7 @@ public List<RlpType> asRlpValues(Sign.SignatureData signatureData) {
result.add(RlpString.create(data));

// access list
result.add(new RlpList());
result.add(new RlpList(rlpAccessListRlp()));

if (signatureData != null) {
result.add(RlpString.create(Sign.getRecId(signatureData, getChainId())));
Expand All @@ -103,7 +116,38 @@ public static Transaction1559 createEtherTransaction(
BigInteger maxPriorityFeePerGas,
BigInteger maxFeePerGas) {
return new Transaction1559(
chainId, nonce, gasLimit, to, value, "", maxPriorityFeePerGas, maxFeePerGas);
chainId,
nonce,
gasLimit,
to,
value,
"",
maxPriorityFeePerGas,
maxFeePerGas,
Collections.emptyList());
}

public static Transaction1559 createTransaction(
long chainId,
BigInteger nonce,
BigInteger gasLimit,
String to,
BigInteger value,
String data,
BigInteger maxPriorityFeePerGas,
BigInteger maxFeePerGas,
List<AccessListObject> accessList) {

return new Transaction1559(
chainId,
nonce,
gasLimit,
to,
value,
data,
maxPriorityFeePerGas,
maxFeePerGas,
accessList);
}

public static Transaction1559 createTransaction(
Expand All @@ -121,12 +165,13 @@ public static Transaction1559 createTransaction(
}

@Override
public BigInteger getGasPrice() {
throw new UnsupportedOperationException("not available for 1559 transaction");
public TransactionType getType() {
return TransactionType.EIP1559;
}

public long getChainId() {
return chainId;
@Override
public BigInteger getGasPrice() {
throw new UnsupportedOperationException("not available for 1559 transaction");
}

public BigInteger getMaxPriorityFeePerGas() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ public List<RlpType> asRlpValues(Sign.SignatureData signatureData) {
result.add(RlpString.create(data));

// access list
result.add(new RlpList(rlpAccessListRlp()));

if (signatureData != null) {
result.add(RlpString.create(Sign.getRecId(signatureData, getChainId())));
result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR())));
result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS())));
}

return result;
}

protected List<RlpType> rlpAccessListRlp() {

List<AccessListObject> accessList = getAccessList();
List<RlpType> rlpAccessList = new ArrayList<>();
accessList.forEach(
Expand All @@ -89,15 +102,7 @@ public List<RlpType> asRlpValues(Sign.SignatureData signatureData) {
rlpAccessListObject.add(new RlpList(keyList));
rlpAccessList.add(new RlpList(rlpAccessListObject));
});
result.add(new RlpList(rlpAccessList));

if (signatureData != null) {
result.add(RlpString.create(Sign.getRecId(signatureData, getChainId())));
result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getR())));
result.add(RlpString.create(Bytes.trimLeadingZeroes(signatureData.getS())));
}

return result;
return rlpAccessList;
}

public static Transaction2930 createEtherTransaction(
Expand Down
51 changes: 51 additions & 0 deletions crypto/src/test/java/org/web3j/crypto/TransactionDecoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,32 @@ public void testDecoding1559() {
assertEquals(transaction1559.getData(), resultTransaction1559.getData());
}

@Test
public void testDecoding1559AccessList() {
final RawTransaction rawTransaction = createEip1559RawTransactionAccessList();
final Transaction1559 transaction1559 = (Transaction1559) rawTransaction.getTransaction();

final byte[] encodedMessage = TransactionEncoder.encode(rawTransaction);
final String hexMessage = Numeric.toHexString(encodedMessage);

final RawTransaction result = TransactionDecoder.decode(hexMessage);
assertTrue(result.getTransaction() instanceof Transaction1559);
final Transaction1559 resultTransaction1559 = (Transaction1559) result.getTransaction();

assertNotNull(result);
assertEquals(transaction1559.getChainId(), resultTransaction1559.getChainId());
assertEquals(transaction1559.getNonce(), resultTransaction1559.getNonce());
assertEquals(transaction1559.getMaxFeePerGas(), resultTransaction1559.getMaxFeePerGas());
assertEquals(
transaction1559.getMaxPriorityFeePerGas(),
resultTransaction1559.getMaxPriorityFeePerGas());
assertEquals(transaction1559.getGasLimit(), resultTransaction1559.getGasLimit());
assertEquals(transaction1559.getTo(), resultTransaction1559.getTo());
assertEquals(transaction1559.getValue(), resultTransaction1559.getValue());
assertEquals(transaction1559.getData(), resultTransaction1559.getData());
assertEquals(transaction1559.getAccessList(), resultTransaction1559.getAccessList());
}

@Test
public void testDecodingSigned1559() throws SignatureException {
final RawTransaction rawTransaction = createEip1559RawTransaction();
Expand Down Expand Up @@ -202,6 +228,31 @@ private static RawTransaction createEip1559RawTransaction() {
BigInteger.valueOf(1100000));
}

private static RawTransaction createEip1559RawTransactionAccessList() {
List<AccessListObject> accessList =
Stream.of(
new AccessListObject(
"0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
Stream.of(
"0x0000000000000000000000000000000000000000000000000000000000000003",
"0x0000000000000000000000000000000000000000000000000000000000000007")
.collect(toList())),
new AccessListObject(
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
Collections.emptyList()))
.collect(toList());
return RawTransaction.createTransaction(
3L,
BigInteger.valueOf(0),
BigInteger.valueOf(30000),
"0x627306090abab3a6e1400e9345bc60c78a8bef57",
BigInteger.valueOf(123),
"0x1000001111100000",
BigInteger.valueOf(5678),
BigInteger.valueOf(1100000),
accessList);
}

@Test
public void testDecoding2930() {
final RawTransaction rawTransaction = createEip2930RawTransaction();
Expand Down

0 comments on commit 01c003f

Please sign in to comment.