mirror of https://github.com/hyperledger/besu
[4844] Add encodingContext to TransactionEncoder and TransactionDecoder (#5820)
* Add decode type to TransactionDecoder * Refactoring TransactionDecoder * Invert methods order * Use Transaction encoder instead of writeTo * Move enter and leave list to inner method as pr suggestion * Size calculation should use opaque bytes instead of rlp --------- Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>pull/5875/head
parent
40273d7d3f
commit
1fa21e2f1a
@ -0,0 +1,74 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; |
||||
import org.hyperledger.besu.datatypes.AccessListEntry; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.TransactionType; |
||||
import org.hyperledger.besu.datatypes.Wei; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput; |
||||
|
||||
import java.math.BigInteger; |
||||
import java.util.function.Supplier; |
||||
|
||||
import com.google.common.base.Suppliers; |
||||
|
||||
class AccessListTransactionDecoder { |
||||
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM = |
||||
Suppliers.memoize(SignatureAlgorithmFactory::getInstance); |
||||
|
||||
public static Transaction decode(final RLPInput rlpInput) { |
||||
rlpInput.enterList(); |
||||
final Transaction.Builder preSignatureTransactionBuilder = |
||||
Transaction.builder() |
||||
.type(TransactionType.ACCESS_LIST) |
||||
.chainId(BigInteger.valueOf(rlpInput.readLongScalar())) |
||||
.nonce(rlpInput.readLongScalar()) |
||||
.gasPrice(Wei.of(rlpInput.readUInt256Scalar())) |
||||
.gasLimit(rlpInput.readLongScalar()) |
||||
.to( |
||||
rlpInput.readBytes( |
||||
addressBytes -> addressBytes.size() == 0 ? null : Address.wrap(addressBytes))) |
||||
.value(Wei.of(rlpInput.readUInt256Scalar())) |
||||
.payload(rlpInput.readBytes()) |
||||
.accessList( |
||||
rlpInput.readList( |
||||
accessListEntryRLPInput -> { |
||||
accessListEntryRLPInput.enterList(); |
||||
final AccessListEntry accessListEntry = |
||||
new AccessListEntry( |
||||
Address.wrap(accessListEntryRLPInput.readBytes()), |
||||
accessListEntryRLPInput.readList(RLPInput::readBytes32)); |
||||
accessListEntryRLPInput.leaveList(); |
||||
return accessListEntry; |
||||
})); |
||||
final byte recId = (byte) rlpInput.readIntScalar(); |
||||
final Transaction transaction = |
||||
preSignatureTransactionBuilder |
||||
.signature( |
||||
SIGNATURE_ALGORITHM |
||||
.get() |
||||
.createSignature( |
||||
rlpInput.readUInt256Scalar().toUnsignedBigInteger(), |
||||
rlpInput.readUInt256Scalar().toUnsignedBigInteger(), |
||||
recId)) |
||||
.build(); |
||||
rlpInput.leaveList(); |
||||
return transaction; |
||||
} |
||||
} |
@ -0,0 +1,109 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import static org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder.writeSignature; |
||||
|
||||
import org.hyperledger.besu.datatypes.AccessListEntry; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.Wei; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput; |
||||
|
||||
import java.math.BigInteger; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public class AccessListTransactionEncoder { |
||||
|
||||
public static void encode(final Transaction transaction, final RLPOutput rlpOutput) { |
||||
rlpOutput.startList(); |
||||
encodeAccessListInner( |
||||
transaction.getChainId(), |
||||
transaction.getNonce(), |
||||
transaction.getGasPrice().orElseThrow(), |
||||
transaction.getGasLimit(), |
||||
transaction.getTo(), |
||||
transaction.getValue(), |
||||
transaction.getPayload(), |
||||
transaction |
||||
.getAccessList() |
||||
.orElseThrow( |
||||
() -> |
||||
new IllegalStateException( |
||||
"Developer error: access list should be guaranteed to be present")), |
||||
rlpOutput); |
||||
rlpOutput.writeIntScalar(transaction.getSignature().getRecId()); |
||||
writeSignature(transaction, rlpOutput); |
||||
rlpOutput.endList(); |
||||
} |
||||
|
||||
public static void encodeAccessListInner( |
||||
final Optional<BigInteger> chainId, |
||||
final long nonce, |
||||
final Wei gasPrice, |
||||
final long gasLimit, |
||||
final Optional<Address> to, |
||||
final Wei value, |
||||
final Bytes payload, |
||||
final List<AccessListEntry> accessList, |
||||
final RLPOutput rlpOutput) { |
||||
rlpOutput.writeBigIntegerScalar(chainId.orElseThrow()); |
||||
rlpOutput.writeLongScalar(nonce); |
||||
rlpOutput.writeUInt256Scalar(gasPrice); |
||||
rlpOutput.writeLongScalar(gasLimit); |
||||
rlpOutput.writeBytes(to.map(Bytes::copy).orElse(Bytes.EMPTY)); |
||||
rlpOutput.writeUInt256Scalar(value); |
||||
rlpOutput.writeBytes(payload); |
||||
/* |
||||
Access List encoding should look like this |
||||
where hex strings represent raw bytes |
||||
[ |
||||
[ |
||||
"0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae", |
||||
[ |
||||
"0x0000000000000000000000000000000000000000000000000000000000000003", |
||||
"0x0000000000000000000000000000000000000000000000000000000000000007" |
||||
] |
||||
], |
||||
[ |
||||
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413", |
||||
[] |
||||
] |
||||
] */ |
||||
writeAccessList(rlpOutput, Optional.of(accessList)); |
||||
} |
||||
|
||||
public static void writeAccessList( |
||||
final RLPOutput out, final Optional<List<AccessListEntry>> accessListEntries) { |
||||
if (accessListEntries.isEmpty()) { |
||||
out.writeEmptyList(); |
||||
} else { |
||||
out.writeList( |
||||
accessListEntries.get(), |
||||
(accessListEntry, accessListEntryRLPOutput) -> { |
||||
accessListEntryRLPOutput.startList(); |
||||
out.writeBytes(accessListEntry.address()); |
||||
out.writeList( |
||||
accessListEntry.storageKeys(), |
||||
(storageKeyBytes, storageKeyBytesRLPOutput) -> |
||||
storageKeyBytesRLPOutput.writeBytes(storageKeyBytes)); |
||||
accessListEntryRLPOutput.endList(); |
||||
}); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,50 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import org.hyperledger.besu.datatypes.Blob; |
||||
import org.hyperledger.besu.datatypes.KZGCommitment; |
||||
import org.hyperledger.besu.datatypes.KZGProof; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Class responsible for decoding blob transactions from the transaction pool. Blob transactions |
||||
* have two network representations. During transaction gossip responses (PooledTransactions), the |
||||
* EIP-2718 TransactionPayload of the blob transaction is wrapped to become: rlp([tx_payload_body, |
||||
* blobs, commitments, proofs]). |
||||
*/ |
||||
public class BlobPooledTransactionDecoder { |
||||
|
||||
/** |
||||
* Decodes a blob transaction from the provided RLP input. |
||||
* |
||||
* @param input the RLP input to decode |
||||
* @return the decoded transaction |
||||
*/ |
||||
public static Transaction decode(final RLPInput input) { |
||||
input.enterList(); |
||||
final Transaction.Builder builder = Transaction.builder(); |
||||
BlobTransactionDecoder.readTransactionPayloadInner(builder, input); |
||||
List<Blob> blobs = input.readList(Blob::readFrom); |
||||
List<KZGCommitment> commitments = input.readList(KZGCommitment::readFrom); |
||||
List<KZGProof> proofs = input.readList(KZGProof::readFrom); |
||||
input.leaveList(); |
||||
builder.kzgBlobs(commitments, blobs, proofs); |
||||
return builder.build(); |
||||
} |
||||
} |
@ -0,0 +1,47 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import static org.slf4j.LoggerFactory.getLogger; |
||||
|
||||
import org.hyperledger.besu.datatypes.Blob; |
||||
import org.hyperledger.besu.datatypes.KZGCommitment; |
||||
import org.hyperledger.besu.datatypes.KZGProof; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput; |
||||
|
||||
import java.security.InvalidParameterException; |
||||
|
||||
import org.slf4j.Logger; |
||||
|
||||
public class BlobPooledTransactionEncoder { |
||||
private static final Logger LOG = getLogger(BlobPooledTransactionEncoder.class); |
||||
static final String NO_BLOBS_ERROR = |
||||
"Transaction with no blobsWithCommitments cannot be encoded for Pooled Transaction"; |
||||
|
||||
public static void encode(final Transaction transaction, final RLPOutput out) { |
||||
LOG.trace("Encoding transaction with blobs {}", transaction); |
||||
var blobsWithCommitments = transaction.getBlobsWithCommitments(); |
||||
if (blobsWithCommitments.isEmpty() || blobsWithCommitments.get().getBlobs().isEmpty()) { |
||||
throw new InvalidParameterException(NO_BLOBS_ERROR); |
||||
} |
||||
out.startList(); |
||||
BlobTransactionEncoder.encode(transaction, out); |
||||
out.writeList(blobsWithCommitments.get().getBlobs(), Blob::writeTo); |
||||
out.writeList(blobsWithCommitments.get().getKzgCommitments(), KZGCommitment::writeTo); |
||||
out.writeList(blobsWithCommitments.get().getKzgProofs(), KZGProof::writeTo); |
||||
out.endList(); |
||||
} |
||||
} |
@ -0,0 +1,74 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; |
||||
import org.hyperledger.besu.datatypes.AccessListEntry; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.TransactionType; |
||||
import org.hyperledger.besu.datatypes.Wei; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput; |
||||
|
||||
import java.math.BigInteger; |
||||
import java.util.function.Supplier; |
||||
|
||||
import com.google.common.base.Suppliers; |
||||
|
||||
public class EIP1559TransactionDecoder { |
||||
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM = |
||||
Suppliers.memoize(SignatureAlgorithmFactory::getInstance); |
||||
|
||||
public static Transaction decode(final RLPInput input) { |
||||
input.enterList(); |
||||
final BigInteger chainId = input.readBigIntegerScalar(); |
||||
final Transaction.Builder builder = |
||||
Transaction.builder() |
||||
.type(TransactionType.EIP1559) |
||||
.chainId(chainId) |
||||
.nonce(input.readLongScalar()) |
||||
.maxPriorityFeePerGas(Wei.of(input.readUInt256Scalar())) |
||||
.maxFeePerGas(Wei.of(input.readUInt256Scalar())) |
||||
.gasLimit(input.readLongScalar()) |
||||
.to(input.readBytes(v -> v.size() == 0 ? null : Address.wrap(v))) |
||||
.value(Wei.of(input.readUInt256Scalar())) |
||||
.payload(input.readBytes()) |
||||
.accessList( |
||||
input.readList( |
||||
accessListEntryRLPInput -> { |
||||
accessListEntryRLPInput.enterList(); |
||||
final AccessListEntry accessListEntry = |
||||
new AccessListEntry( |
||||
Address.wrap(accessListEntryRLPInput.readBytes()), |
||||
accessListEntryRLPInput.readList(RLPInput::readBytes32)); |
||||
accessListEntryRLPInput.leaveList(); |
||||
return accessListEntry; |
||||
})); |
||||
final byte recId = (byte) input.readIntScalar(); |
||||
final Transaction transaction = |
||||
builder |
||||
.signature( |
||||
SIGNATURE_ALGORITHM |
||||
.get() |
||||
.createSignature( |
||||
input.readUInt256Scalar().toUnsignedBigInteger(), |
||||
input.readUInt256Scalar().toUnsignedBigInteger(), |
||||
recId)) |
||||
.build(); |
||||
input.leaveList(); |
||||
return transaction; |
||||
} |
||||
} |
@ -0,0 +1,41 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import static org.hyperledger.besu.ethereum.core.encoding.AccessListTransactionEncoder.writeAccessList; |
||||
import static org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder.writeSignatureAndRecoveryId; |
||||
|
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public class EIP1559TransactionEncoder { |
||||
|
||||
public static void encode(final Transaction transaction, final RLPOutput out) { |
||||
out.startList(); |
||||
out.writeBigIntegerScalar(transaction.getChainId().orElseThrow()); |
||||
out.writeLongScalar(transaction.getNonce()); |
||||
out.writeUInt256Scalar(transaction.getMaxPriorityFeePerGas().orElseThrow()); |
||||
out.writeUInt256Scalar(transaction.getMaxFeePerGas().orElseThrow()); |
||||
out.writeLongScalar(transaction.getGasLimit()); |
||||
out.writeBytes(transaction.getTo().map(Bytes::copy).orElse(Bytes.EMPTY)); |
||||
out.writeUInt256Scalar(transaction.getValue()); |
||||
out.writeBytes(transaction.getPayload()); |
||||
writeAccessList(out, transaction.getAccessList()); |
||||
writeSignatureAndRecoveryId(transaction, out); |
||||
out.endList(); |
||||
} |
||||
} |
@ -0,0 +1,41 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
/** |
||||
* Enum representing the context in which a transaction is being encoded. This context is used to |
||||
* determine the appropriate encoding strategy for a transaction. |
||||
* |
||||
* <p>The context can be one of the following: |
||||
* |
||||
* <ul> |
||||
* <li>{@link #BLOCK_BODY}: The transaction is part of a block body. This context is used when |
||||
* encoding transactions for inclusion in a block. |
||||
* <li>{@link #POOLED_TRANSACTION}: The transaction is part of a transaction pool. This context is |
||||
* used when encoding transactions that are currently in the transaction pool, waiting to be |
||||
* included in a block. It is also used when encoding transactions for RPC calls related to |
||||
* the transaction pool. |
||||
* </ul> |
||||
*/ |
||||
public enum EncodingContext { |
||||
/** Represents the context where the transaction is part of a block body. */ |
||||
BLOCK_BODY, |
||||
|
||||
/** |
||||
* Represents the context where the transaction is part of a transaction pool. This context is |
||||
* also used when encoding transactions for RPC calls related to the transaction pool. |
||||
*/ |
||||
POOLED_TRANSACTION, |
||||
} |
@ -0,0 +1,76 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_PROTECTED_V_BASE; |
||||
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_PROTECTED_V_MIN; |
||||
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_UNPROTECTED_V_BASE; |
||||
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_UNPROTECTED_V_BASE_PLUS_1; |
||||
import static org.hyperledger.besu.ethereum.core.Transaction.TWO; |
||||
|
||||
import org.hyperledger.besu.crypto.SECPSignature; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithm; |
||||
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.datatypes.TransactionType; |
||||
import org.hyperledger.besu.datatypes.Wei; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPInput; |
||||
|
||||
import java.math.BigInteger; |
||||
import java.util.Optional; |
||||
import java.util.function.Supplier; |
||||
|
||||
import com.google.common.base.Suppliers; |
||||
|
||||
public class FrontierTransactionDecoder { |
||||
// Supplier for the signature algorithm
|
||||
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM = |
||||
Suppliers.memoize(SignatureAlgorithmFactory::getInstance); |
||||
|
||||
public static Transaction decode(final RLPInput input) { |
||||
input.enterList(); |
||||
final Transaction.Builder builder = |
||||
Transaction.builder() |
||||
.type(TransactionType.FRONTIER) |
||||
.nonce(input.readLongScalar()) |
||||
.gasPrice(Wei.of(input.readUInt256Scalar())) |
||||
.gasLimit(input.readLongScalar()) |
||||
.to(input.readBytes(v -> v.size() == 0 ? null : Address.wrap(v))) |
||||
.value(Wei.of(input.readUInt256Scalar())) |
||||
.payload(input.readBytes()); |
||||
|
||||
final BigInteger v = input.readBigIntegerScalar(); |
||||
final byte recId; |
||||
Optional<BigInteger> chainId = Optional.empty(); |
||||
if (v.equals(REPLAY_UNPROTECTED_V_BASE) || v.equals(REPLAY_UNPROTECTED_V_BASE_PLUS_1)) { |
||||
recId = v.subtract(REPLAY_UNPROTECTED_V_BASE).byteValueExact(); |
||||
} else if (v.compareTo(REPLAY_PROTECTED_V_MIN) > 0) { |
||||
chainId = Optional.of(v.subtract(REPLAY_PROTECTED_V_BASE).divide(TWO)); |
||||
recId = v.subtract(TWO.multiply(chainId.get()).add(REPLAY_PROTECTED_V_BASE)).byteValueExact(); |
||||
} else { |
||||
throw new RuntimeException( |
||||
String.format("An unsupported encoded `v` value of %s was found", v)); |
||||
} |
||||
final BigInteger r = input.readUInt256Scalar().toUnsignedBigInteger(); |
||||
final BigInteger s = input.readUInt256Scalar().toUnsignedBigInteger(); |
||||
final SECPSignature signature = SIGNATURE_ALGORITHM.get().createSignature(r, s, recId); |
||||
|
||||
input.leaveList(); |
||||
|
||||
chainId.ifPresent(builder::chainId); |
||||
return builder.signature(signature).build(); |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
||||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
||||
* specific language governing permissions and limitations under the License. |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.core.encoding; |
||||
|
||||
import static org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder.writeSignatureAndV; |
||||
|
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.rlp.RLPOutput; |
||||
|
||||
import org.apache.tuweni.bytes.Bytes; |
||||
|
||||
public class FrontierTransactionEncoder { |
||||
public static void encode(final Transaction transaction, final RLPOutput out) { |
||||
out.startList(); |
||||
out.writeLongScalar(transaction.getNonce()); |
||||
out.writeUInt256Scalar(transaction.getGasPrice().orElseThrow()); |
||||
out.writeLongScalar(transaction.getGasLimit()); |
||||
out.writeBytes(transaction.getTo().map(Bytes::copy).orElse(Bytes.EMPTY)); |
||||
out.writeUInt256Scalar(transaction.getValue()); |
||||
out.writeBytes(transaction.getPayload()); |
||||
writeSignatureAndV(transaction, out); |
||||
out.endList(); |
||||
} |
||||
} |
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue