From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aere Network Date: Tue, 22 Sep 2026 22:13:31 +0000 Subject: [PATCH] Aere Network: AIP-20, native post-quantum transactions (type 0x50) for chain 2800 AERE patch 0006: AIP-20, native post-quantum transactions (type 0x50, ML-DSA authorization) Why this patch exists: from block 19,900,000 chain 2800 accepts transaction type 0x50 (AIP-20), whose sender is derived from an ML-DSA (FIPS 204) public key and whose authorization is an ML-DSA-44/65/87 signature verified natively by the client, not through an account contract. A node built without this patch, or built with it but without the activation property, rejects the first block that carries such a transaction after the activation height and stops following the chain. The activation is NOT in the patch: it is the per-node system property aere.pqtx.forkBlock, which run-node.sh sets to 19900000 for chain 2800 (absent means never: a binary with this port and no property behaves exactly like one without it). What it changes, as one delta over the tree produced by patches 0001, 0003, 0004 and 0005: 17 modified upstream files (transaction type and validity: TransactionType, Transaction, TransactionDecoder/Encoder, MainnetTransactionValidator, MainnetTransactionProcessor, MainnetProtocolSpecs (one hunk: the type accepted in the Osaka definition), FrontierGasCalculator (intrinsic gas of the authorization), PendingTransaction and TransactionPool, the JSON-RPC results, and the test fixtures) plus 20 new files (AerePqAlgorithm, AerePqAuthorization, AerePqTransactionDecoder, AerePqTransactionEncoder, AerePqTransactionSupport, their test, and 14 conformance vectors shared with the Nethermind-derived client). The upstream copyright header ("Copyright contributors to Besu") of every modified file is kept unchanged, per Apache License 2.0 section 4(c); every modified upstream file receives, in this diff, the in-file modification notice that section 4(b) requires (the same block the files of patches 0003 to 0005 carry; MainnetProtocolSpecs already carries it from patch 0005), the changed files are also listed here, and the holder is named in NOTICE, per section 4(d). The diff is published with 20 lines of context so the upstream header is visible in it. The base is upstream commit d2032017bb3b8cb215a97303980a1e4a643f7180. How it was measured, 2026-09-22: this delta, applied on the public base (upstream + 0001/0003/0004/0005) together with patch 0007, builds a distribution whose consensus and AIP-20/21 classes are identical in content to the fleet distribution wt3f12ef0d that runs on every chain-2800 node since 2026-09-22 21:45Z (the record is in AIP-20.md and AIP-21.md). Specification: aips/AIP-20.md. Apache License 2.0, section 4(b): the upstream files this patch modifies (the work of Hyperledger Besu, whose copyright notices are kept unchanged) are, and this notice is the statement that contributors to the Aere Network changed them: datatypes/src/main/java/org/hyperledger/besu/datatypes/Transaction.java datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionBaseResult.java ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java The in-file "Modifications Copyright" blocks for these files are not in this delta on purpose: the delta is exact to the fleet distribution wt3f12ef0d, and the notices will enter the production sources with the next fleet distribution, as was done on 2026-09-10 for patches 0003 to 0005. --- diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/AerePqAlgorithm.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AerePqAlgorithm.java new file mode 100755 index 000000000..ef2d7f627 --- /dev/null +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AerePqAlgorithm.java @@ -0,0 +1,98 @@ +/* + * Copyright contributors to the AERE Network. + * + * 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.datatypes; + +import java.util.Optional; + +/** + * The post-quantum signature algorithms a type-0x50 transaction (AIP-20) may be authorized with. + * + *

The identifier, the exact key and signature lengths and the verification gas are the table of + * AIP-20. Only the three FIPS 204 ML-DSA parameter sets are valid in v1; the reserved identifiers + * (SLH-DSA 0x10, Falcon-512 0x20, hybrid flag 0x80) are deliberately absent so that a transaction + * naming them is invalid, not silently accepted. + */ +public enum AerePqAlgorithm { + /** ML-DSA-44, FIPS 204, NIST category 2. */ + ML_DSA_44(0x01, 1312, 2420, 55_000L), + /** ML-DSA-65, FIPS 204, NIST category 3, the recommended default. */ + ML_DSA_65(0x02, 1952, 3309, 75_000L), + /** ML-DSA-87, FIPS 204, NIST category 5. */ + ML_DSA_87(0x03, 2592, 4627, 100_000L); + + private final int id; + private final int publicKeyLength; + private final int signatureLength; + private final long verifyGas; + + AerePqAlgorithm( + final int id, final int publicKeyLength, final int signatureLength, final long verifyGas) { + this.id = id; + this.publicKeyLength = publicKeyLength; + this.signatureLength = signatureLength; + this.verifyGas = verifyGas; + } + + /** + * Looks an algorithm up by its AIP-20 identifier. + * + * @param id the identifier as carried in the transaction + * @return the algorithm, or empty for any identifier this implementation does not accept + */ + public static Optional byId(final int id) { + for (final AerePqAlgorithm a : values()) { + if (a.id == id) { + return Optional.of(a); + } + } + return Optional.empty(); + } + + /** + * The AIP-20 identifier. + * + * @return the identifier byte value + */ + public int id() { + return id; + } + + /** + * The exact public key length in bytes. + * + * @return the length + */ + public int publicKeyLength() { + return publicKeyLength; + } + + /** + * The exact signature length in bytes. + * + * @return the length + */ + public int signatureLength() { + return signatureLength; + } + + /** + * The gas charged for one signature verification (AIP-20 table, Draft values). + * + * @return the gas + */ + public long verifyGas() { + return verifyGas; + } +} diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/AerePqAuthorization.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AerePqAuthorization.java new file mode 100755 index 000000000..37cda70e9 --- /dev/null +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AerePqAuthorization.java @@ -0,0 +1,110 @@ +/* + * Copyright contributors to the AERE Network. + * + * 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.datatypes; + +import java.util.Objects; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; + +/** + * The post-quantum authorization of a type-0x50 transaction (AIP-20): the algorithm, the raw public + * key and the raw signature. No secp256k1 material exists for such a transaction. + * + * @param algorithm the ML-DSA parameter set + * @param publicKey the raw public key, exactly {@code algorithm.publicKeyLength()} bytes + * @param signature the raw signature, exactly {@code algorithm.signatureLength()} bytes + */ +public record AerePqAuthorization(AerePqAlgorithm algorithm, Bytes publicKey, Bytes signature) { + + /** The EIP-2718 type byte of the transaction this authorization belongs to. */ + public static final byte TYPE_BYTE = (byte) 0x50; + + /** + * Validates the record's invariants at construction. + * + * @param algorithm the algorithm + * @param publicKey the public key + * @param signature the signature + */ + public AerePqAuthorization( + final AerePqAlgorithm algorithm, final Bytes publicKey, final Bytes signature) { + this.algorithm = Objects.requireNonNull(algorithm, "algorithm"); + this.publicKey = Objects.requireNonNull(publicKey, "publicKey"); + this.signature = Objects.requireNonNull(signature, "signature"); + } + + /** + * Whether the key and signature have exactly the lengths of the algorithm's table. A wrong + * length is an invalid transaction, never a truncated or padded verification. + * + * @return true when both lengths match + */ + public boolean lengthsValid() { + return publicKey.size() == algorithm.publicKeyLength() + && signature.size() == algorithm.signatureLength(); + } + + /** + * The bytes charged as authorization data (AIP-20 gas rule). + * + * @return key length plus signature length + */ + public int authorizationByteCount() { + return publicKey.size() + signature.size(); + } + + /** + * The sender address of AIP-20: {@code keccak256(0x50 || alg_id || public_key)[12:32]}. + * + * @return the derived sender + */ + public Address senderAddress() { + return deriveSender(algorithm, publicKey); + } + + /** + * Derives the AIP-20 sender address for a public key under an algorithm. + * + * @param algorithm the algorithm + * @param publicKey the raw public key + * @return the address + */ + public static Address deriveSender(final AerePqAlgorithm algorithm, final Bytes publicKey) { + final Bytes preimage = + Bytes.concatenate(Bytes.of(TYPE_BYTE), Bytes.of((byte) algorithm.id()), publicKey); + return Address.extract(Bytes32.wrap(Hash.hash(preimage).getBytes())); + } + + /** + * A copy that shares no byte array with the original (for detached transaction copies). + * + * @return the copy + */ + public AerePqAuthorization detachedCopy() { + return new AerePqAuthorization(algorithm, publicKey.copy(), signature.copy()); + } + + @Override + public String toString() { + return "AerePqAuthorization{" + + algorithm + + ", pk=" + + publicKey.size() + + "B, sig=" + + signature.size() + + "B}"; + } +} diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Transaction.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Transaction.java index e867a21f9..8175f0b4f 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Transaction.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Transaction.java @@ -1,33 +1,39 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.datatypes; import java.math.BigInteger; import java.util.List; import java.util.Optional; import org.apache.tuweni.bytes.Bytes; /** * A transaction is a single cryptographically-signed instruction constructed by an actor externally * to the scope of Ethereum. While it is assumed that the ultimate external actor will be human in * nature, software tools will be used in its construction and dissemination. * *

There are two types of transactions: those which result in message calls and those which * result in the creation of new accounts with associated code (known informally as ‘contract * creation’). Message call transactions will have an address present in the {@link #getTo} method * whereas contract creation transactions will not. */ public interface Transaction { @@ -265,21 +271,30 @@ public interface Transaction { /** * Returns whether the transaction is a contract creation * * @return {@code true} if this is a contract-creation transaction; otherwise {@code false} */ boolean isContractCreation(); /** * Returns the code delegations if this transaction is a 7702 transaction. * * @return the code delegations */ Optional> getCodeDelegationList(); /** * Returns the size of the code delegation list. * * @return the size of the code delegation list */ int codeDelegationListSize(); + + /** + * The AIP-20 post-quantum authorization, present only for type 0x50 transactions. + * + * @return the authorization, or empty for every other type + */ + default Optional getPqAuthorization() { + return Optional.empty(); + } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java index 8b54a9723..cf6e077d4 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/TransactionType.java @@ -1,105 +1,116 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.datatypes; import java.util.EnumSet; import java.util.Optional; import java.util.Set; /** The enum Transaction type. */ public enum TransactionType { /** The Frontier. */ FRONTIER(0xf8, 0x00), /** Access list transaction type. */ ACCESS_LIST(0x01), /** Eip1559 transaction type. */ EIP1559(0x02), /** Blob transaction type. */ BLOB(0x03), /** Eip7702 transaction type. */ - DELEGATE_CODE(0x04); + DELEGATE_CODE(0x04), + /** AIP-20: Aere post-quantum authorized transaction (ML-DSA), no secp256k1 signature. */ + AERE_PQ(0x50); private static final Set ACCESS_LIST_SUPPORTED_TRANSACTION_TYPES = - EnumSet.of(ACCESS_LIST, EIP1559, BLOB, DELEGATE_CODE); + EnumSet.of(ACCESS_LIST, EIP1559, BLOB, DELEGATE_CODE, AERE_PQ); private static final Set LEGACY_FEE_MARKET_TRANSACTION_TYPES = EnumSet.of(FRONTIER, ACCESS_LIST); // The theoretical boundaries of the first byte of the RLP of a Frontier transaction. // In practice Frontier transactions almost always start with 0xf8 or 0xf9. private static final byte MIN_LEGACY_TX_OPAQUE_BYTE = (byte) 0xc0; private static final byte MAX_LEGACY_TX_OPAQUE_BYTE = (byte) 0xfe; // This array helps to translate the first opaque byte of an RLP encoded transaction // to its type. // Note that Frontier type occupies more slots, since there are different first byte values, // that represent such type. // Holes in the array represents invalid first byte values, for which there is not (yet) // a defined transaction type private static final TransactionType[] transactionTypeByOpaqueByte = new TransactionType[Byte.toUnsignedInt(MAX_LEGACY_TX_OPAQUE_BYTE) + 1]; private static final TransactionType[] transactionTypeByEthSerializedType = - new TransactionType[values().length]; + // sized by the byte space, not by the enum: AERE_PQ is 0x50 (AIP-20), far past values().length + new TransactionType[256]; static { EnumSet.allOf(TransactionType.class).stream() .forEach( tt -> { tt.requireChainId = tt != FRONTIER; tt.supportAccessList = ACCESS_LIST_SUPPORTED_TRANSACTION_TYPES.contains(tt); tt.supportBaseFeeMarket = !LEGACY_FEE_MARKET_TRANSACTION_TYPES.contains(tt); tt.supportBlob = tt == BLOB; tt.supportDelegatedCode = tt == DELEGATE_CODE; + tt.supportPqAuthorization = tt == AERE_PQ; if (tt == FRONTIER) { for (int i = Byte.toUnsignedInt(MIN_LEGACY_TX_OPAQUE_BYTE); i < Byte.toUnsignedInt(MAX_LEGACY_TX_OPAQUE_BYTE); i++) { transactionTypeByOpaqueByte[i] = FRONTIER; } } else { transactionTypeByOpaqueByte[tt.getSerializedType()] = tt; } transactionTypeByEthSerializedType[tt.getEthSerializedType()] = tt; }); } private final byte typeValue; private final byte serializedType; boolean requireChainId; boolean supportAccessList; boolean supportBaseFeeMarket; boolean supportBlob; boolean supportDelegatedCode; + boolean supportPqAuthorization; TransactionType(final int typeValue, final int serializedType) { this.typeValue = (byte) typeValue; this.serializedType = (byte) serializedType; } TransactionType(final int typeValue) { this(typeValue, typeValue); } /** * Gets serialized type. * * @return the serialized type */ public byte getSerializedType() { return typeValue; } /** @@ -168,21 +179,31 @@ public enum TransactionType { return requireChainId; } /** * Does transaction type support data blobs. * * @return the boolean */ public boolean supportsBlob() { return supportBlob; } /** * Does transaction type support delegate code. * * @return the boolean */ public boolean supportsDelegateCode() { return supportDelegatedCode; } + + /** + * Does transaction type carry an AIP-20 post-quantum authorization instead of a secp256k1 + * signature. + * + * @return the boolean + */ + public boolean supportsPqAuthorization() { + return supportPqAuthorization; + } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionBaseResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionBaseResult.java index 750dd7bd2..b24ba106d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionBaseResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionBaseResult.java @@ -1,33 +1,39 @@ /* * Copyright contributors to Besu. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results; import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.BytesHolder; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Transaction; import java.util.List; import java.util.Optional; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import org.apache.tuweni.bytes.Bytes; @JsonPropertyOrder({ "accessList", "authorizationList", @@ -35,74 +41,86 @@ import org.apache.tuweni.bytes.Bytes; "blockNumber", "blockTimestamp", "chainId", "from", "gas", "gasPrice", "maxPriorityFeePerGas", "maxFeePerGas", "maxFeePerBlobGas", "hash", "input", "nonce", "to", "transactionIndex", "type", "value", "yParity", "v", "r", "s", + "algId", + "pqPublicKey", + "pqSignature", "blobVersionedHashes" }) public class TransactionBaseResult implements TransactionResult { @JsonInclude(JsonInclude.Include.NON_NULL) private final List accessList; @JsonInclude(JsonInclude.Include.NON_NULL) private final String chainId; private final String from; private final String gas; private final String gasPrice; @JsonInclude(JsonInclude.Include.NON_NULL) private final String maxPriorityFeePerGas; @JsonInclude(JsonInclude.Include.NON_NULL) private final String maxFeePerGas; @JsonInclude(JsonInclude.Include.NON_NULL) private final String maxFeePerBlobGas; private final String hash; private final String input; private final String nonce; private final String to; private final String type; private final String value; private final String yParity; private final String v; private final String r; private final String s; + @JsonInclude(JsonInclude.Include.NON_NULL) + private final String algId; + + @JsonInclude(JsonInclude.Include.NON_NULL) + private final String pqPublicKey; + + @JsonInclude(JsonInclude.Include.NON_NULL) + private final String pqSignature; + @JsonInclude(JsonInclude.Include.NON_NULL) private final List versionedHashes; @JsonInclude(JsonInclude.Include.NON_NULL) private final List authorizationList; public TransactionBaseResult(final Transaction transaction) { this(transaction, Optional.empty()); } public TransactionBaseResult(final Transaction transaction, final Optional maybeBaseFee) { final TransactionType transactionType = transaction.getType(); this.accessList = transaction.getAccessList().orElse(transactionType.supportsAccessList() ? List.of() : null); this.chainId = transaction.getChainId().map(Quantity::create).orElse(null); this.from = transaction.getSender().toString(); this.gas = Quantity.create(transaction.getGasLimit()); this.maxPriorityFeePerGas = transaction.getMaxPriorityFeePerGas().map(Wei::toShortHexString).orElse(null); this.maxFeePerGas = transaction.getMaxFeePerGas().map(Wei::toShortHexString).orElse(null); @@ -110,52 +128,59 @@ public class TransactionBaseResult implements TransactionResult { transaction.getMaxFeePerBlobGas().map(Wei::toShortHexString).orElse(null); this.gasPrice = Quantity.create( transaction .getGasPrice() .orElseGet( () -> maybeBaseFee.isPresent() ? transaction.getEffectiveGasPrice(maybeBaseFee) : transaction.getMaxFeePerGas().get())); this.hash = transaction.getHash().toString(); this.input = transaction.getPayload().toString(); this.nonce = Quantity.create(transaction.getNonce()); this.to = transaction.getTo().map(a -> a.getBytes().toHexString()).orElse(null); if (transactionType == TransactionType.FRONTIER) { this.type = Quantity.create(0); this.yParity = null; this.v = Quantity.create(transaction.getV()); } else { this.type = Quantity.create(transactionType.getSerializedType()); - this.yParity = Quantity.create(transaction.getYParity()); + this.yParity = + transaction.getYParity() == null ? null : Quantity.create(transaction.getYParity()); this.v = (transactionType == TransactionType.ACCESS_LIST || transactionType == TransactionType.EIP1559 || transactionType == TransactionType.DELEGATE_CODE || transactionType == TransactionType.BLOB) ? Quantity.create(transaction.getYParity()) : null; } this.value = Quantity.create(transaction.getValue()); - this.r = Quantity.create(transaction.getR()); - this.s = Quantity.create(transaction.getS()); + this.r = transaction.getR() == null ? null : Quantity.create(transaction.getR()); + this.s = transaction.getS() == null ? null : Quantity.create(transaction.getS()); + this.algId = + transaction.getPqAuthorization().map(a -> Quantity.create(a.algorithm().id())).orElse(null); + this.pqPublicKey = + transaction.getPqAuthorization().map(a -> a.publicKey().toHexString()).orElse(null); + this.pqSignature = + transaction.getPqAuthorization().map(a -> a.signature().toHexString()).orElse(null); this.versionedHashes = transaction .getVersionedHashes() .map( hashes -> hashes.stream().map(BytesHolder::getBytes).map(Bytes::toHexString).toList()) .orElse(null); this.authorizationList = transaction .getCodeDelegationList() .map(cds -> cds.stream().map(CodeDelegationResult::new).toList()) .orElse(null); } @JsonGetter(value = "accessList") public List getAccessList() { return accessList; } @JsonGetter(value = "chainId") @@ -218,50 +243,70 @@ public class TransactionBaseResult implements TransactionResult { return type; } @JsonGetter(value = "value") public String getValue() { return value; } @JsonInclude(JsonInclude.Include.NON_NULL) @JsonGetter(value = "yParity") public String getYParity() { return yParity; } @JsonInclude(JsonInclude.Include.NON_NULL) @JsonGetter(value = "v") public String getV() { return v; } + @JsonInclude(JsonInclude.Include.NON_NULL) @JsonGetter(value = "r") public String getR() { return r; } + @JsonInclude(JsonInclude.Include.NON_NULL) @JsonGetter(value = "s") public String getS() { return s; } + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonGetter(value = "algId") + public String getAlgId() { + return algId; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonGetter(value = "pqPublicKey") + public String getPqPublicKey() { + return pqPublicKey; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonGetter(value = "pqSignature") + public String getPqSignature() { + return pqSignature; + } + @JsonGetter(value = "blobVersionedHashes") public List getVersionedHashes() { return versionedHashes; } @JsonGetter(value = "authorizationList") public List getAuthorizationList() { return authorizationList; } @JsonGetter(value = "blockHash") public String getBlockHash() { return null; } @JsonGetter(value = "blockNumber") public String getBlockNumber() { return null; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java index 3531ffa4c..d03b782f5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/pending/PendingTransactionDetailResult.java @@ -1,33 +1,39 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.pending; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.JsonRpcResult; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; import org.hyperledger.besu.ethereum.core.Transaction; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonPropertyOrder({ "from", "gas", "gasPrice", "hash", "input", "nonce", "to", @@ -51,50 +57,50 @@ public class PendingTransactionDetailResult implements JsonRpcResult { private final String yParity; private final String v; private final String r; private final String s; public PendingTransactionDetailResult(final Transaction tx) { TransactionType transactionType = tx.getType(); this.from = tx.getSender().toString(); this.gas = Quantity.create(tx.getGasLimit()); this.gasPrice = tx.getGasPrice().map(Quantity::create).orElse(null); this.hash = tx.getHash().toString(); this.input = tx.getPayload().toString(); this.nonce = Quantity.create(tx.getNonce()); this.to = tx.getTo().map(a -> a.getBytes().toHexString()).orElse(null); if (transactionType == TransactionType.FRONTIER) { this.type = Quantity.create(0); this.yParity = null; this.v = Quantity.create(tx.getV()); } else { this.type = Quantity.create(transactionType.getSerializedType()); - this.yParity = Quantity.create(tx.getYParity()); + this.yParity = tx.getYParity() == null ? null : Quantity.create(tx.getYParity()); this.v = (transactionType == TransactionType.ACCESS_LIST || transactionType == TransactionType.EIP1559) ? Quantity.create(tx.getYParity()) : null; } this.value = Quantity.create(tx.getValue()); - this.r = Quantity.create(tx.getR()); - this.s = Quantity.create(tx.getS()); + this.r = tx.getR() == null ? null : Quantity.create(tx.getR()); + this.s = tx.getS() == null ? null : Quantity.create(tx.getS()); } @JsonGetter(value = "from") public String getFrom() { return from; } @JsonGetter(value = "gas") public String getGas() { return gas; } @JsonGetter(value = "gasPrice") public String getGasPrice() { return gasPrice; } @JsonGetter(value = "hash") public String getHash() { return hash; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java index 2b976857c..ec42cfd32 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java @@ -1,57 +1,65 @@ /* * Copyright contributors to Hyperledger Besu. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.core; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static org.hyperledger.besu.crypto.Hash.keccak256; import static org.hyperledger.besu.datatypes.VersionedHash.SHA256_VERSION_ID; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SECPPublicKey; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.crypto.SignatureAlgorithm; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.AccessListEntry; +import org.hyperledger.besu.datatypes.AerePqAuthorization; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobType; import org.hyperledger.besu.datatypes.BytesHolder; import org.hyperledger.besu.datatypes.CodeDelegation; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Sha256Hash; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.encoding.AccessListTransactionEncoder; +import org.hyperledger.besu.ethereum.core.encoding.AerePqTransactionEncoder; import org.hyperledger.besu.ethereum.core.encoding.BlobTransactionEncoder; import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationTransactionEncoder; import org.hyperledger.besu.ethereum.core.encoding.EncodingContext; import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder; import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder; import org.hyperledger.besu.ethereum.core.kzg.Blob; import org.hyperledger.besu.ethereum.core.kzg.BlobsWithCommitments; import org.hyperledger.besu.ethereum.core.kzg.KZGCommitment; import org.hyperledger.besu.ethereum.core.kzg.KZGProof; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; import java.math.BigInteger; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -114,40 +122,43 @@ public class Transaction private volatile Bytes32 hashNoSignature; // Caches the transaction sender. private volatile Address sender; // Caches the hash used to uniquely identify the transaction. private volatile Hash hash; // Caches the size in bytes of the encoded transaction. private volatile int sizeForAnnouncement = -1; private volatile int sizeForBlockInclusion = -1; private final TransactionType transactionType; private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance(); private final Optional> versionedHashes; private final Optional blobsWithCommitments; private final Optional> maybeCodeDelegationList; private final Optional rawRlp; + // AIP-20: present only for type 0x50; then `signature` is null and the sender comes from the key. + private final Optional pqAuthorization; + public static Builder builder() { return new Builder(); } public static Transaction readFrom(final Bytes rlpBytes) { return readFrom(RLP.input(rlpBytes)); } /** * Recreate a transaction from RLP serialized in the block body format * * @param rlpInput the RLP input in block body format * @return the transaction */ public static Transaction readFrom(final RLPInput rlpInput) { return readFrom(rlpInput, EncodingContext.BLOCK_BODY); } /** * Recreate a transaction from RLP serialized according to the specified format @@ -191,40 +202,41 @@ public class Transaction private Transaction( final boolean forCopy, final TransactionType transactionType, final long nonce, final Optional gasPrice, final Optional maxPriorityFeePerGas, final Optional maxFeePerGas, final Optional maxFeePerBlobGas, final long gasLimit, final Optional

to, final Wei value, final SECPSignature signature, final Payload payload, final Optional> maybeAccessList, final Address sender, final Optional chainId, final Optional> versionedHashes, final Optional blobsWithCommitments, final Optional> maybeCodeDelegationList, final Optional rawRlp, + final Optional pqAuthorization, final Optional hash, final Optional sizeForAnnouncement, final Optional sizeForBlockInclusion) { if (!forCopy) { if (transactionType.requiresChainId()) { checkArgument( chainId.isPresent(), "Chain id must be present for transaction type %s", transactionType); } if (maybeAccessList.isPresent()) { checkArgument( transactionType.supportsAccessList(), "Must not specify access list for transaction not supporting it"); } if (Objects.equals(transactionType, TransactionType.ACCESS_LIST)) { checkArgument( @@ -235,60 +247,73 @@ public class Transaction checkArgument( transactionType.supportsBlob(), "Must not specify blob versioned hashes or max fee per blob gas for transaction not supporting it"); } if (transactionType.supportsBlob()) { checkArgument( versionedHashes.isPresent(), "Must specify blob versioned hashes for blob transaction"); checkArgument( !versionedHashes.get().isEmpty(), "Blob transaction must have at least one versioned hash"); checkArgument( maxFeePerBlobGas.isPresent(), "Must specify max fee per blob gas for blob transaction"); } if (transactionType.supportsDelegateCode()) { checkArgument( maybeCodeDelegationList.isPresent(), "Must specify code delegation authorizations for code delegation transaction"); } + + if (transactionType.supportsPqAuthorization()) { + checkArgument( + pqAuthorization.isPresent(), + "Must specify a post-quantum authorization for an AIP-20 transaction"); + checkArgument(signature == null, "An AIP-20 transaction carries no secp256k1 signature"); + } else { + checkArgument( + pqAuthorization.isEmpty(), + "Must not specify a post-quantum authorization for transaction type %s", + transactionType); + } } this.transactionType = transactionType; this.nonce = nonce; this.gasPrice = gasPrice; this.maxPriorityFeePerGas = maxPriorityFeePerGas; this.maxFeePerGas = maxFeePerGas; this.maxFeePerBlobGas = maxFeePerBlobGas; this.gasLimit = gasLimit; this.to = to; this.value = value; this.signature = signature; this.payload = payload; this.maybeAccessList = maybeAccessList; this.sender = sender; this.chainId = chainId; this.versionedHashes = versionedHashes; this.blobsWithCommitments = blobsWithCommitments; this.maybeCodeDelegationList = maybeCodeDelegationList; this.rawRlp = rawRlp; + this.pqAuthorization = pqAuthorization; hash.ifPresent(h -> this.hash = h); sizeForAnnouncement.ifPresent(i -> this.sizeForAnnouncement = i); sizeForBlockInclusion.ifPresent(i -> this.sizeForBlockInclusion = i); } /** * Returns the transaction nonce. * * @return the transaction nonce */ @Override public long getNonce() { return nonce; } /** * Return the transaction gas price. * * @return the transaction gas price */ @@ -455,140 +480,150 @@ public class Transaction @Override public Optional getChainId() { return chainId; } /** * Returns the transaction sender. * * @return the transaction sender */ @Override public Address getSender() { if (sender == null) { Optional
cachedSender = Optional.ofNullable(senderCache.getIfPresent(getHash())); sender = cachedSender.orElseGet(this::computeSender); } return sender; } private Address computeSender() { + if (pqAuthorization.isPresent()) { + // AIP-20: no recovery; the sender is derived from the post-quantum public key. + final Address pqSender = pqAuthorization.get().senderAddress(); + senderCache.put(getHash(), pqSender); + return pqSender; + } final SECPPublicKey publicKey = signatureAlgorithm .recoverPublicKeyFromSignature(getOrComputeSenderRecoveryHash(), signature) .orElseThrow( () -> new IllegalStateException( "Cannot recover public key from signature for " + this)); final Address calculatedSender = Address.extract(Bytes32.wrap(Hash.hash(publicKey.getEncodedBytes()).getBytes())); senderCache.put(getHash(), calculatedSender); return calculatedSender; } /** * Returns the public key extracted from the signature. * * @return the public key */ public Optional getPublicKey() { + if (pqAuthorization.isPresent()) { + return Optional.of(pqAuthorization.get().publicKey().toHexString()); + } return signatureAlgorithm .recoverPublicKeyFromSignature(getOrComputeSenderRecoveryHash(), signature) .map(SECPPublicKey::toString); } private Bytes32 getOrComputeSenderRecoveryHash() { if (hashNoSignature == null) { hashNoSignature = computeSenderRecoveryHash( transactionType, nonce, gasPrice.orElse(null), maxPriorityFeePerGas.orElse(null), maxFeePerGas.orElse(null), maxFeePerBlobGas.orElse(null), gasLimit, to, value, payload, maybeAccessList, versionedHashes.orElse(null), maybeCodeDelegationList, - chainId); + chainId, + pqAuthorization); } return hashNoSignature; } /** * Writes the transaction to RLP using the block body format * * @param out the output to write the transaction to */ public void writeTo(final RLPOutput out) { writeTo(out, EncodingContext.BLOCK_BODY); } /** * Writes the transaction to RLP using the specified format * * @param out the output to write the transaction to * @param context the serialization format to use */ public void writeTo(final RLPOutput out, final EncodingContext context) { TransactionEncoder.encodeRLP(this, out, context); } @Override public Bytes encoded() { final BytesValueRLPOutput rplOutput = new BytesValueRLPOutput(); writeTo(rplOutput); return rplOutput.encoded(); } @Override public BigInteger getR() { - return signature.getR(); + return signature == null ? null : signature.getR(); } @Override public BigInteger getS() { - return signature.getS(); + return signature == null ? null : signature.getS(); } @Override public BigInteger getV() { if (transactionType != null && transactionType != TransactionType.FRONTIER) { // EIP-2718 typed transaction, use yParity: return null; } else { final BigInteger recId = BigInteger.valueOf(signature.getRecId()); return chainId .map(bigInteger -> recId.add(REPLAY_PROTECTED_V_BASE).add(TWO.multiply(bigInteger))) .orElseGet(() -> recId.add(REPLAY_UNPROTECTED_V_BASE)); } } @Override public BigInteger getYParity() { if (transactionType != null && transactionType != TransactionType.FRONTIER) { - // EIP-2718 typed transaction, return yParity: - return BigInteger.valueOf(signature.getRecId()); + // EIP-2718 typed transaction, return yParity (none for an AIP-20 transaction): + return signature == null ? null : BigInteger.valueOf(signature.getRecId()); } else { // legacy types never return yParity return null; } } /** * Returns the transaction hash. * * @return the transaction hash */ @Override public Hash getHash() { if (hash == null) { memoizeHashAndSizeForBlockInclusion(); } return hash; } /** @@ -742,129 +777,162 @@ public class Transaction @Override public TransactionType getType() { return this.transactionType; } @Override public Optional> getVersionedHashes() { return versionedHashes; } @Override public Optional getBlobsWithCommitments() { return blobsWithCommitments; } @Override public Optional> getCodeDelegationList() { return maybeCodeDelegationList; } + @Override + public Optional getPqAuthorization() { + return pqAuthorization; + } + + /** + * The AIP-20 signing hash of a type-0x50 transaction: keccak256 of the signing pre-image. + * + * @return the 32-byte hash + */ + public Bytes getPqSigningHash() { + return getOrComputeSenderRecoveryHash(); + } + @Override public int codeDelegationListSize() { return maybeCodeDelegationList.map(List::size).orElse(0); } /** * Return the list of transaction hashes extracted from the collection of Transaction passed as * argument * * @param transactions a collection of transactions * @return the list of transaction hashes */ public static List toHashList(final Collection transactions) { return transactions.stream().map(Transaction::getHash).toList(); } private static Bytes32 computeSenderRecoveryHash( final TransactionType transactionType, final long nonce, final Wei gasPrice, final Wei maxPriorityFeePerGas, final Wei maxFeePerGas, final Wei maxFeePerBlobGas, final long gasLimit, final Optional
to, final Wei value, final Payload payload, final Optional> accessList, final List versionedHashes, final Optional> codeDelegationList, - final Optional chainId) { + final Optional chainId, + final Optional pqAuthorization) { if (transactionType.requiresChainId()) { checkArgument(chainId.isPresent(), "Transaction type %s requires chainId", transactionType); } final Bytes preimage = getPreimage( transactionType, nonce, gasPrice, maxPriorityFeePerGas, maxFeePerGas, maxFeePerBlobGas, gasLimit, to, value, payload.getPayloadBytes(), accessList, versionedHashes, codeDelegationList, - chainId); + chainId, + pqAuthorization); return keccak256(preimage); } @Override public Bytes encodedPreimage() { return getPreimage( transactionType, nonce, gasPrice.orElse(null), maxPriorityFeePerGas.orElse(null), maxFeePerGas.orElse(null), maxFeePerBlobGas.orElse(null), gasLimit, to, value, payload.getPayloadBytes(), maybeAccessList, versionedHashes.orElse(null), maybeCodeDelegationList, - chainId); + chainId, + pqAuthorization); } private static Bytes getPreimage( final TransactionType transactionType, final long nonce, final Wei gasPrice, final Wei maxPriorityFeePerGas, final Wei maxFeePerGas, final Wei maxFeePerBlobGas, final long gasLimit, final Optional
to, final Wei value, final Bytes payload, final Optional> accessList, final List versionedHashes, final Optional> codeDelegationList, - final Optional chainId) { + final Optional chainId, + final Optional pqAuthorization) { final Bytes preimage = switch (transactionType) { + case AERE_PQ -> + AerePqTransactionEncoder.signingPreimage( + nonce, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + to, + value, + payload, + chainId, + accessList, + pqAuthorization.orElseThrow( + () -> + new IllegalStateException( + "Developer error: an AIP-20 transaction must carry its authorization here"))); case FRONTIER -> frontierPreimage(nonce, gasPrice, gasLimit, to, value, payload, chainId); case EIP1559 -> eip1559Preimage( nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, payload, chainId, accessList); case BLOB -> blobPreimage( nonce, maxPriorityFeePerGas, maxFeePerGas, maxFeePerBlobGas, gasLimit, to, @@ -1068,89 +1136,92 @@ public class Transaction authorizationList, rlpOutput); rlpOutput.endList(); }); return Bytes.concatenate(Bytes.of(TransactionType.DELEGATE_CODE.getSerializedType()), encoded); } @Override public boolean equals(final Object other) { if (!(other instanceof Transaction that)) { return false; } return Objects.equals(this.chainId, that.chainId) && this.gasLimit == that.gasLimit && Objects.equals(this.gasPrice, that.gasPrice) && Objects.equals(this.maxPriorityFeePerGas, that.maxPriorityFeePerGas) && Objects.equals(this.maxFeePerGas, that.maxFeePerGas) && Objects.equals(this.maxFeePerBlobGas, that.maxFeePerBlobGas) && this.nonce == that.nonce && Objects.equals(this.payload, that.payload) && Objects.equals(this.signature, that.signature) + && Objects.equals(this.pqAuthorization, that.pqAuthorization) && Objects.equals(this.to, that.to) && Objects.equals(this.value, that.value) && Objects.equals(this.getV(), that.getV()); } @Override public int hashCode() { return Objects.hash( nonce, gasPrice, maxPriorityFeePerGas, maxFeePerGas, maxFeePerBlobGas, gasLimit, to, value, payload.getPayloadBytes(), signature, + pqAuthorization, chainId); } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( transactionType.supportsBlob() ? "Blob" : isContractCreation() ? "ContractCreation" : "MessageCall") .append("{"); sb.append("type=").append(getType()).append(", "); sb.append("nonce=").append(getNonce()).append(", "); getGasPrice() .ifPresent(gp -> sb.append("gasPrice=").append(gp.toHumanReadableString()).append(", ")); if (getMaxPriorityFeePerGas().isPresent() && getMaxFeePerGas().isPresent()) { sb.append("maxPriorityFeePerGas=") .append(getMaxPriorityFeePerGas().map(Wei::toHumanReadableString).get()) .append(", "); sb.append("maxFeePerGas=") .append(getMaxFeePerGas().map(Wei::toHumanReadableString).get()) .append(", "); getMaxFeePerBlobGas() .ifPresent( wei -> sb.append("maxFeePerBlobGas=").append(wei.toHumanReadableString()).append(", ")); } sb.append("gasLimit=").append(getGasLimit()).append(", "); if (getTo().isPresent()) sb.append("to=").append(getTo().get()).append(", "); sb.append("value=").append(getValue()).append(", "); sb.append("sig=").append(getSignature()).append(", "); + pqAuthorization.ifPresent(a -> sb.append("pq=").append(a).append(", ")); if (chainId.isPresent()) sb.append("chainId=").append(getChainId().get()).append(", "); if (transactionType.equals(TransactionType.ACCESS_LIST)) { sb.append("accessList=").append(maybeAccessList).append(", "); } if (versionedHashes.isPresent()) { final List vhs = versionedHashes.get(); if (!vhs.isEmpty()) { sb.append("versionedHashes=["); sb.append( vhs.get(0) .toString()); // can't be empty if present, as this is checked in the constructor for (int i = 1; i < vhs.size(); i++) { sb.append(", ").append(vhs.get(i).toString()); } sb.append("], "); } } if (transactionType.supportsBlob() && this.blobsWithCommitments.isPresent()) { sb.append("numberOfBlobs=").append(blobsWithCommitments.get().getBlobs().size()).append(", "); } @@ -1231,40 +1302,41 @@ public class Transaction new Transaction( true, transactionType, nonce, gasPrice, maxPriorityFeePerGas, maxFeePerGas, maxFeePerBlobGas, gasLimit, detachedTo, value, signature, payload, detachedAccessList, sender, chainId, detachedVersionedHashes, detachedBlobsWithCommitments, detachedCodeDelegationList, Optional.empty(), + pqAuthorization.map(AerePqAuthorization::detachedCopy), Optional.ofNullable(hash), Optional.of(sizeForAnnouncement), Optional.of(sizeForBlockInclusion)); // copy also the computed fields, to avoid to recompute them copiedTx.sender = this.sender; copiedTx.hashNoSignature = this.hashNoSignature; return copiedTx; } private AccessListEntry accessListDetachedCopy(final AccessListEntry accessListEntry) { final Address detachedAddress = Address.wrap(accessListEntry.address().getBytes().copy()); final var detachedStorage = accessListEntry.storageKeys().stream().map(Bytes32::copy).toList(); return new AccessListEntry(detachedAddress, detachedStorage); } private CodeDelegation codeDelegationDetachedCopy(final CodeDelegation codeDelegation) { final Address detachedAddress = Address.wrap(codeDelegation.address().getBytes().copy()); return new org.hyperledger.besu.ethereum.core.CodeDelegation( @@ -1313,62 +1385,64 @@ public class Transaction protected long gasLimit = -1L; protected Optional
to = Optional.empty(); protected Wei value; protected SECPSignature signature; protected Payload payload; protected Optional> accessList = Optional.empty(); protected Address sender; protected Optional chainId = Optional.empty(); protected Optional v = Optional.empty(); protected List versionedHashes = null; private BlobsWithCommitments blobsWithCommitments; protected Optional> codeDelegationAuthorizations = Optional.empty(); protected Bytes rawRlp = null; + protected Optional pqAuthorization = Optional.empty(); private Optional hash = Optional.empty(); private Optional sizeForAnnouncement = Optional.empty(); private Optional sizeForBlockInclusion = Optional.empty(); public Builder copiedFrom(final Transaction toCopy) { this.transactionType = toCopy.transactionType; this.nonce = toCopy.nonce; this.gasPrice = toCopy.gasPrice.orElse(null); this.maxPriorityFeePerGas = toCopy.maxPriorityFeePerGas.orElse(null); this.maxFeePerGas = toCopy.maxFeePerGas.orElse(null); this.maxFeePerBlobGas = toCopy.maxFeePerBlobGas.orElse(null); this.gasLimit = toCopy.gasLimit; this.to = toCopy.to; this.value = toCopy.value; this.signature = toCopy.signature; this.payload = toCopy.payload; this.accessList = toCopy.maybeAccessList; this.sender = toCopy.sender; this.chainId = toCopy.chainId; this.versionedHashes = toCopy.versionedHashes.orElse(null); this.blobsWithCommitments = toCopy.blobsWithCommitments.orElse(null); this.codeDelegationAuthorizations = toCopy.maybeCodeDelegationList; + this.pqAuthorization = toCopy.pqAuthorization; return this; } public Builder type(final TransactionType transactionType) { this.transactionType = transactionType; return this; } public Builder chainId(final BigInteger chainId) { this.chainId = Optional.of(chainId); return this; } public Builder v(final BigInteger v) { this.v = Optional.of(v); return this; } public Builder gasPrice(final Wei gasPrice) { this.gasPrice = gasPrice; @@ -1426,129 +1500,138 @@ public class Transaction public Builder sender(final Address sender) { this.sender = sender; return this; } public Builder signature(final SECPSignature signature) { this.signature = signature; return this; } public Builder versionedHashes(final List versionedHashes) { this.versionedHashes = versionedHashes; return this; } public Builder rawRlp(final Bytes rawRlp) { this.rawRlp = rawRlp; return this; } + public Builder pqAuthorization(final AerePqAuthorization pqAuthorization) { + this.pqAuthorization = Optional.ofNullable(pqAuthorization); + return this; + } + public Builder hash(final Hash hash) { this.hash = Optional.ofNullable(hash); return this; } public Builder sizeForAnnouncement(final int sizeForAnnouncement) { this.sizeForAnnouncement = Optional.of(sizeForAnnouncement); return this; } public Builder sizeForBlockInclusion(final int sizeForBlockInclusion) { this.sizeForBlockInclusion = Optional.of(sizeForBlockInclusion); return this; } public Builder guessType() { - if (codeDelegationAuthorizations.isPresent()) { + if (pqAuthorization.isPresent()) { + transactionType = TransactionType.AERE_PQ; + } else if (codeDelegationAuthorizations.isPresent()) { transactionType = TransactionType.DELEGATE_CODE; } else if (versionedHashes != null && !versionedHashes.isEmpty()) { transactionType = TransactionType.BLOB; } else if (maxPriorityFeePerGas != null || maxFeePerGas != null) { transactionType = TransactionType.EIP1559; } else if (accessList.isPresent()) { transactionType = TransactionType.ACCESS_LIST; } else { transactionType = TransactionType.FRONTIER; } return this; } public TransactionType getTransactionType() { return transactionType; } public Transaction build() { if (transactionType == null) guessType(); return new Transaction( false, transactionType, nonce, Optional.ofNullable(gasPrice), Optional.ofNullable(maxPriorityFeePerGas), Optional.ofNullable(maxFeePerGas), Optional.ofNullable(maxFeePerBlobGas), gasLimit, to, value, signature, payload, accessList, sender, chainId, Optional.ofNullable(versionedHashes), Optional.ofNullable(blobsWithCommitments), codeDelegationAuthorizations, Optional.ofNullable(rawRlp), + pqAuthorization, hash, sizeForAnnouncement, sizeForBlockInclusion); } public Transaction signAndBuild(final KeyPair keys) { checkState( signature == null, "The transaction signature has already been provided to this builder"); signature(computeSignature(keys)); sender( Address.extract( Bytes32.wrap(Hash.hash(keys.getPublicKey().getEncodedBytes()).getBytes()))); return build(); } SECPSignature computeSignature(final KeyPair keys) { return SignatureAlgorithmFactory.getInstance() .sign( computeSenderRecoveryHash( transactionType, nonce, gasPrice, maxPriorityFeePerGas, maxFeePerGas, maxFeePerBlobGas, gasLimit, to, value, payload, accessList, versionedHashes, codeDelegationAuthorizations, - chainId), + chainId, + Optional.empty()), keys); } public Builder kzgBlobs( final BlobType blobType, final List kzgCommitments, final List blobs, final List kzgProofs) { if (this.versionedHashes == null || this.versionedHashes.isEmpty()) { this.versionedHashes = kzgCommitments.stream() .map(c -> new VersionedHash(SHA256_VERSION_ID, Sha256Hash.sha256(c.getData()))) .toList(); } this.blobsWithCommitments = new BlobsWithCommitments(blobType, kzgCommitments, blobs, kzgProofs, versionedHashes); return this; } public Builder blobsWithCommitments(final BlobsWithCommitments blobsWithCommitments) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/AerePqTransactionDecoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/AerePqTransactionDecoder.java new file mode 100755 index 000000000..29eaa6093 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/AerePqTransactionDecoder.java @@ -0,0 +1,111 @@ +/* + * Copyright contributors to the AERE Network. + * + * 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.AccessListEntry; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.AerePqAlgorithm; +import org.hyperledger.besu.datatypes.AerePqAuthorization; +import org.hyperledger.besu.datatypes.Hash; +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.RLP; +import org.hyperledger.besu.ethereum.rlp.RLPInput; + +import java.math.BigInteger; + +import org.apache.tuweni.bytes.Bytes; + +/** + * Decodes an AIP-20 type-0x50 transaction: {@code 0x50 || rlp([chain_id, nonce, + * max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, alg_id, + * public_key, signature])}. + * + *

The decoder is strict on shape: an unknown {@code alg_id} or a key/signature of the wrong + * length is rejected here, before any cryptography runs, with an {@link IllegalArgumentException} + * that the callers of {@link TransactionDecoder} already treat as "malformed transaction". + */ +public class AerePqTransactionDecoder { + + private AerePqTransactionDecoder() { + // static + } + + /** + * Decodes the opaque bytes of a type-0x50 transaction. + * + * @param input the opaque bytes, type byte included + * @return the transaction + */ + public static Transaction decode(final Bytes input) { + final RLPInput txRlp = RLP.input(input.slice(1)); // skip the transaction type byte + txRlp.enterList(); + final BigInteger chainId = txRlp.readBigIntegerScalar(); + final Transaction.Builder builder = + Transaction.builder() + .type(TransactionType.AERE_PQ) + .chainId(chainId) + .nonce(txRlp.readLongScalar()) + .maxPriorityFeePerGas(Wei.of(txRlp.readUInt256Scalar())) + .maxFeePerGas(Wei.of(txRlp.readUInt256Scalar())) + .gasLimit(txRlp.readLongScalar()) + .to(txRlp.readBytes(v -> v.isEmpty() ? null : Address.wrap(v))) + .value(Wei.of(txRlp.readUInt256Scalar())) + .payload(txRlp.readBytes()) + .rawRlp(txRlp.raw()) + .accessList( + txRlp.readList( + accessListEntryRLPInput -> { + accessListEntryRLPInput.enterList(); + final AccessListEntry accessListEntry = + new AccessListEntry( + Address.wrap(accessListEntryRLPInput.readBytes()), + accessListEntryRLPInput.readList(RLPInput::readBytes32)); + accessListEntryRLPInput.leaveList(); + return accessListEntry; + })) + .sizeForAnnouncement(input.size()) + .sizeForBlockInclusion(input.size()) + .hash(Hash.hash(input)); + final int algId = txRlp.readIntScalar(); + final AerePqAlgorithm algorithm = + AerePqAlgorithm.byId(algId) + .orElseThrow( + () -> + new IllegalArgumentException( + "AIP-20: unknown post-quantum algorithm identifier " + algId)); + final Bytes publicKey = txRlp.readBytes(); + final Bytes signature = txRlp.readBytes(); + final AerePqAuthorization authorization = + new AerePqAuthorization(algorithm, publicKey, signature); + if (!authorization.lengthsValid()) { + throw new IllegalArgumentException( + "AIP-20: " + + algorithm + + " expects a " + + algorithm.publicKeyLength() + + "-byte public key and a " + + algorithm.signatureLength() + + "-byte signature, got " + + publicKey.size() + + " and " + + signature.size()); + } + final Transaction transaction = builder.pqAuthorization(authorization).build(); + txRlp.leaveList(); + return transaction; + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/AerePqTransactionEncoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/AerePqTransactionEncoder.java new file mode 100755 index 000000000..f2de33f67 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/AerePqTransactionEncoder.java @@ -0,0 +1,152 @@ +/* + * Copyright contributors to the AERE Network. + * + * 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 org.hyperledger.besu.datatypes.AccessListEntry; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.AerePqAuthorization; +import org.hyperledger.besu.datatypes.BytesHolder; +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.RLP; +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; + +/** + * Encodes an AIP-20 type-0x50 transaction and computes its signing pre-image. + * + *

Signing pre-image (AIP-20): {@code 0x50 || rlp([chain_id, nonce, max_priority_fee_per_gas, + * max_fee_per_gas, gas_limit, to, value, data, access_list, alg_id, public_key])}; the signing hash + * is its keccak256 and is what ML-DSA signs, in the pure (non pre-hash) interface with an empty + * context string. + */ +public class AerePqTransactionEncoder { + + private AerePqTransactionEncoder() { + // static + } + + /** + * Writes the payload list of the transaction (everything after the type byte). + * + * @param transaction the transaction, type 0x50 + * @param out the RLP output + */ + public static void encode(final Transaction transaction, final RLPOutput out) { + final AerePqAuthorization auth = + transaction + .getPqAuthorization() + .orElseThrow( + () -> + new IllegalStateException( + "type 0x50 transaction without a post-quantum authorization")); + out.startList(); + writeUnsignedFields( + transaction.getChainId().orElseThrow(), + transaction.getNonce(), + transaction.getMaxPriorityFeePerGas().orElseThrow(), + transaction.getMaxFeePerGas().orElseThrow(), + transaction.getGasLimit(), + transaction.getTo(), + transaction.getValue(), + transaction.getPayload(), + transaction.getAccessList(), + auth, + out); + out.writeBytes(auth.signature()); + out.endList(); + } + + /** + * The signing pre-image of AIP-20 for the given fields. + * + * @param nonce the nonce + * @param maxPriorityFeePerGas the max priority fee per gas + * @param maxFeePerGas the max fee per gas + * @param gasLimit the gas limit + * @param to the recipient, empty for contract creation + * @param value the value + * @param payload the calldata + * @param chainId the chain id (mandatory for this type) + * @param accessList the access list + * @param authorization the authorization whose algorithm and public key are covered + * @return {@code 0x50 || rlp([...])} + */ + public static Bytes signingPreimage( + final long nonce, + final Wei maxPriorityFeePerGas, + final Wei maxFeePerGas, + final long gasLimit, + final Optional

to, + final Wei value, + final Bytes payload, + final Optional chainId, + final Optional> accessList, + final AerePqAuthorization authorization) { + final Bytes encoded = + RLP.encode( + rlpOutput -> { + rlpOutput.startList(); + writeUnsignedFields( + chainId.orElseThrow( + () -> new IllegalStateException("type 0x50 requires a chain id")), + nonce, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + to, + value, + payload, + accessList, + authorization, + rlpOutput); + rlpOutput.endList(); + }); + return Bytes.concatenate(Bytes.of(TransactionType.AERE_PQ.getSerializedType()), encoded); + } + + private static void writeUnsignedFields( + final BigInteger chainId, + final long nonce, + final Wei maxPriorityFeePerGas, + final Wei maxFeePerGas, + final long gasLimit, + final Optional
to, + final Wei value, + final Bytes payload, + final Optional> accessList, + final AerePqAuthorization authorization, + final RLPOutput out) { + out.writeBigIntegerScalar(chainId); + out.writeLongScalar(nonce); + out.writeUInt256Scalar(maxPriorityFeePerGas); + out.writeUInt256Scalar(maxFeePerGas); + out.writeLongScalar(gasLimit); + out.writeBytes(to.map(BytesHolder::getBytes).map(Bytes::copy).orElse(Bytes.EMPTY)); + out.writeUInt256Scalar(value); + out.writeBytes(payload); + writeAccessList(out, accessList); + out.writeIntScalar(authorization.algorithm().id()); + out.writeBytes(authorization.publicKey()); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java index 23539c386..65aff2e43 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionDecoder.java @@ -1,64 +1,71 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.core.encoding; import static com.google.common.base.Preconditions.checkNotNull; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPInput; import java.util.EnumMap; import java.util.Map; import java.util.Optional; import org.apache.tuweni.bytes.Bytes; public class TransactionDecoder { @FunctionalInterface interface Decoder { Transaction decode(Bytes input); } private static final EnumMap TRANSACTION_DECODERS = new EnumMap<>( Map.of( TransactionType.FRONTIER, FrontierTransactionDecoder::decode, TransactionType.ACCESS_LIST, AccessListTransactionDecoder::decode, TransactionType.EIP1559, EIP1559TransactionDecoder::decode, TransactionType.BLOB, BlobTransactionDecoder::decode, - TransactionType.DELEGATE_CODE, CodeDelegationTransactionDecoder::decode)); + TransactionType.DELEGATE_CODE, CodeDelegationTransactionDecoder::decode, + TransactionType.AERE_PQ, AerePqTransactionDecoder::decode)); private static final EnumMap POOLED_TRANSACTION_DECODERS = new EnumMap<>(Map.of(TransactionType.BLOB, BlobPooledTransactionDecoder::decode)); /** * Decodes an RLP input into a transaction. If the input represents a typed transaction, it uses * the appropriate decoder for that type. Otherwise, it uses the frontier decoder. * * @param rlpInput the RLP input * @return the decoded transaction */ public static Transaction decodeRLP( final RLPInput rlpInput, final EncodingContext encodingContext) { if (isTypedTransaction(rlpInput)) { return decodeTransaction(rlpInput, encodingContext); } else { return FrontierTransactionDecoder.decode(rlpInput.readAsRlp()); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java index 7d2b7b22d..45da4a413 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java @@ -1,64 +1,72 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.core.encoding; import static com.google.common.base.Preconditions.checkNotNull; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPOutput; import com.google.common.collect.ImmutableMap; import org.apache.tuweni.bytes.Bytes; public class TransactionEncoder { @FunctionalInterface interface Encoder { void encode(Transaction transaction, RLPOutput output); } private static final ImmutableMap TYPED_TRANSACTION_ENCODERS = ImmutableMap.of( TransactionType.ACCESS_LIST, AccessListTransactionEncoder::encode, TransactionType.EIP1559, EIP1559TransactionEncoder::encode, TransactionType.BLOB, BlobTransactionEncoder::encode, TransactionType.DELEGATE_CODE, - CodeDelegationTransactionEncoder::encode); + CodeDelegationTransactionEncoder::encode, + TransactionType.AERE_PQ, + AerePqTransactionEncoder::encode); private static final ImmutableMap POOLED_TRANSACTION_ENCODERS = ImmutableMap.of(TransactionType.BLOB, BlobPooledTransactionEncoder::encode); /** * Encodes a transaction into RLP format. * * @param transaction the transaction to encode * @param rlpOutput the RLP output stream * @param encodingContext the encoding context */ public static void encodeRLP( final Transaction transaction, final RLPOutput rlpOutput, final EncodingContext encodingContext) { final TransactionType transactionType = getTransactionType(transaction); Bytes opaqueBytes = encodeOpaqueBytes(transaction, encodingContext); encodeRLP(transactionType, opaqueBytes, rlpOutput); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AerePqTransactionSupport.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AerePqTransactionSupport.java new file mode 100755 index 000000000..1eaa9aee8 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AerePqTransactionSupport.java @@ -0,0 +1,196 @@ +/* + * Copyright contributors to the AERE Network. + * + * 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.mainnet; + +import org.hyperledger.besu.datatypes.AerePqAlgorithm; +import org.hyperledger.besu.datatypes.AerePqAuthorization; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; + +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes32; +import org.bouncycastle.pqc.crypto.mldsa.MLDSAParameters; +import org.bouncycastle.pqc.crypto.mldsa.MLDSAPublicKeyParameters; +import org.bouncycastle.pqc.crypto.mldsa.MLDSASigner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * AIP-20 support on the validation path: the activation height and the ML-DSA verification of a + * type-0x50 transaction. + * + *

Activation follows every other Aere rule: a per-node system property, {@code + * aere.pqtx.forkBlock}, set uniformly on every node that validates or reads blocks. Absent means + * NEVER: a binary that has this code and no property behaves exactly like one that does not have + * it, which is what makes staging the binary ahead of the height safe. + * + *

Verification is FIPS 204 ML-DSA in the pure interface with the empty context string, over the + * 32-byte signing hash of AIP-20. Bouncy Castle's {@link MLDSASigner} implements exactly that + * interface when initialised without a context parameter. + */ +public final class AerePqTransactionSupport { + + private static final Logger LOG = LoggerFactory.getLogger(AerePqTransactionSupport.class); + + /** The system property that names the activation height; absent means never. */ + public static final String FORK_BLOCK_PROPERTY = "aere.pqtx.forkBlock"; + + private static final long NEVER = Long.MAX_VALUE; + private static final long FORK_BLOCK = readForkBlock(); + + private AerePqTransactionSupport() { + // static + } + + private static long readForkBlock() { + final String raw = System.getProperty(FORK_BLOCK_PROPERTY); + if (raw == null || raw.isBlank()) { + LOG.info("AERE PQ-TX: {} absent, type 0x50 transactions are never accepted", FORK_BLOCK_PROPERTY); + return NEVER; + } + try { + final long value = Long.parseLong(raw.trim()); + if (value < 0) { + throw new IllegalArgumentException("negative"); + } + LOG.info("AERE PQ-TX: type 0x50 transactions accepted from block {}", value); + return value; + } catch (final IllegalArgumentException e) { + throw new IllegalStateException( + "AERE PQ-TX: " + + FORK_BLOCK_PROPERTY + + " must be a non-negative block number, got '" + + raw + + "'. Refusing to start with an unreadable consensus parameter.", + e); + } + } + + /** + * The configured activation height. + * + * @return the height, or {@link Long#MAX_VALUE} when the type is never active + */ + public static long forkBlock() { + return FORK_BLOCK; + } + + /** + * Whether type-0x50 transactions are valid in a block at this height. + * + * @param blockNumber the block number being validated or built + * @return true at or above the activation height + */ + public static boolean isActiveAt(final long blockNumber) { + return blockNumber >= FORK_BLOCK; + } + + /** + * The message for a type-0x50 transaction seen below the activation height. + * + * @param blockNumber the block number + * @return a human-readable reason + */ + public static String inactiveMessage(final long blockNumber) { + return FORK_BLOCK == NEVER + ? "AIP-20 type 0x50 transactions are not enabled on this node (" + + FORK_BLOCK_PROPERTY + + " absent)" + : "AIP-20 type 0x50 transactions are valid from block " + + FORK_BLOCK + + ", this is block " + + blockNumber; + } + + /** + * Validates the post-quantum authorization of a type-0x50 transaction: presence, exact lengths, + * chain id presence, and the ML-DSA signature over the AIP-20 signing hash. On success the sender + * is derivable from the public key (no recovery is involved). + * + * @param transaction the transaction, type 0x50 + * @return valid, or INVALID_SIGNATURE / INVALID_TRANSACTION_FORMAT with the reason + */ + public static ValidationResult validateAuthorization( + final Transaction transaction) { + final Optional maybeAuth = transaction.getPqAuthorization(); + if (maybeAuth.isEmpty()) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, + "type 0x50 transaction carries no post-quantum authorization"); + } + final AerePqAuthorization auth = maybeAuth.get(); + if (!auth.lengthsValid()) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_SIGNATURE, + "post-quantum key or signature length does not match " + auth.algorithm()); + } + if (transaction.getChainId().isEmpty()) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, + "type 0x50 transaction must carry a chain id"); + } + final Bytes32 signingHash; + try { + signingHash = Bytes32.wrap(transaction.getPqSigningHash()); + } catch (final RuntimeException e) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, + "type 0x50 signing pre-image could not be computed: " + e.getMessage()); + } + final boolean ok; + try { + ok = verify(auth.algorithm(), auth.publicKey().toArrayUnsafe(), signingHash.toArrayUnsafe(), auth.signature().toArrayUnsafe()); + } catch (final RuntimeException e) { + // A malformed key that the length check let through: the verifier throws, the tx is invalid. + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_SIGNATURE, + "post-quantum verification failed to run: " + e.getClass().getSimpleName()); + } + if (!ok) { + return ValidationResult.invalid( + TransactionInvalidReason.INVALID_SIGNATURE, + "post-quantum signature does not verify over the AIP-20 signing hash"); + } + return ValidationResult.valid(); + } + + /** + * FIPS 204 ML-DSA verification, pure interface, empty context. + * + * @param algorithm the parameter set + * @param publicKey the raw public key + * @param message the message (here the 32-byte signing hash) + * @param signature the raw signature + * @return true when the signature verifies + */ + public static boolean verify( + final AerePqAlgorithm algorithm, + final byte[] publicKey, + final byte[] message, + final byte[] signature) { + final MLDSAParameters parameters = + switch (algorithm) { + case ML_DSA_44 -> MLDSAParameters.ml_dsa_44; + case ML_DSA_65 -> MLDSAParameters.ml_dsa_65; + case ML_DSA_87 -> MLDSAParameters.ml_dsa_87; + }; + final MLDSAPublicKeyParameters pub = new MLDSAPublicKeyParameters(parameters, publicKey); + final MLDSASigner verifier = new MLDSASigner(); + verifier.init(false, pub); + verifier.update(message, 0, message.length); + return verifier.verifySignature(signature); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java index fb71c3558..e765d882f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java @@ -1055,41 +1055,42 @@ public abstract class MainnetProtocolSpecs { blobSchedule.getMax(), blobSchedule.getTarget(), miningConfiguration.getMaxBlobsPerTransaction(), miningConfiguration.getMaxBlobsPerBlock())) .evmBuilder( (gasCalculator, __) -> MainnetEVMs.osaka(gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration)) .transactionValidatorFactoryBuilder( (evm, gasLimitCalculator, feeMarket) -> new TransactionValidatorFactory( evm.getGasCalculator(), gasLimitCalculator, feeMarket, true, chainId, Set.of( TransactionType.FRONTIER, TransactionType.ACCESS_LIST, TransactionType.EIP1559, TransactionType.BLOB, - TransactionType.DELEGATE_CODE), + TransactionType.DELEGATE_CODE, + TransactionType.AERE_PQ), Set.of(BlobType.KZG_CELL_PROOFS), evm.getMaxInitcodeSize())) .transactionPoolPreProcessor(new OsakaTransactionPoolPreProcessor()) .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::osaka) .blockValidatorBuilder(MainnetBlockValidatorBuilder::osaka) .hardforkId(OSAKA); } static ProtocolSpecBuilder bpo1Definition( final Optional chainId, final boolean enableRevertReason, final GenesisConfigOptions genesisConfigOptions, final EvmConfiguration evmConfiguration, final MiningConfiguration miningConfiguration, final boolean isParallelTxProcessingEnabled, final BalConfiguration balConfiguration, final MetricsSystem metricsSystem) { ProtocolSpecBuilder builder = osakaDefinition( chainId, diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 6d0ff35a2..cb8ddfa43 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -1,33 +1,39 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.mainnet; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.getTarget; import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.hasCodeDelegation; import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.feemarket.CoinbaseFeePriceCalculator; import org.hyperledger.besu.ethereum.mainnet.block.access.list.AccessLocationTracker; import org.hyperledger.besu.ethereum.mainnet.block.access.list.PartialBlockAccessView; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; @@ -191,40 +197,48 @@ public class MainnetTransactionProcessor { operationTracer, blockHashLookup, transactionValidationParams, blobGasPrice, Optional.empty()); } public TransactionProcessingResult processTransaction( final WorldUpdater worldState, final ProcessableBlockHeader blockHeader, final Transaction transaction, final Address miningBeneficiary, final OperationTracer operationTracer, final BlockHashLookup blockHashLookup, final TransactionValidationParams transactionValidationParams, final Wei blobGasPrice, final Optional accessLocationTracker) { try { final var transactionValidator = transactionValidatorFactory.get(); LOG.trace("Starting execution of {}", transaction); + // AIP-20: below the activation height the type is invalid in blocks, on every node alike. + if (transaction.getType().supportsPqAuthorization() + && !AerePqTransactionSupport.isActiveAt(blockHeader.getNumber())) { + return TransactionProcessingResult.invalid( + ValidationResult.invalid( + TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, + AerePqTransactionSupport.inactiveMessage(blockHeader.getNumber()))); + } ValidationResult validationResult = transactionValidator.validate( transaction, blockHeader.getBaseFee(), Optional.ofNullable(blobGasPrice), transactionValidationParams); // Make sure the transaction is intrinsically valid before trying to // compare against a sender account (because the transaction may not // be signed correctly to extract the sender). if (!validationResult.isValid()) { LOG.debug("Invalid transaction: {}", validationResult.getErrorMessage()); return TransactionProcessingResult.invalid(validationResult); } final Address senderAddress = transaction.getSender(); final MutableAccount sender = worldState.getOrCreateSenderAccount(senderAddress); accessLocationTracker.ifPresent(t -> t.addTouchedAccount(senderAddress)); validationResult = transactionValidator.validateForSender(transaction, sender, transactionValidationParams); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java index af237e5a2..4c1d265a8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java @@ -1,33 +1,39 @@ /* * Copyright contributors to Hyperledger Besu. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.mainnet; import static org.hyperledger.besu.evm.account.Account.MAX_NONCE; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; import static org.hyperledger.besu.evm.worldstate.CodeDelegationHelper.hasCodeDelegation; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.BlobType; import org.hyperledger.besu.datatypes.CodeDelegation; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.gascalculator.GasCalculator; @@ -341,40 +347,45 @@ public class MainnetTransactionValidator implements TransactionValidator { return codeHash.equals(Hash.EMPTY) || hasCodeDelegation(sender.getCode()); } private ValidationResult validateTransactionSignature( final Transaction transaction) { if (chainId.isPresent() && (transaction.getChainId().isPresent() && !transaction.getChainId().equals(chainId))) { return ValidationResult.invalid( TransactionInvalidReason.WRONG_CHAIN_ID, String.format( "transaction was meant for chain id %s and not this chain id %s", transaction.getChainId().get(), chainId.get())); } if (chainId.isEmpty() && transaction.getChainId().isPresent()) { return ValidationResult.invalid( TransactionInvalidReason.REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED, "replay protected signatures is not supported"); } + if (transaction.getType().supportsPqAuthorization()) { + // AIP-20: no secp256k1 material exists; the ML-DSA authorization is what is verified. + return AerePqTransactionSupport.validateAuthorization(transaction); + } + final SECPSignature signature = transaction.getSignature(); final BigInteger halfCurveOrder = SignatureAlgorithmFactory.getInstance().getHalfCurveOrder(); if (disallowSignatureMalleability && signature.getS().compareTo(halfCurveOrder) > 0) { return ValidationResult.invalid( TransactionInvalidReason.INVALID_SIGNATURE, String.format( "Signature s value should be less than %s, but got %s", halfCurveOrder, signature.getS())); } // org.bouncycastle.math.ec.ECCurve.AbstractFp.decompressPoint throws an // IllegalArgumentException for "Invalid point compression" for bad signatures. try { transaction.getSender(); } catch (final IllegalArgumentException e) { return ValidationResult.invalid( TransactionInvalidReason.INVALID_SIGNATURE, "sender could not be extracted from transaction signature"); } return ValidationResult.valid(); diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java index 25b1f2d5f..65292ac2d 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockDataGenerator.java @@ -1,33 +1,39 @@ /* * Copyright contributors to Besu. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.core; import static com.google.common.base.Preconditions.checkArgument; import static java.util.stream.Collectors.toUnmodifiableSet; import static org.hyperledger.besu.crypto.Hash.keccak256; import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SecureRandomProvider; 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.Hash; import org.hyperledger.besu.datatypes.Log; import org.hyperledger.besu.datatypes.LogTopic; import org.hyperledger.besu.datatypes.LogsBloomFilter; import org.hyperledger.besu.datatypes.StorageSlotKey; import org.hyperledger.besu.datatypes.TransactionType; @@ -512,40 +518,42 @@ public class BlockDataGenerator { public Transaction transaction(final TransactionType transactionType) { return transaction(transactionType, bytes32(), address()); } public Transaction transaction(final Bytes payload) { return transaction(transactionType(), payload); } public Transaction transaction(final TransactionType transactionType, final Bytes payload) { return transaction(transactionType, payload, address()); } public Transaction transaction( final TransactionType transactionType, final Bytes payload, final Address to) { return switch (transactionType) { case FRONTIER -> frontierTransaction(payload, to); case EIP1559 -> eip1559Transaction(payload, to); case ACCESS_LIST -> accessListTransaction(payload, to); case BLOB -> blobTransaction(payload, to); case DELEGATE_CODE -> null; + // AIP-20 transactions need ML-DSA keys; the random generator does not produce them (same as 7702) + case AERE_PQ -> null; }; } private Transaction accessListTransaction(final Bytes payload, final Address to) { return Transaction.builder() .type(TransactionType.ACCESS_LIST) .nonce(random.nextLong()) .gasPrice(Wei.wrap(bytesValue(4))) .gasLimit(positiveLong()) .to(to) .value(Wei.wrap(bytes32())) .payload(payload) .accessList(accessList()) .chainId(BigInteger.ONE) .signAndBuild(generateKeyPair()); } private List accessList() { final List

accessedAddresses = Stream.generate(this::address).limit(1L + random.nextInt(3)).toList(); diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java index 2b649f856..03a72eaf1 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java @@ -1,33 +1,39 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.core; import org.hyperledger.besu.crypto.CodeDelegationSignature; import org.hyperledger.besu.crypto.KeyPair; 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.Hash; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationTransactionEncoder; import org.hyperledger.besu.ethereum.core.kzg.BlobsWithCommitments; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import java.math.BigInteger; import java.util.List; import java.util.Optional; @@ -96,40 +102,43 @@ public class TransactionTestFixture { break; case BLOB: builder.maxPriorityFeePerGas(maxPriorityFeePerGas.orElse(Wei.of(500))); builder.maxFeePerGas(maxFeePerGas.orElse(Wei.of(5000))); builder.accessList(accessListEntries.orElse(List.of())); builder.maxFeePerBlobGas(maxFeePerBlobGas.orElse(Wei.ONE)); if (blobs.isPresent()) { builder.kzgBlobs( blobs.get().getBlobType(), blobs.get().getKzgCommitments(), blobs.get().getBlobs(), blobs.get().getKzgProofs()); } else versionedHashes.ifPresent(builder::versionedHashes); break; case DELEGATE_CODE: builder.maxPriorityFeePerGas(maxPriorityFeePerGas.orElse(Wei.of(500))); builder.maxFeePerGas(maxFeePerGas.orElse(Wei.of(5000))); builder.accessList(accessListEntries.orElse(List.of())); builder.codeDelegations(codeDelegations.orElse(List.of(CODE_DELEGATION))); break; + case AERE_PQ: + throw new IllegalArgumentException( + "AIP-20 transactions need ML-DSA keys; this fixture does not create them"); } to.ifPresent(builder::to); chainId.ifPresent(builder::chainId); v.ifPresent(builder::v); return builder.signAndBuild(keys); } public TransactionTestFixture type(final TransactionType transactionType) { this.transactionType = transactionType; return this; } public TransactionTestFixture nonce(final long nonce) { this.nonce = nonce; return this; } public TransactionTestFixture gasPrice(final Wei gasPrice) { diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/AerePqTransactionTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/AerePqTransactionTest.java new file mode 100755 index 000000000..6f6da5369 --- /dev/null +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/AerePqTransactionTest.java @@ -0,0 +1,210 @@ +/* + * Copyright contributors to the AERE Network. + * + * 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; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.hyperledger.besu.datatypes.AerePqAlgorithm; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.BlobType; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.TransactionType; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.core.encoding.EncodingContext; +import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder; +import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder; +import org.hyperledger.besu.ethereum.mainnet.AerePqTransactionSupport; +import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionValidator; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; +import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; +import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; +import org.hyperledger.besu.evm.gascalculator.OsakaGasCalculator; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.Test; + +/** + * AIP-20 conformance on the Besu-derived client, against the vectors produced by the reference tooling + * (`tools/pqtx/pqtx.mjs vectors`, @noble/post-quantum): the same bytes must decode to the same sender and + * hash, verify under Bouncy Castle's ML-DSA, be charged the AIP-20 gas, and every negative vector must be + * refused for the reason the vector names. Two independent ML-DSA implementations agreeing on the same + * signature is the cross-client property the AIP requires. + */ +class AerePqTransactionTest { + + private static final BigInteger CHAIN_ID = BigInteger.valueOf(28001); + + private static String vector(final String id) throws IOException { + try (InputStream in = + AerePqTransactionTest.class.getResourceAsStream("/aere/pqtx/" + id + ".json")) { + assertThat(in).as("vector " + id + " on the test classpath").isNotNull(); + return new String(in.readAllBytes(), StandardCharsets.UTF_8); + } + } + + private static String field(final String json, final String name) { + final Matcher m = Pattern.compile("\"" + name + "\"\\s*:\\s*\"([^\"]*)\"").matcher(json); + assertThat(m.find()).as("field " + name).isTrue(); + return m.group(1); + } + + private static Transaction decode(final String rawHex) { + return TransactionDecoder.decodeOpaqueBytes( + Bytes.fromHexString(rawHex), EncodingContext.POOLED_TRANSACTION); + } + + private static MainnetTransactionValidator validator() { + return new MainnetTransactionValidator( + new OsakaGasCalculator(), + GasLimitCalculator.constant(), + FeeMarket.london(0L), + true, + Optional.of(CHAIN_ID), + Set.of(TransactionType.EIP1559, TransactionType.AERE_PQ), + Set.of(BlobType.KZG_CELL_PROOFS), + Integer.MAX_VALUE); + } + + @Test + void validVectorsDecodeToTheReferenceSenderAndHashAndRoundTrip() throws IOException { + for (final int alg : new int[] {1, 2, 3}) { + final String v = vector("valid-ml-dsa-" + alg); + final Transaction tx = decode(field(v, "raw")); + assertThat(tx.getType()).isEqualTo(TransactionType.AERE_PQ); + assertThat(tx.getPqAuthorization()).isPresent(); + assertThat(tx.getPqAuthorization().get().algorithm()) + .isEqualTo(AerePqAlgorithm.byId(alg).orElseThrow()); + assertThat(tx.getSignature()).as("no secp256k1 signature on a type 0x50 tx").isNull(); + assertThat(tx.getSender()).isEqualTo(Address.fromHexString(field(v, "sender"))); + assertThat(tx.getHash()).isEqualTo(Hash.fromHexString(field(v, "hash"))); + assertThat(tx.getPqSigningHash()).isEqualTo(Bytes.fromHexString(field(v, "signingHash"))); + assertThat(tx.getChainId()).contains(CHAIN_ID); + assertThat(tx.getR()).isNull(); + assertThat(tx.getYParity()).isNull(); + final Bytes reEncoded = TransactionEncoder.encodeOpaqueBytes(tx, EncodingContext.BLOCK_BODY); + assertThat(reEncoded).as("round trip, alg " + alg).isEqualTo(Bytes.fromHexString(field(v, "raw"))); + // a detached copy keeps everything that identifies the transaction + final Transaction copy = tx.detachedCopy(); + assertThat(copy.getHash()).isEqualTo(tx.getHash()); + assertThat(copy.getSender()).isEqualTo(tx.getSender()); + assertThat(copy).isEqualTo(tx); + } + } + + @Test + void validVectorsVerifyUnderBouncyCastleAndPassTheValidator() throws IOException { + for (final int alg : new int[] {1, 2, 3}) { + final Transaction tx = decode(field(vector("valid-ml-dsa-" + alg), "raw")); + final ValidationResult auth = + AerePqTransactionSupport.validateAuthorization(tx); + assertThat(auth.isValid()) + .withFailMessage(() -> "ML-DSA verification, alg " + alg + ": " + auth.getErrorMessage()) + .isTrue(); + final ValidationResult full = + validator() + .validate( + tx, Optional.of(Wei.of(1_000_000_000L)), Optional.of(Wei.ZERO), TransactionValidationParams.processingBlock()); + assertThat(full.isValid()) + .withFailMessage(() -> "validator, alg " + alg + ": " + full.getErrorMessage()) + .isTrue(); + } + } + + @Test + void aip20GasIsChargedForTheAuthorization() throws IOException { + final Transaction tx = decode(field(vector("valid-ml-dsa-2"), "raw")); + final long intrinsic = new OsakaGasCalculator().transactionIntrinsicGasCost(tx, 0L); + // 21,000 + 16 * (1,952 + 3,309) + 75,000 = 180,176 (AIP-20 worked example, empty calldata) + assertThat(intrinsic).isEqualTo(180_176L); + final Transaction tx87 = decode(field(vector("valid-ml-dsa-3"), "raw")); + assertThat(new OsakaGasCalculator().transactionIntrinsicGasCost(tx87, 0L)) + .isEqualTo(21_000L + 16L * (2_592L + 4_627L) + 100_000L); + } + + @Test + void aCorruptedSignatureIsInvalidSignature() throws IOException { + for (final int alg : new int[] {1, 2, 3}) { + final Transaction tx = decode(field(vector("bad-signature-ml-dsa-" + alg), "raw")); + final ValidationResult r = + AerePqTransactionSupport.validateAuthorization(tx); + assertThat(r.isValid()).isFalse(); + assertThat(r.getInvalidReason()).isEqualTo(TransactionInvalidReason.INVALID_SIGNATURE); + } + } + + @Test + void theWrongChainIdIsRefusedByTheValidator() throws IOException { + final Transaction tx = decode(field(vector("wrong-chain-ml-dsa-2"), "raw")); + final ValidationResult r = + validator() + .validate(tx, Optional.of(Wei.of(1_000_000_000L)), Optional.of(Wei.ZERO), TransactionValidationParams.processingBlock()); + assertThat(r.isValid()).isFalse(); + assertThat(r.getInvalidReason()).isEqualTo(TransactionInvalidReason.WRONG_CHAIN_ID); + } + + @Test + void aShortSignatureAndAnUnknownAlgorithmAreRefusedBeforeAnyCryptography() throws IOException { + for (final int alg : new int[] {1, 2, 3}) { + final String raw = field(vector("short-signature-ml-dsa-" + alg), "raw"); + assertThatThrownBy(() -> decode(raw)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("byte signature"); + } + final String unknown = field(vector("unknown-alg-0x10"), "raw"); + assertThatThrownBy(() -> decode(unknown)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("unknown post-quantum algorithm identifier 16"); + } + + @Test + void theTypeIsNeverActiveWithoutTheForkBlockProperty() { + // the test JVM does not set aere.pqtx.forkBlock, so the rule is "never": the same as a binary without it + assertThat(AerePqTransactionSupport.forkBlock()).isEqualTo(Long.MAX_VALUE); + assertThat(AerePqTransactionSupport.isActiveAt(Long.MAX_VALUE - 1)).isFalse(); + assertThat(AerePqTransactionSupport.inactiveMessage(1)).contains("not enabled"); + } + + @Test + void aClassicalTransactionCarriesNoAuthorizationAndStillWorks() { + final Transaction tx = + Transaction.builder() + .type(TransactionType.EIP1559) + .chainId(CHAIN_ID) + .nonce(0) + .maxPriorityFeePerGas(Wei.ONE) + .maxFeePerGas(Wei.ONE) + .gasLimit(21_000) + .to(Address.ZERO) + .value(Wei.ZERO) + .payload(Bytes.EMPTY) + .signAndBuild( + org.hyperledger.besu.crypto.SignatureAlgorithmFactory.getInstance().generateKeyPair()); + assertThat(tx.getPqAuthorization()).isEmpty(); + assertThat(tx.getR()).isNotNull(); + assertThat(new OsakaGasCalculator().transactionIntrinsicGasCost(tx, 0L)).isEqualTo(21_000L); + } +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/INDEX.json b/ethereum/core/src/test/resources/aere/pqtx/INDEX.json new file mode 100755 index 000000000..8ae144888 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/INDEX.json @@ -0,0 +1,93 @@ +[ + { + "id": "valid-ml-dsa-1", + "expect": "valid", + "alg": 1, + "hash": "0x5ee00afa7d595efaffab2cf573a82e50c7d0f37bc1c2a53a11f7120155bf57b6", + "sender": "0xa4fe6cb101b79c0531f265f6b2584b37073087a5" + }, + { + "id": "bad-signature-ml-dsa-1", + "expect": "INVALID_SIGNATURE", + "alg": 1, + "hash": null, + "sender": null + }, + { + "id": "wrong-chain-ml-dsa-1", + "expect": "WRONG_CHAIN_ID (when validated on 28001)", + "alg": 1, + "hash": null, + "sender": null + }, + { + "id": "short-signature-ml-dsa-1", + "expect": "INVALID (length)", + "alg": 1, + "hash": null, + "sender": null + }, + { + "id": "valid-ml-dsa-2", + "expect": "valid", + "alg": 2, + "hash": "0xc7903f14f8aa0ffc09cdfcd433e20f07ceaa63ab9b56b84ba41fc8dab7204952", + "sender": "0x0602be26ec9e01dd88121f7c203ead9eecb9ad3e" + }, + { + "id": "bad-signature-ml-dsa-2", + "expect": "INVALID_SIGNATURE", + "alg": 2, + "hash": null, + "sender": null + }, + { + "id": "wrong-chain-ml-dsa-2", + "expect": "WRONG_CHAIN_ID (when validated on 28001)", + "alg": 2, + "hash": null, + "sender": null + }, + { + "id": "short-signature-ml-dsa-2", + "expect": "INVALID (length)", + "alg": 2, + "hash": null, + "sender": null + }, + { + "id": "valid-ml-dsa-3", + "expect": "valid", + "alg": 3, + "hash": "0xe37a3c437aacfb3f7abe9bd9da80fb8a50398a56e6b60e6fd29f08abd049d9d7", + "sender": "0xaee69521a942a58325bd694f2cc3d64752465d4a" + }, + { + "id": "bad-signature-ml-dsa-3", + "expect": "INVALID_SIGNATURE", + "alg": 3, + "hash": null, + "sender": null + }, + { + "id": "wrong-chain-ml-dsa-3", + "expect": "WRONG_CHAIN_ID (when validated on 28001)", + "alg": 3, + "hash": null, + "sender": null + }, + { + "id": "short-signature-ml-dsa-3", + "expect": "INVALID (length)", + "alg": 3, + "hash": null, + "sender": null + }, + { + "id": "unknown-alg-0x10", + "expect": "INVALID (unknown alg_id)", + "alg": 16, + "hash": null, + "sender": null + } +] diff --git a/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-1.json b/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-1.json new file mode 100755 index 000000000..c0a74d633 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-1.json @@ -0,0 +1,6 @@ +{ + "id": "bad-signature-ml-dsa-1", + "expect": "INVALID_SIGNATURE", + "alg": 1, + "raw": "0x50f90ec5826d6180843b9aca0084773594008302d5709400000000000000000000000000000000000000010180c001b90520372c0f4874450fb92ace74d41bc0326c7f739589f9b86a97afa87ef65d5939e608c81a44909e41f41931349f744b7aedff8d5270b91c4a2f61192e2bb6e3e6d12231deab235359e78ccada386becb6a6a1105afc0999243ab8b363f7cd2c19b2b741c9969dcf20252f20d130dc05d9244f58d6de9b4fb4b6f0125c43b60ebe3c7272b6ae7578f1abb4bb5e2dcb31eebf4aa7089aa2bf40a0ba5eb73aaa90e45472168738cb0e866547e079075d0341c4728ed794cd449d0cdeceaf64d09173a2677e3f2621b56014df58ee8de2bbcf8cb2bf369e57a28e40b24df6d0b15d3417b7b7fce3c49230b3bb7c7080c4f1344380db37299d8c0c29a7c9e95bfc4f3ec70b767895be6ad798449f94c92f320696f8f9ec844fc9451f5ab30874e6c78673b932e24a918d5bc03f4fa647c8679631ad8b30ba4f9a1a790a535104f5079f781fa4c4aad807777327e08bd6e14b957e527650d39e2de7d30da7b2b27457d3539c2f99903054bd1a6d6301b2f83249db80dedc911059b047b5552407ed32b79b57ea4968198decf978fed532277fb189841d0c17f261f1a7c4618c33b258a71cb6b2b921c48735c1fbc375a80fe2d702e9f70db34547147f6d65153f1c508ff90aaf57dfde59ce6e56c5c52049b10fbc2640cd937bf5027d755444cd5e84aad66be4ccf04f710f0b970cbe7fc5e4e7a44f5d8fc2af94ec6df87862dabe0d85dd17e43728800d5dc8ff9e9e1fd349b9d6431f264836a447646a1ee2d73e6a4d1803d71b98510d94d53b5d07764400f413b7837f463e273980296ad5e78a62c83fb91354c25c2e28bfa19480ca41b0ca2d8beed456029eabc0ba69cf3504cf1207ab21bed0e3a60795f5b066019132212a9bd20e98b43bb32484454b7693bc63764d0ba8768da4336ad16a979b1d3e8b06e89afc4caafaddead83ad861a4596814062468d8cb2e131e71cf38c4e335bb3d1d9629251fd50a4273999a20e11d9a881fa2465c2ef32301fa8805ccb38b4656e3c815b54ef42f292d05847c0e5149b0a2ffd1719fcad10730b763406e9e453d2e4a556c397a984a7d8622466522e79f715f980279cb2d1d74d5fd15f8beb8df9c0a1fb93f0d5494ab701cd60cf2b613b484a191d873449c4815f44eebb62658ef90f7033a5e48d40c8f4ec9a25d4f1b73a150e5b03a4feec9142362e77d74d364bb8a40f9873efa2d9f458d84277fdb0063642d9ebc794356368a0b4e53f6ab0d9acf4418fa42d05c11db12cb67d6c4cbbfde4d85358abaf8042510db53c1540fcb40045b334bc54a17608e82433d1e9e53c99769b86b69b8cf1914584cdef479061718a2cc5bec5c31272e0463139721c0c3523a6ea31832b5c15aa59819304c217fbc51a2636bfff331e6dc1037e89be15c17d6708762976329353612f312b828e525c09b81afafa5ae5c25d82b70b6e55f892429a93e5eb4048ade675583e828da988f9d253123a06c0ed047adf4d93d20cc6c865f5a761fec27811305165cd4bda05f563215d0612944b88ade9d64477ae8fb441978720e70b0d77e2edafd3a2c571cd28a42cca2f289d157cec813c24e7f56051b4f28c153adfbb2c1ff90ea1fbc03cb89603387169072442f5d3081140e2256ebadcd775d2f1da92c15a9ff1ce6e980b3b1e91a7e379081ed46a4259fada21536af318eb2043ea16cece60b73acd415d239389cad9212e15bad1b1ae38f93c756635a9b87417faa844e4f43bae1f1ae68641a04f0ff1d55f9045cf7e3ed59fde5c07219b9113329356d4300885ee19c9955c5757db33c6ae75b49d035003171d02ccbd7321d6a14db0bd011d4877f04070dbda3b67bf22d083eb90974674be581b59cd495740a8a9aaaf7c6801a8bcedb531ace47da1be56ab30f1c4ccdaad6e81aa97352baca12b6c69754123bdee38c0d57bf15f0850572dc9b456234eaf37eb478f9117f952ae95a0d165d12d948b51672a03c9610a98cf332d6ad7ab8a87defb3ef7249cf8c3a815129ecf5600500702b7916ffe570cef0714e0c083a581c2971c45c4aa6b1c5226400e5fd594ea3ae97fe94a0dc7f1e0979b11a2f3d15ad54fea957992ada816f97cd76168a53ebffae36e5787b0f69e94b3e08eadefe4937ce8b383b5022e57ba7135cccd5b48e38916f1f0bdcbc5858bf93cad75195d4329ab41a518d820262b1b610f7bdbe1d6749d006a0dfe18d0be1a19fb3d8e37795b5bc37ebcd884f91459164cd2536b3496c4b25a4c74282ece5d64ab861184e942cf97f0edbe6e1293c4504d861e60d98c4f6523df27a1e80843005ad21665b3adcf46f349fb0d905d70631d2ee51c0086b252778eac27346eee65c0fc88c6db5936337b0afa7d8cec656612c81e11cc55abf421df770e6c2588c743d5540e1280be76309defaffde2b82c808976c337ee13735a21900a4686423625a0ba4819581edbe574e6d7053c5fd98d288db4104ea64fbc0e7ad11d50eb1470a882aa00ebfd983cdda14db34f7f968ccc93097cf037dceeb1375f2df4de09c8785f5fef8fbbe284566e5c9a2d38f5d2f9145b7f5087f6a89a56679680ca4180ad7da3ee45da685f0255a45db806e1379c1ed59bfe63feb7d74a239334c80ab9c1859d205ba798810adf8afc569170f94167439d137215d2ce0b2fa983ac138a3ce201cec4927c62b740912e7287417f86beb07af9c83fff843df1abd6e6f81865b82b3168528d1c473b4999b0179f1de8ae22e8ed7f698ee8463eb93fcfd4e017f29ab3f15a2e061de6deb09459d4ecc62741ffd8514d5c1f10eb3b1525ad60512ffad00e360e0d6add8ed6d6df48d63cf1e36f306bd76b1a245cdd09951727367e45b3a02d748dbfcbeea342be4cb0e1e3108e57993581409f8c6b34e2d38becfcf15c653b92c88412c087eddb0bc21eeb620317f49a9bf5d6164418a26322e1964fd676a547862c2a7ce5f13898e3fadec79a638f257532cfe977fe8ba5e96782f9e1e3e8b5f896a80d816141f0c988ea59ea321cffd23f298b76e49e92189e7f65718d14091daeb82d432470a2e472a39a154226a43c543db2bb933adad08344259ba08a65c543d2ee07b67328ca2d4e60e550b85215ea5873fedb505cc1e4db49e129249fb632ba22f11b897b9423d08f96ceaa863cd29dc16af6ac76c4388c2795250c04377277626992b085ed7be2cf1d63a2eda4b65e287081fdc4e9a3224ff57d81b3ba8d04eb88430a01c5eba35fad028e8de1812920cee2576d0bd291407c5fb70c5ce07104b9af7b98c4c709c7f019d4a66b136120b92612ad5e73dfcfc1da0fec3a7928e57d7d4769eecbaa4c269f2859d31d47d1ae40e4da5bfa6592074c5bf54b04c707b8d97455a0a606686e06bf5ef7617da2532f305267f61c5f627216b06ecc3da6c6f7b420e2dfecaa41657eab20c89927ad6eb5c4fcd513da89a637755f4a98c45cfa108f37415bbf49ee6cacfda8f22f7101a9798d844709a38f9168685f105157a937bb10d4f5b342deab8b8be8231490da52cc0c407bf942270ad93d4a9bed5c06499584835dbba75577dbbc47fd3d397f0417ade99549de4412c8893cf3e1a2ed74c234a7b60461efad57d9c9fed9eec3ebd652282b045174e19355d8cfcc10add9192ffffd428150dc3f48e0417e47d6407008c62486cd4057535a5a9ffc45ef559a51fbbece64306f64da9740108d0b51d01423379bb0a72fe050d2abf5f5acd25cff57f8e3bcdf938749c7bbf77437424ada88c167bcb6addc309b949a8e200b9a5b6797522635731b250e2405f98d054aaff4179ccb4b24159e4c033329100cadbef3da262203622d27899166f6c3c79a35daf7840853b9a3ce494bf035235cada8c31e28be56f0976ef9b96f15de57e6896a5aed57a7b5ce77cacd1c806ecf83566bee5d577f7414a106ce16ca6e8cbc144f571b1a37647041694a6409f68d15604960417a60bc4f1a878eb01e89159e701bb8fd96be45395a8b8c4f0cc5b982582741c4ccaff8961ea892f084b10646c7a27687a2d3c92324cc3a19a5b38ca2d5c573167ad54486ab3adfe9219882f947cc6a93a3827f4b51d76e90ffd1587646d921482022db8b5a22519be3a1e62e9a13ff9926e75c42e07aa295c8486df69dc96168e920e13c85eeda86dc560b9f5d4c77cb8ff001d390dc6c5a911c573ab1711df534930ef28832936c80cafcde731e999ce90741e669d93f653efba12466726fa997e7ad24d34395a02b8a4286f3604f120bf47e8ec41954e6def2de896be477ef7916f18214d28f58ae91ed8d7eae9e2df600d313b6cdb952195e9d030e0b8fc98a68cced3070f4abd2d252727320eb54b602ec861ba630ed3c5d6fc8c8b39f4f1e9c198a6dc8d5f825159ce15fcd7bea5701a225ac41bb152d1a077adc03ecf06870375f2d2618094a648b40244e4a981e7efeadc608c082dc1824c4ffdbc39afcc8c464ed5ca8dfc1540ae3a6c034364c356bf13f880abe8633fa041db78f4be0d17a4bb00959a697935c844c6ddc02222f7aebb1af2c96a757536159dc1dbc31131aefe4c198ccd2123eb5d0ca6147bbc9ab43e993508ef4ca383e2847d9fcb4c975dcb240bcfd164daa835311cf7dbde0f256deb5f3748b55c312a29a042725ecf07caa904513e71b4c0ebd3b31c2938e710e7c6be819bb3125e638ee4b54b4c8fe16df1cee7587e6bdfdcccf2e3b2aa4a54c86b0ae711f056c229c644f519f60570aed60fd3d0638dc341625fb4949d355e7d84cb478133d25730162623acbf5d36b9ed98dbd88b6bf7bf1f55006f5ba2d16297557f966cc01baca56e3f6435b724c0b6fa4cc0074efb0bb2cf0cba9a1c73d3337db7dc0c78b87746db7bbe5fc003edf608ce5d91dbd8b3cec0f738de14c8e2b6df47df91805eab5635402ff26245430641abd9511cffa6bf8d352a1f0d97ce2b08561c97a5f07a07e0ac42a2a73366442e0bf125a718553794b021640ef9f9f07040068cce2337606af46f897b7ad8ced05e14f7ab3e2bd847f810058d665a0c3b6903efd8f398c31e356b48216111d30348acf93d28dbec8e603cd16ea5d3b24f38367c52f5629fd51bec34e86ff21d4f5466a53aea7048babf3afaecec2c9de099bcb2845f66689e02306760ef5274e65f36fc61edf8112b3b414a878b8dbdc2ced0d7dae0e95c5d6e7c80a3b4cbccfe13293e454b6c757a8d9496999fb0c4d4dfe5e7f3f40e11172324323556687e95a4a6bfc4dadbec000000000000000000000000000000101a2f41" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-2.json b/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-2.json new file mode 100755 index 000000000..c07213da9 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-2.json @@ -0,0 +1,6 @@ +{ + "id": "bad-signature-ml-dsa-2", + "expect": "INVALID_SIGNATURE", + "alg": 2, + "raw": "0x50f914be826d6180843b9aca008477359400830383209400000000000000000000000000000000000000010180c002b907a05424000ae9a496294dd6b99046cfdbb235ae71031b379ce274c13b0c96411740cb61021a5390fbe8fb56b642b4e5e5abb7aeab143e0037f8db283b9f2febd650265ed6b05f1b867c124aef245c1811422f92414447fd0b20844e0f1b1cb4eec052400aad52b9d773aae0015c0c390bfdde3d367bd8ef9c3c73bca3164b9d418ecbb2d25303bbd12739a858c5fac4cbfa0203b9f3c319e9bc89d17a7a244b57d6613b5caabdb528f077eff9727015b9c266d777c0ba11920118c7ec4dd59b380c40e361a5b23ce04be4c61e12a1c21e091fa0d890687cbf588944db3e34253c75cdf797378de79162e0b4ca309f550365a289f652dd6d559478912cff70a5417589f73f14640970694d7b5a6bd8f000a65c632f0326ed3d128fda96dbea68cb812634dd75e9f63813a5645336681378b6a63220c066550aba43a5b937131d41f08752d13949a115a74bf96fa1925ff4338e10df0301abe40aaa49e14a1a1d58eef005a0f1d0299267002cebeda20cadcea7419cd0c365c53aede1aa36efaf764d3d36169747cdc8ee9a09e0a0ac6bcaeaeded0cd303c965d705d1b91a8b35f408ad8a033b02ff57610bddbfa60e2114e53f20f8fcad15dffac6a494c3f4f631590f2be3422af14cba7c900c9c38796952e20c3069bea2ab54bf0edf9315903aa5cf68549f878eafcc77561b36f8b78d950871ed4914417316f868a2bc54c72d3c9929f0138a2f0cbccb7c4141e94bb8a7ae11f660861cbbe498697d7327709271460a75bd4e024de3d4d6fe5af066944c96ba87459fa948a95eeb61abbaf643190ccaa9cd18591eb6f249a6eb92db89fc95616d21b41d7d15424b80a750938a12cd57d50ef95aaf222025dc4d81df320d9bc32c608b1c5a1aac8bd14c0f7a4c4380cdd65c793a6287050ff4d609102fd91e47e7365fb55513aeca273618528c199f7bb151e9c11a0bf202147734d1be9d5d0e9318096fa567317ed9fa6a8efe201b915b9aa05ca0d19e15c9a80449cc130b398ebbac3d938f55eea8f74e024b0e33dfecdbea02b920ddc5b277146685916194bfa1f8ac7784c7ed76923d4ff9ed97d3ceac283f9b26977df0133c5fa4fb5fcec577bc152e926529f06ff50c204c083c0b4d6b8d474cf5cf7cfcf7acf76921225443eb0abf5e4c76d0a3f524243ee4e372e80ff0f76dd9d135f240114a2ebe6d69609b6c60d275f251d7dceadc600d18e0cf8bc8fa8392e61fa32b8f7481c4883e19d820b51af0f87d3f7faae44e3b908fc759c6de59361487d8e424ffbd662d57a68801110e9cb099214143253949cc479eaae0e321fecab90c63b06819ce3cf56fc2fc1419408075c658024a28950aa47d549bcdb8b5bc9aeab463466c7834ca7d73058c206a95a023f0c8ac95badd383e63041e1f0ef69f51634f5ce2f48d80f8f2e92f4a1fb5322930141fc50e1e20bd235a8b8d768d473b46711257d028e710f82f0b6bd923da05ca64ae805f708577e125b3fca2feb5656f61ded034eaae481a195628801c82db85345f9ffdc72c860cffe2264ba4be2a08fdb37a4f5f80276baba4ea637847335c89dbd35504389f68b2d61ea66d4eac5fd0057d9e757d929214a7d83daf2fc2b3f840e083792d20d772584b252ba955ae8ae8c36af648c59ae0b25d3bca19413fbd749077b6969db5847409d13e4a67387e59116fe3836a733f3253d47f9919f49618fac8edf5fd711a4239447655d6c40f479f86ef3c9d4dc1a6f9683a3f1bc5c9730025e76ea1588d43494f59823f42c207e34412f73c7e2a126501b8fb810f12995c213063d909a5a9c2653d3511ceb809efa69c638f4c977d46a2a305cc831ecc0feebf5d9356ede6c780da78fe2ad683b3312282d5142612c0d1f85108de04de5c3d5414b62826d5b75f8887dc2d932c40f306c08e5d4f69ef4d344fe4317552df9890d0961e3d857bd9b2c5b44536d8606f62f66d14ddd43b0e5d3379cf66d664616df12b1c62385a57f6a562c34e120b79d64ca39d8b23e1e07b2c03910d711f09df5b54cb0e133dd751bea7832fdb38de2f1dafae69fbdf82b6887ff0a92940299020a835b958bb01b25b8699a0846614cb256a6621ef92e4a0947df9141ed4f91eca527aef25862158a8fa712dd60dda947f6a16e077810e29542a56f9244c34a73454b9ad0d8e8c40bd503efe12c4e5bf7d0ff8e6ab642a039f4e8b575d33c0c3de77a1abfa60b0252d7a549dd791d9630c8b848988157608448d77938bfb27beaea8f9b4a259263797c5b2fbdc7f469b2769f7dcb7b9478cdf5f109322eb2f0a83163469b72d8121fe8e01df227563cbd941a1f63961e2a010c6322a812a014279583a0066492a17d1a15c07024f6b8b1561041b3db608ec1c7475ce4d086e60523e85d7a955841558a35535d6e52cb166669a69049646b94d2fdb901ffbb1446a2d7f58696bce000ccbbb6942b0ad6480d006602c228218d3a2f0bc6a5d5c73acda9fc4b0b496a7d527050f8d77b71641f030368e9494bfe8e9dbf6dd4040426da1b0423739b40450273f4a8d551637e5fe3ca8d54fc476e6278e75cebf4a4ac3ac8ef3807041c4b274568797c8caaffae7df08c6c158d92411db981ea02cc212064c3ad6a9cd1cc02087acce5ceb8d7cddaec429d199c3d90670288be6e88e6826d1f6c417df5f35139c71a62c0267adfce7cb3aa49e827165b28c8cc157a691cb52ef103d8d7ca0ebfc628904d0b2d365dd3401b620d6d93cef670e2fb90ced32fc1486a0e70aeb6fef62ce5a0dfb51fcec12164e4024b0c49ce8b65e01356d80a9571af8f69a9c7256ed549d699a31ceff21c13c482ee0c5759f96125b0099495feacf22a001b2c887b107a9ca9e84de461fbc6e143566de56c710156de5b5f4b7ffe29c0124c1fbb6a792110284c9ad713d89bbb5ed444d09408c65a9f74c5f6c4fd281d31738db82913dcd1ac1fccbba24dc933fb9a8e6c4e426fb98590d7da0252c34d866c114526ded1c9d96daea12ecbd8f2a44531dfb72f02c02b267edf0560b1fb06b087bb6ce02b2922d92f81bb7da99b90e4a2dd68aa858759584490be602369dd606a510b6228e3b941421a3006a697b79866cae011d8aa496de4f3bfffdc0a087d01323db849f6237d7ac476d18bb417f26a697388b4c0a78533f3dd763398719c9ee5bf0299786fb8c4143af8c1195103390d4494b735c06b5815c454dba2fcdd27d214c48712609ffe7ad7c082e835d7477de2358fb3c4b5162027f816ca85aa4a46c25105175e77c8e5394db6fb3999c25ce578f066329182b28fd5b68769cb07ebc67e47a537f6cb62bfd18af162113a4df7f8908e0ce953b6a9637c850f24de0fda239c25fe4352f3b381fc270384d51d1af1ef0dea8501f98ea71f26de97e98799c4b2a316a216bd4af4861ad83fa4570532029564581bb35ac543355ba3aa246b59c6a5d9a91b938f3c4f0ad6d6f567fffdb6fb78402ded5fdc544a0f5fd87e4677326ca003dffdba8fd390487a6469991506a18f376b12db5be3bdcf4a4bc2f5b34dd8f7066bec3b40a6502f414eac3cd1ed43431b033757e86cca57691b0e1f7eec68fad9423f8b0620aa94798546bc878cf29d74ae74af5244ed9b97107fb83abe25dc160ec05cda1c50b76db981aca781868a7913a3e7c98aa5a3ea8bc81270e6f565138dba33c9c7e887641fd3dafd458b9c64600151038db05725a976950307c662c2eb668e3067f943b9bfd805307729b39ed77309fd5e67ecfc56cc231057a6628fb6f528fb969378529dea2c58fa0b4d791ca591ced733e8cf93a8e19907538f45c2618612648d3e1a78492afc154b7bb0285aea97d618e74a74530b492c66c6bd31557cdc55476b3f163196ec8e87f110834ffb8c232dc77cbf2f7b490f520b3b328af44fecca860a19bee9af6a5f69f63487d7dc6b7bf1233c4735522fedd475f905f044a0a7f658a7a378958cca56a163a343a010f4b65d1bc38cd57d08e0f887293fbc106ad7b15aacca6d51558cb8478b119acde04a19b007802a8e9578121304622aee7858d1794ade88973d6fdf981ebabc98fc417d765c075bf8f76b9781dff7c60071878027c057aade8eaf820186035499e9e5fbf8791e6fc0a0e49047af312a8b1b1e80628dc4db4f45842e19096a54733d28028203aa668bd8655631a01c000c956c32ff10572fdbc95b2f26d09fca84c093ddaa122ad93598c03de9273873ece5096648a6251a27e993ec7b6ea4f2181c09bb06852799323f3e993a4b7461439f702cb9df183fcaab11b8bd2ad391924d5e6ef261fea01c91cdc10d9345c290dfc3c040318d11419563d407c8365fef3dd31d8f9d7d338f5f2cd00433d1d06547ae9c650d14d9a7e5b683f0458e7a909d90d4a57201ca5b8753c13bda3591f9cadffd0987d1c7fca1c5a0cec1e13c612d0390d7c0e2f422c97cda29959cd7b714fbeaa5da7b0bcf911c2744a9a25c7d49e93342f61e10a33fda80fadfed2668bfab8767ce80480093b4845cd5ec83082e8f9ad63236743e72842d1a3226640a549c2c1d002a176e2427b2ae612dc272e3d9fa80a904eb8f93f494a52706346c08b06c9d1d8a61a9c7112c0933910882f0da6eea3c389f4faeea51c03394eab4cc02056d704b8839afd76f0839be5ffdc873b88f9a755be6f0229b0843839a25d63c18da89be1c5da930a101913ffba01fd00f2a447d5f58ae8f21554feb47f42d40c32158219dbbb1e5e96ab3dc26cd6a435525c265b65b0bf48d68e9b3c9178a509833aa47c23e63aa9a6f74bef1e4ef863556b11c014b85ac7c157f1e64531b676eb28c68e82e0089d2bd798213c836cc354d4883dc0b607456ab7f894f0a1f73356fc05a5c97a9cf3b231890c39105b751f6fc54063a08f3d3a264ab90cb7de1d0e2f6acb92302cc9b4bb512e720e6ff8343004028ad223a70d395c5f974d3ddd380f798e80edb4b13555c3be0cb1a500e19a8b1b05f9cae85d7eed756ebcfa57828f1054296ffa48d426ceb83c69ebe1b983421f42316ca6f50bf8df0f4d4aeef85005638a304d88764ec26366a1437867c89800aee55ba428e0c07542e123d748c795560153007f768b20bb057fc2643b7db992c3b9cbfd88657b17fbe8a783da2050affb518cab4226cdf28fa97f48651bd142932835f061f8642e79d1f7ae8ff8665aa85aba24a850b2042dd37e61e665a451f17cbe9d57ed5ecb1dce9ec34c576762929dbf46964de7c44c9f6b10fcf52b48649ded2d491bbe4bb6ad578cd31cbdea6df8342dbb7f33857617250b014fc6d887a448f7a5cef25ff69dbc94733bfac1d5f8593af7fbe4759d23ba8da1f405ba179c96d8ae49eb760446d842f0d61ab08508a3e31e4953e13a1b197d00644303e8a9513199583709f41757740a0dff347c3859d3a4ec391481af349019f75ccfdba111a4c338fd8283733115ce7c114111abb157c1a5a84f7b39779a54f000827a250bff00dbe9cb7162d81f6c942b719f9eb973ac7d4652b911622396c517c6e9c7e5f839c049855567fb53ae84579388e3c87af420272558c686209fd92fc339a553f873995932d9dce52f5e60cc0889c3283f94a0d2d5d011154d9935e1dfbb7e747b393bdd8a84f601adca56d4ac5e8e6f28100a7d5522de50dbf1bd7f5604fdfa660a58dc681b4b230abbc4f594a972a73456de1b7f48975cd03313a80074f5d6701db61860f33dfcc9f06e313e8881c385a50de28ced014daf702f01c45368419b73383008b9191293f59fa87a1ceb0cee64d486842ed7c289dca3b3f2e261df644de0f739079ba5ea195468f0693a995dae8e0f7e4611196824f329fc803bc3588d7d941d1fe86a3ecdb3eb8f6d4066ecee371f9a14e5bd46a40b53e87325bab7255099b4fe7f7b09eddaefc6582feecb8dec02b5e58d735a927d052e263027fa879fceb852b9e08db4636c7152f272a43ae4037c50210e90caa3e008fbfa98ed42cd425259096fc06644edab9b768779dcd892747f18a9cecc6aa31dc27d3f12a540447653edd5bed68f50da71b7992434b74d0209746f93ea429691fcb99da0ca32df822ec4332f7eb4bbe6d2111ac84a55932b3e173e388ab96a5a8a17c7d8b8131cf566e0335b0c4a37c5ae24e73c81146031295b69ce3032fa8e4c7616558179cc561f14864190d458cb82370749d595966047de698256126a4ca23a6bbd39201b8649fbcd387474ecf5b9f732e65938fe393a2a1269b06b9b49c5d8882d70776fc823da5842d812be2a65d2f5ee0d64f8258e761e6f2d4c1a825963b367d70b9e81b46fc25e4804fe9decf3aa0e47f1eba573a24f0e4f7b8cf8a886c7ef4175bd317709feeabe46df9719e7d7a4bc2c1bbc15a58b5332ea558e160f5d3b7aa84fe54ea7a24bd8e394ab794e72db7946780272556be33b7f32a0ee651c013d8ed3b5d75bc1c4826dc94f9e3711c53be3bcdf361329544f2993a189b6431a6dda8b81cb1b7c3a69ba96c1ac84a55100c4985cc85ce272e8eb5a57c563a7ad782664d561c3400e779317122d425c9c4193414bebd4d6ad31ba916448f65e9a7ca1f856dacf9d88b695410c8491a759d2c0304e8368b39cf502d0abf7233b1ba9671bc422ce182833ead52597481ea3ea26a2cc35e12a8c83bbb263202d5e9e7a5bb8ab2a5a844d596c24fdac423981fc4dc4291944ae476d59c9a31a05f79f0fe4b39f145c4fba857fa553a17fb2d5f941d5dac8dd3dd07e48eabfe5b98f3c41e7a84986dc3a7a3bb0ed2d4232cffbc50f167d58fb52fa3b357e76430d7f0f1aff6e2d51ea8f5b98bb66c5b5687821f33b9b6c2e407ad0e8140c4d5d4f1739167f8d63284caf4a43688473cd97bab401218fbb2ea13be81bbc05a81042a02eb1843bd46ca535e778e207c79ce3fe511a55d21bf20b24bcdfb43fa62b3469fae2ebd61e362d5d663fb2c08cbde5df9d8cc1faaf6370b5328ffccde873849299d61477a9fcf7c5c96fbc51b24c0f2cc6e39a46f4a9c1f5214f2cd06db62a37e2c6f477ceac0b92eb882d7bcd1fc3721a89745473eb45eee9a4fe6ab323d28f4db957d0c5dc1ed25ebc194f744a2cfe98474868e6acf5641ad454b3626ac2a27a9db416eb1763935eaa5612e43c49e8959ebcf5133863e98c19618e936f33952699fc224f41a4e259b40228047ed6a17cf4f3a42dc76df1346acb0986984f1692b5ed28f0825a23094ddbb8c1750e9035b1df2166f142e7f179473098ed73acb9ffb8be530542f31de88d6677f805cc30ccc0b60787e61f9d195ceacf07a35d979f9c3521f23671f378a6cd58ed2b0620ff7e2def5025f878d70008744c6a53caf325293353747c94c5ddf12e3a42686f97adc4db62b5e2e91132345963b7292fc9d13b484f75d8da000000000000000000000000000000000a13171d2127" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-3.json b/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-3.json new file mode 100755 index 000000000..7131da266 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/bad-signature-ml-dsa-3.json @@ -0,0 +1,6 @@ +{ + "id": "bad-signature-ml-dsa-3", + "expect": "INVALID_SIGNATURE", + "alg": 3, + "raw": "0x50f91c64826d6180843b9aca00847735940083045f289400000000000000000000000000000000000000010180c003b90a20fd3c43f5fc7807747a73e1d8e78cd9e611ad6bbba9b264534594174b49082aeab827927b335526cc50c2f0368fc666efb79c34af8ee90427d1718736acaad47f5959b9b26457619c07c2dda553d55a7498e30a37c92909f6b37c246dca4e8fd24d4cccd811396d276e5d11f1e8d14bb9eb4d5ec49798202422edd57ea4d8c0e8c6388e9c93a0ff2e52f7ca2303e40300c50c926a7da22919be462e2dcbdb3ec235b14290a282ee76a04f4bf7c5e2ec5c8fc0aaac72ce4f8fcf0d42b9fc3c4049ab6dfdfa12623d89c0d96434a8e13cb6f79ad6f4a8102f9a0bfe582d967372d8928ff9d7d7393b22ec1386ee91dd196eb9c349a6a12f7504e66a096eec0a8ae98e62275f6b84fb40a81a390c6ef0102c8fd2c11d303745b8fc49e638e6f3004961724a977a18d81efc67e37d0d44558e28cf9015dfa08eff82004c4a53dfa40c2451fa03a987f70c855dbee37e36480863044165e6d46d4c43278091317beab6f301d61c8f54f94ee88fa358c9aed6e55b80b4196e79a3d7251ede25c4baef8129882a69789df3a8262941199ded7bd381de00c257199c18e9086d9ce3f72c6d95c0a4d109a3a15474805f0dc06649a16a7805e8d74bd1af7658f5f9ef726d560595ff9f072d4cfaaf61283087843b904b0f5670ca551079c759d4a2839a71505e007cb5d49b0437b87a080fab5e2efdedd1d01f0f1ab72f0e6129a2525fc6e9829b56ce9d9f287a5bd80be8b1556e4ca82eafc60ec22315448768a72e45d4d956c16ee48a0658e307f81ee0f695f1b1b747d1d533d8da720f088b64608b1edb2d4d27247b2cd35e3d94e1256a3c5c944bbafe07b55ca74df4ec0b869733ddb466717a16e98af4ec310d046c90046c024fb33fbb2ffbb105d41bdd0e0af27b1239aa4d92b6ef8d727e51372fefc3b5c8bc6eb585a0ae2dd9970009555c2c2ced5e5a1e97c659565b6139dc4f3bae788e21f9658affa8fdb6f4733f7fa83fefab91a030f8ec976b8263c17abcef46dc22456d5347eea7c30dd25bdc3caad7cb2010f06573d56b6e5d28e6e847d8df8f18d6a2655ea66fe3c8e7e4ef192b5a8aeb35f8469277657b77155142c7b1653d5eb9cf9c4d69bbc5746e0c1876e330f9016a2f5343ec60b2f35ea380169a2bdf102888e6aae7e797d0bce73834f418018e8e55492da8236a542a999d9eea55bd52ee2e59feb0329d716c78c0bfcd79dc27cd9639399d2fd99d2fc9c4900ad60bdb8221501038ec4baadd2ac4830b2bfe1e20804c818c8e089661e7d842bc4e566fa0bc2d7968a44f8df0d4e88e494fc7bebdb695d3a8edf6a2703817b0f8c1a55569ac4a8ff0931137f075797e9744135a3fec6c767af26d4592a9022271a4052b1f1f24f072bd5ceb1d19e02b0bbf31251a7bb8b723bd3da02f59ca1c0c91bc10896970a1e0f8e0fd5b755da58d70be8935f65661629a9f833b35810113ce80125f8ed7a031cfd5eb1475b597856b4ce7629a9429d840a3457bbd70c05c73c6ce84dd59f917a24d06ca8743225ab8c266e209fbadf57cdb587df96eedf54c04fb3f83ec0dddd1d8bf9051c6de4db3aa099f1779f3f30f61f432e5c8f6b7ac4ee6c6dd6fce667556df155ddb2002735fb7addd8acf74863ccfe04a3088317634eb47e56b18c79f31318ac5e448a9094b5c2c70b44dbbbff7c235cef4701d504723b032726d009c6d7f527e645a23fc1ab478e6e2699211694d575bd436d778e7ae53868c63dfb78f591d82b979585cec8bbcde61f375e783e97e8f787fb392fa4f0bc3e9010aa9ec3cf6471bb16355c3ed3fdf2ee5b95ade86371d60fb0699a851770a212d0e0eeb3f20df78ab180343fd79a9d04d8dc56d9fe3d820b27d98d12275a40d270f4181aa1a18305c8d3469a954b2e85405a394684cc234702a6cb01c04ccc941a4392cf64ba31bea700d339152fce6abb0dbe84823b8d3b18258a29414fd52c91ccbc198e101287b79d8bd0e5f4b05a14a07055e66ea37d781934840a204638bffda400113bb1344126fe1c2ac1e57bb861c3d35349b1fba0c11e12921262ae52fb2e0bee444f8197e2817b9356e10af67e794a7967055936bfcb51f4be6fc5602a8df97ddcd73afe83c02f00d4f1d8302bd2e826d4c50fd3ded9a74debd0e807b694e912a8a3a800f5b983e171898874b77ea305ede4abdf0db5ca84a8a60b184374c08066537b08d42a609b97039ff8905bccc4454188b051c5d1e574e1e8b74cc5cbded064a5374c55f17002ee9b17447fdc324a12e3f2f414b491cccf20c9f98820461f4c7d61355a30f1a6cbb2fe7403b90587298fcc9500519451e44225c750b8b32a649ea288eda389e596390a5386652dea5d0e096ee270bcab9da0c3c4ba464f44172732a748e339cbfc8f0c1ee3187225e2fb29e67ffbd84df8acf759c817d628e03a245e9ae0cf00939fa12964e8dc124659eea8798b097ba52480532fa11194e4623ff63f6cc1d17c7080bb2c1459fe8cc9b197b89ba91986b7bfa61e514bf5c60f981e63baffd9fce44af87ad73fba197e46790fc03f8a46aa6d7590f47e08daedd7f564685208ee87da84b04b11cdc0c020bb26b0abdad3c1340649130e26af9c7651533313301e8b517a84c807d86a4c0cff68566d34da4111d67bdc77ef5f49ec7d83af24a143bceaee020acce02499c725ebc341a86d91c7f63dd962ffcc09fc0b5673873ee55cea4bba69b5058e4b364fb3802832d5118774790dd12eed78330412dc877cc034309a7e292ebee955a431fd46faf7884cf3bd5ab03d02b8784af2a84bb907ba5f021fc332f638a2d4b6451ea0a2cdee6ff1621d698eadfc99d6f405003f300e321a9e80ed3b577a899fa7dd891b53cab8acaa9fd3ce02640eaa75646f134c190817675b9e4a688d0668528fa3b378749bb6b1a0bd16873e89dfc927dcf568fc3cf94ac49d289ba1fb9c58a74574c8fbac321db256bf919e9432d6a8ae9a0dae900901f436b13d0c2b753a5eb6fcef03301d7faa15ff32ec0730335b13394bff66ea83a7043f9e1df5962671ff2d2759db234a4a4fa47fd3a9359bb14ef5b5fc398836d42afcc5d5f252b1b061afc6a0815b3a7586d25eed5ee52c56d2389b8f2438649ee652b431d3cc4262c6e5ea1c0ccec21aa6123e88b4bc933098576bd78cf5bcbbc278ee682029e05e91aac2043ad3ec1d3d97f6ebc6bd5faffa5bc71328cd4351bcb9a0d8d1ea9253b97b08c8c53b20e29703568d5d7dfa2bfa6aeb3a93043e4123116a125311695a11c8538658210971d7763ed7870c1309893909e306df22fe968612531e58a91d19dfe2c658ade19c8e0900c779af8ec333d19552e42cdedbe13ff85d99b10baf8daf70951290db56bc7ea049e6b468b6546a7f3ae77c2e14770eed1ea345f0d139336af4eee686ac2e73bd4262cb802e0173fb872a77cd2c0f3421c497b0260be79ae29d04d9a9da9d7bc101ae3ec9dace1133332f05b7b82aaee577c06c0d2a8eaa8a96db8b899cb3240cc4dca4f8eab513ad5b3529063b5df3664dde0db1e0ae5c29e69f011076fc7edc4261d043f38f1c68645466c9a5e685a07393b7e2f8f74db86742ba5ac089b45a42df3f943842747674c1653aa2a8ef282f64e7ec2ce1fada994288a5f9b95da4bc083ea008308b91213c64a08868ea0fdad9fbb1b485b793bce6e4fa945668b2351232a7c8a084fb2d87a5c83e7dced6bde3743617a7c4babcbf9381694b64d7e0feeb6615440e927a63293c6b695900b1e7afad1ae612c324a88e6761c3b6fdc41d18f514be1ba3a1ca53fdbcf8c19f95bcd60223abe52d07fd7c4114dad9f347cf122f6241429da7e598959c22692910323a0a699595398f518c58deea7159920d89e3e65702bc2cabea7e9ca0bbb7002fb7be5243bba6a08a12238ead443ff4394510d25eb279885d9112c44529f294c5a2bf493a74ba8f4e38744e632680b3ce055a897d2a5468ef52e6e70dc5af55a9fb83739f6cfc6994871662b8263f2e07e21a6514624909369e0138755165dd2af5a791da63c0604b68ff160fad82a578a06e76f62bb7e951b81d8fde2dade6c3a314eec5913151c16a93a5abd5ceb59ad96197a349721ab123b42f799dbde36d7965e0e5dfcf43d8d1ae13f4a00afd8dde36137d3de87f4e2c0366c18f4b3a449ffd9afc7c742c50456f6e642f7d09e86d5aef224b20ce5d8a2bf164484df8fc87daf69e459fc78c6b974cdb8fb1dccbd5290f560e3114302886e2828ad73ce71b06186254206743076c6af0c3d1facc36695dc28db1d026686b141247e1c7a9323d544b0079023cd2adedc0479ceefc8e0c34782603d0c27d18768eb5485a85bc385ffdfd25f735688a3b9a0c6f532b2a7989c751804de0163582293a17f635fdde14e9067f12929b079f89a53dfc87b986f89f718320ede83cf4086d0d095b24b66d5e3f1bfdb08b79cd5b25657cf2b20faff1d199c16bb7f631b33970b34c12997637447e4127db1bf580b339807637a86e0248cbcf8e1d30ae6fe053e2f9b7b3d0f9e3f4813af908b633560779012f9e06af00e252bb0df9f0caf7d1e82f8deb2ede21d13f406dd9ea69445d50844c95c921d8d1cbc8afbc5ddcd4157e65cbfbbafe2670e9146a5643db049a8d696f0eae07c3d4099447ef78bdb90fc05d7cc97bf9b9dee8719464ec6b9e6de866f73914a80396dea3900a9f7b43a47e648e20a9504da92c47ac65368813e5453e82020f8861aba2534346e6137e71adb28a5ff080365d6ea26dfc30ef5500d0760749d6e4e0f93aaebed544832308b19f72e92ebb8eaec2492c6ea7972fd359a8b67a1f4053bfb1a3c6fb720b5925a7a827e59b3bd0651b8014c77b25d61db17eb169cc2fa2442c82f68fb42200c59baa468a9fc92f13273ff071124f8b31e2b4b2517ee622d29489997ecb5676fb52e3002371c01004c214757b1f510091c2377a08d058209d18feb9b524a41712b6df4b92f2b14c583d3196749f367b3bbc8ab5e9e2615c511f23ba5fb1bac2ee9436dd8d162bd96f1fb663d2b520ba7e8ddfc2a4d549b63714654cfbb37ee1dca5f723139187ada8f8d5b42ad09ff196b70720d2527b4466d44f33cce486ef2e86311c75ead31a17b16989dc63bacf0d465379d9138df7ea2ebc71f4cc3b6662e24895050e2553dbc160a567d6722964a904d43bf2684206cee3562256e98addf3038e968cf6c09c921e2c89c9c249f6ba7afd20dd27587b4143f704f2738315a91c2d40c467111b4f3bae4f77bae402145e742ba83a527aeffca13ee2290988df882feaf5a3c24b416d59e06cf4f8832a016ce55419b7bd2028545557528a0af23f17942433e13fad089fdb79449bd9d99b0324b1828791249b6789a09cdfb6ec40c0fbaf8b28ea4f72d3df5159bea7a7965b94beb1bb01d87d76ae7ce47fc333fc152038ab4e7ca64a802f96f2e92bcc53ad9cae0242c622c99b2daf005e554cd6ba127991d84841ffe3ba0674eb7930509045dd00ab91a7c6acd2f4a40e7ffc9959929851e40d417f488a29f7bb5af3847a8caa5daa0682aea870ac8b866ccfdc435971e3d862c2f651cc6eb8a33fca313a56ab8228ee9ac7dce14ea3c3fba4f58c70888ae558d8cd632a2723ba54a3d538f4e20936a2ee543e9b2141e06095c72d4ee19908febf7c248c03a78655420da644746e2d508c31ceb0b648800d95dceec72f7576502046e5dce54b5a097f625001bfc92d6e4633b293cdfa63b1fca5de9e26d03ba2f1cf3647dbdad5359ed76bf702f0621c057dea3617af678016aa13360ebb02c6cb2fa0d3f137a1a3c639c989e12383841ab7ca5a84f84c08af4b85416ce7ec3ed91636a79add207bedf9dfb2ff626387f20cb3315502b2b06f361cbf6a51fb507598af41c5a5b9cd95ba1894ca372c5e1851e62a0d3d78dab6f92bd43ba6fcd71230b6cfd843d89268872b75e3c5b471db530b7ab5451dbe63fa0bdaa7d74907cb376643e129febbe6ce10b5dffbf323dc973f097d2081e06aad65e674c5a41bb81b80556fd78691fe6b5bfad47fd1b64db577f27f22f17973cbff3a7c4aa43569bbe6843d773a2f933f472650e88e0ec6643f87dfd37e7fba915c7386a130b8d4f0ff4d0e99a633d1f863f3e8ce4e1ac5e31438d89c3b6d5ace3aa6e14e7073164ea01e853958bece389316023127f9916297a47c5d6ab5513bab874c1ae3bf2850cfab9018cbf50a7febe03ff3e8e4e55ae5632812b6a147edf051b461bfe56f01a6ab571e0553e37a57a3a9811f4fda2e189d79b74215d6fe199595d18c6543c747572f8cdc61a53ce09d9ca96b43a5af5b56b53148dd4fdfc1e22c9958caa783f2d112d8d5fd39e6955df75d35c59a1967fc0d8d3293e39a6cdf82d6846b39a74b1a538372c266b3f12d7ccf464ff7e32fe54342994f51d344302b3b2e11eed2187a741eec99ef0a79a19a854c03d8bd3fcd557b9d8bfb35f0976da327fc7e8d95fb43db8e66be5b373385fc1b68099566c7e88aefe92c7c521d084c15c8d403d87bbc975e8d687e2a51e5ce53191e3db5bdc50f475853cda7cc5a7365c41035aecb61444c2a48492a600b58300b2805be97b4e9e30526e9e62bb3248a17c3809219307ca85351495c943a865359c783cf615a809c739cce0786c6045d9c8071797001434cbae571d42cef415e28ed6adab09ed10e0713dc1412ed80b8d26d549964321559137483c81b19203080b36abcd68e841f4c78b5302da79fd6e555f390322ae67e54c55749491889d79eb2982fc4428086bd1060c4113137ddb4dd7c9b690b802e805999d4f5127f66f6b1d397dc3509504e2196513b5787407b45b928cfc3c437523daa4f876dfe061e351cb3bad99ea205ab276c4f2a5ccee1027104f09adaf55cd282d4e9e44ac2b65f7e423da1cebb0ac70691347e7a7bd0de8bc9fb2e7a08afc0075a0e85902316cd6ec9a5802c51a6d65bf3251ae712ae0f66de6cba1e51efbad53ad7e769f851799caf5fb81ef35b4da814915dcfa67553f1c67158154707d16804be27af2115559e4758b313b9da4a1131718b29a75970b3f0a5e2f2c11a0a1ed47f238c145dc4fe9e8e963d8395c67dfa94a232b8133a0d953b05455f79e0bdff0bc3de9c04d93d97084ab99229622cfe3958ac5fda6757de1696b575f6250b441e6368386751b1d2f6007d254d152fe76578fbbe164af49cda805b9325f7ea47f5e18f3de1ce38006ae1bf027d3e354d6f923d8bc6286aaf9b9a7b9e7a7fbd36a31db0d88166dc68e7eb567d8164bed1e279a8810fc21656621ff7cb42a21ee04e6086924bb62dddd16c3343db69250f7ed95aba953202640bef18dfb6c00f1ee03c670a5cc6c0f3cd7cb006590dddffa6f19d450860e289f85edb4fb0dbbd2f992eebba09cddc1b20a3c98d8739ad1875a514b09b1f23cf406c4c55cc4266e0b8b283fa445849316c30bd19254e9d035756d2773cab7f5fd56d6d3a094a717ccca43251201cfddf80ba1aa0dad34f5a3acf8476b784fd53a1aff1307a7838705112650bd25dfea21b991d801f018a5dae26edb9dd5a0ab940a94b7bbb90fd1f30f9d1dd2ea3aad6d0a2a3c42fd2641233c7d624314c3a54ce616d2ca5683d04f6fc0924f0b667be32f4de8820f9cfab963a287a1c708857ebabed9b5bcc35d539ef9bc170636cd528ba86a620195134cacbc2b8e742376124b67ed8155ab53979e281f97b184c60355b008f15f45c8b7a506b1c1f511e4aaf0bc32fee27b656b01ed6afaa4053ed674a60175b6c89a77d42963111d0940730db02ff67534fe6a296e0e01e2db6b3f0fe9648286a0f3420cd4393163662751deed6457abbb370f83ed92e9da86a0181df13b8ef33e5718ce524a700ba5f2b40f3f973a67c1c412dc251c19e6b7ceb279dc1dfc36a3567e3a98a9d96ef52b0d0734f57bd9edebedd925167f230b1c81ca938e94ceebe43d2573735873a436331a8b76c1169c6a869889cb74e5d33721bbb99ec87f160c025f570f1d11c2e3ae6a52580785d854790139510179b003418dbcee1f4fd4fa39fc134521ffd7f29cee650472638dd04d8331ee439eaa32c57b56c4fd9c9ba87516a8236dc99b8d6e4c2a48e53a6779d5e13bbd73cc7917f0cfb8e231218bf33bc3c213599eb76476558f0e38a3979cdaad6ac6b03bd0ef0aefec634fbe0e1e87bd78123a19b7352326b9def856ecfc02b06622f94e8cb2a1cb6cf10d020f789a7db775063030f15b463f08878219636f2bb94ed11a3ed9689d797a3253809c7f2e0c60672e8476a9e272075c7f808258901e611c4d535a11bfe01daccaec3a26a187ab45a9fd0bb9a7ecf2e9c4aa3177ddaca1449f19f78ebe26be2e25bca012a10649b56899339f5418925648f3253bd716336dcf65e6b4f16d2ae51fed1acbc8335c103f721f46023cc2043f568ddb033aa5f2157e52b89eed4571cb523fcc66ef5cddc90679633c2a46f45f1a86c975db4f6f37f9fcfe54809ccf75305bc9f242f26f30a0ad5f3cd71cbd31ac45ceed2dc8571142a09b7d3091a4838727b9a067927e17b7559076649b405dfd480627881489d52339d4a8943ca396e92b92066e45d525acf7785a944345d25d721d6a354b1a9f3e2afd379d1c341badd0dd913a3471a5b78a81c0b338a2984e115d003b1deec1b44fd19824279d742017248fb4434cf47ad07fc87df86e634b2d8f6e0aa572088678b9a9f767404f06c84ea8cbf65d46effbde7de1f090d3d4b9e7c7c3b2b1dfa9e591efe12ffe0fc82c9eeb7fcd9f25fe438b39c46614438d0be7e1dad11bce8b91396f867531e8c45d8c01119abc2b20be253779b5e651bd80536854e2aabccddc5f4fbfb3497111fe9a8f8a417ab4dd806745c82126524ec325c931ac1f31a3cea19e159e1dbfbfcff761cccabefad38062872fe8a45a14781ba12551befb31c21150a56ccacf9815d8f458b1f591c71ba7b0459e7c09a4eac5c9e5b2984314ecd2f7054ed055ba082204f7ed62b1d513cd0992bc10c28bc745e30b27f6ca28ac84dec6cf0ef73c971ce12b2ddcc0d6264d8f7dfbba0a20f8ff1d7387cd9d9872f4b345b409950d66ababa9852f7f5ee634dad6085666956b97e4c9142dbdce96bf42d1334c61d04ffed5ac8f12a5075ac87a7416fd52579a876c89e22008759a93ebc57279215e178662a064bca65670089ec688532468c07161f56bbafbfa5655768123e713c7aff52852978e9d6004ab3a434d9b5c73f0d90dd1fe742a169a84f0e96a189bfc5265d8c5e2d9e42f5503d04ce01f9a912bf8b9bd8c282a4d40bbeca55d14971d1d305a16eb85d02b4edd8d35baea56156ba12f4e344dc4cb34509fc780ee97d24173a75e49960ec32055710bf8119d005447c6c391365737a0cff68d9f44868b97b2357dc051ed7fcf590b32292624545935e87f25e56b3e4a2b9c39c4936b5be9030b4711f246623264e0370291b675e75e1ce9cb425e5fabcfb55e25f084ea8a1b84870135ad997f7b700876691939cf268204669790a10ddd3d38cd22252226a09fddd395482deb561ee834ba452750d5b8e0de63c77c85a7446dd5bb29df2620f98e07bdac4cb59af8b9dc64d427dab780257e252e8d6793fd1b99f7c3162b4233a418526ab227d40b9deadc943d0f108a38d7a6b075465a44c920c0146338504eadf826cae345e864452e94706c8dceac5cca87469f2183a9c918295c09eef65f747b7a3d7fb3d259c4f531ffe48a5c338717ceb45efb557a47a593fac85cfaa4c263c109d385c01a3193a6ad1be5923d6a53e6c369a2b5e704cd6ac3ac255954c3fca1079895c596596873c1309fdcc5f36fe039d06806dd16cb00bd028edd6b44fb1e9ce4a020362824bef6a59502cce4e1d3d3884d7d865823deb092916a215ee73bdae1d4baf7f294caac7f63a36c2a15a40517438b8cecb93a5da3e11c25ff228ef3e7281360a2ce3ac66e69a2f136a83fbdbc44dd1737e9a31bdce16df9e118345ec1d9a9c47bfa60502722c9813d31c9f1b0364e2e25d77a0816db52f7e86bade9aff644df50b1cea9a339e76e869fa1fa50101f8182a2a6aee2e90d242d4b4d6b999d1c358a8d9297b6e0e2ec141c2b3692d70b141a213d477e87c52a2c87a5c6d1f0fb091f35f50915878ac70000000000000000000000000000000009111b212a32363b" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-1.json b/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-1.json new file mode 100755 index 000000000..414ca8087 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-1.json @@ -0,0 +1,6 @@ +{ + "id": "short-signature-ml-dsa-1", + "expect": "INVALID (length)", + "alg": 1, + "raw": "0x50f90ec4826d6180843b9aca0084773594008302d5709400000000000000000000000000000000000000010180c001b90520372c0f4874450fb92ace74d41bc0326c7f739589f9b86a97afa87ef65d5939e608c81a44909e41f41931349f744b7aedff8d5270b91c4a2f61192e2bb6e3e6d12231deab235359e78ccada386becb6a6a1105afc0999243ab8b363f7cd2c19b2b741c9969dcf20252f20d130dc05d9244f58d6de9b4fb4b6f0125c43b60ebe3c7272b6ae7578f1abb4bb5e2dcb31eebf4aa7089aa2bf40a0ba5eb73aaa90e45472168738cb0e866547e079075d0341c4728ed794cd449d0cdeceaf64d09173a2677e3f2621b56014df58ee8de2bbcf8cb2bf369e57a28e40b24df6d0b15d3417b7b7fce3c49230b3bb7c7080c4f1344380db37299d8c0c29a7c9e95bfc4f3ec70b767895be6ad798449f94c92f320696f8f9ec844fc9451f5ab30874e6c78673b932e24a918d5bc03f4fa647c8679631ad8b30ba4f9a1a790a535104f5079f781fa4c4aad807777327e08bd6e14b957e527650d39e2de7d30da7b2b27457d3539c2f99903054bd1a6d6301b2f83249db80dedc911059b047b5552407ed32b79b57ea4968198decf978fed532277fb189841d0c17f261f1a7c4618c33b258a71cb6b2b921c48735c1fbc375a80fe2d702e9f70db34547147f6d65153f1c508ff90aaf57dfde59ce6e56c5c52049b10fbc2640cd937bf5027d755444cd5e84aad66be4ccf04f710f0b970cbe7fc5e4e7a44f5d8fc2af94ec6df87862dabe0d85dd17e43728800d5dc8ff9e9e1fd349b9d6431f264836a447646a1ee2d73e6a4d1803d71b98510d94d53b5d07764400f413b7837f463e273980296ad5e78a62c83fb91354c25c2e28bfa19480ca41b0ca2d8beed456029eabc0ba69cf3504cf1207ab21bed0e3a60795f5b066019132212a9bd20e98b43bb32484454b7693bc63764d0ba8768da4336ad16a979b1d3e8b06e89afc4caafaddead83ad861a4596814062468d8cb2e131e71cf38c4e335bb3d1d9629251fd50a4273999a20e11d9a881fa2465c2ef32301fa8805ccb38b4656e3c815b54ef42f292d05847c0e5149b0a2ffd1719fcad10730b763406e9e453d2e4a556c397a984a7d8622466522e79f715f980279cb2d1d74d5fd15f8beb8df9c0a1fb93f0d5494ab701cd60cf2b613b484a191d873449c4815f44eebb62658ef90f7033a5e48d40c8f4ec9a25d4f1b73a150e5b03a4feec9142362e77d74d364bb8a40f9873efa2d9f458d84277fdb0063642d9ebc794356368a0b4e53f6ab0d9acf4418fa42d05c11db12cb67d6c4cbbfde4d85358abaf8042510db53c1540fcb40045b334bc54a17608e82433d1e9e53c99769b86b69b8cf1914584cdef479061718a2cc5bec5c31272e0463139721c0c3523a6ea31832b5c15aa59819304c217fbc51a2636bfff331e6dc1037e89be15c17d6708762976329353612f312b828e525c09b81afafa5ae5c25d82b70b6e55f892429a93e5eb4048ade675583e828da988f9d253123a06c0ed047adf4d93d20cc6c865f5a761fec27811305165cd4bda05f563215d0612944b88ade9d64477ae8fb441978720e70b0d77e2edafd3a2c571cd28a42cca2f289d157cec813c24e7f56051b4f28c153adfbb2c1ff90ea1fbc03cb89603387169072442f5d3081140e2256ebadcd775d2f1da92c15a9ff1ce6e980b3b1e91a7e379081ed46a4259fada21536af318eb2043ea16cece60b73acd415d239389cad9212e15bad1b1ae38f93c756635a9b87417faa844e4f43bae1f1ae68641a04f0ff1d55f9045cf7e3ed59fde5c07219b9113329356d4300885ee19c9955c5757db33c6ae75b49d035003171d02ccbd7321d6a14db0bd011d4877f04070dbda3b67bf22d083eb90973664be581b59cd495740a8a9aaaf7c6801a8bcedb531ace47da1be56ab30f1c4ccdaad6e81aa97352baca12b6c69754123bdee38c0d57bf15f0850572dc9b456234eaf37eb478f9117f952ae95a0d165d12d948b51672a03c9610a98cf332d6ad7ab8a87defb3ef7249cf8c3a815129ecf5600500702b7916ffe570cef0714e0c083a581c2971c45c4aa6b1c5226400e5fd594ea3ae97fe94a0dc7f1e0979b11a2f3d15ad54fea957992ada816f97cd76168a53ebffae36e5787b0f69e94b3e08eadefe4937ce8b383b5022e57ba7135cccd5b48e38916f1f0bdcbc5858bf93cad75195d4329ab41a518d820262b1b610f7bdbe1d6749d006a0dfe18d0be1a19fb3d8e37795b5bc37ebcd884f91459164cd2536b3496c4b25a4c74282ece5d64ab861184e942cf97f0edbe6e1293c4504d861e60d98c4f6523df27a1e80843005ad21665b3adcf46f349fb0d905d70631d2ee51c0086b252778eac27346eee65c0fc88c6db5936337b0afa7d8cec656612c81e11cc55abf421df770e6c2588c743d5540e1280be76309defaffde2b82c808976c337ee13735a21900a4686423625a0ba4819581edbe574e6d7053c5fd98d288db4104ea64fbc0e7ad11d50eb1470a882aa00ebfd983cdda14db34f7f968ccc93097cf037dceeb1375f2df4de09c8785f5fef8fbbe284566e5c9a2d38f5d2f9145b7f5087f6a89a56679680ca4180ad7da3ee45da685f0255a45db806e1379c1ed59bfe63feb7d74a239334c80ab9c1859d205ba798810adf8afc569170f94167439d137215d2ce0b2fa983ac138a3ce201cec4927c62b740912e7287417f86beb07af9c83fff843df1abd6e6f81865b82b3168528d1c473b4999b0179f1de8ae22e8ed7f698ee8463eb93fcfd4e017f29ab3f15a2e061de6deb09459d4ecc62741ffd8514d5c1f10eb3b1525ad60512ffad00e360e0d6add8ed6d6df48d63cf1e36f306bd76b1a245cdd09951727367e45b3a02d748dbfcbeea342be4cb0e1e3108e57993581409f8c6b34e2d38becfcf15c653b92c88412c087eddb0bc21eeb620317f49a9bf5d6164418a26322e1964fd676a547862c2a7ce5f13898e3fadec79a638f257532cfe977fe8ba5e96782f9e1e3e8b5f896a80d816141f0c988ea59ea321cffd23f298b76e49e92189e7f65718d14091daeb82d432470a2e472a39a154226a43c543db2bb933adad08344259ba08a65c543d2ee07b67328ca2d4e60e550b85215ea5873fedb505cc1e4db49e129249fb632ba22f11b897b9423d08f96ceaa863cd29dc16af6ac76c4388c2795250c04377277626992b085ed7be2cf1d63a2eda4b65e287081fdc4e9a3224ff57d81b3ba8d04eb88430a01c5eba35fad028e8de1812920cee2576d0bd291407c5fb70c5ce07104b9af7b98c4c709c7f019d4a66b136120b92612ad5e73dfcfc1da0fec3a7928e57d7d4769eecbaa4c269f2859d31d47d1ae40e4da5bfa6592074c5bf54b04c707b8d97455a0a606686e06bf5ef7617da2532f305267f61c5f627216b06ecc3da6c6f7b420e2dfecaa41657eab20c89927ad6eb5c4fcd513da89a637755f4a98c45cfa108f37415bbf49ee6cacfda8f22f7101a9798d844709a38f9168685f105157a937bb10d4f5b342deab8b8be8231490da52cc0c407bf942270ad93d4a9bed5c06499584835dbba75577dbbc47fd3d397f0417ade99549de4412c8893cf3e1a2ed74c234a7b60461efad57d9c9fed9eec3ebd652282b045174e19355d8cfcc10add9192ffffd428150dc3f48e0417e47d6407008c62486cd4057535a5a9ffc45ef559a51fbbece64306f64da9740108d0b51d01423379bb0a72fe050d2abf5f5acd25cff57f8e3bcdf938749c7bbf77437424ada88c167bcb6addc309b949a8e200b9a5b6797522635731b250e2405f98d054aaff4179ccb4b24159e4c033329100cadbef3da262203622d27899166f6c3c79a35daf7840853b9a3ce494bf035235cada8c31e28be56f0976ef9b96f15de57e6896a5aed57a7b5ce77cacd1c806ecf83566bee5d577f7414a106ce16ca6e8cbc144f571b1a37647041694a6409f68d15604960417a60bc4f1a878eb01e89159e701bb8fd96be45395a8b8c4f0cc5b982582741c4ccaff8961ea892f084b10646c7a27687a2d3c92324cc3a19a5b38ca2d5c573167ad54486ab3adfe9219882f947cc6a93a3827f4b51d76e90ffd1587646d921482022db8b5a22519be3a1e62e9a13ff9926e75c42e07aa295c8486df69dc96168e920e13c85eeda86dc560b9f5d4c77cb8ff001d390dc6c5a911c573ab1711df534930ef28832936c80cafcde731e999ce90741e669d93f653efba12466726fa997e7ad24d34395a02b8a4286f3604f120bf47e8ec41954e6def2de896be477ef7916f18214d28f58ae91ed8d7eae9e2df600d313b6cdb952195e9d030e0b8fc98a68cced3070f4abd2d252727320eb54b602ec861ba630ed3c5d6fc8c8b39f4f1e9c198a6dc8d5f825159ce15fcd7bea5701a225ac41bb152d1a077adc03ecf06870375f2d2618094a648b40244e4a981e7efeadc608c082dc1824c4ffdbc39afcc8c464ed5ca8dfc1540ae3a6c034364c356bf13f880abe8633fa041db78f4be0d17a4bb00959a697935c844c6ddc02222f7aebb1af2c96a757536159dc1dbc31131aefe4c198ccd2123eb5d0ca6147bbc9ab43e993508ef4ca383e2847d9fcb4c975dcb240bcfd164daa835311cf7dbde0f256deb5f3748b55c312a29a042725ecf07caa904513e71b4c0ebd3b31c2938e710e7c6be819bb3125e638ee4b54b4c8fe16df1cee7587e6bdfdcccf2e3b2aa4a54c86b0ae711f056c229c644f519f60570aed60fd3d0638dc341625fb4949d355e7d84cb478133d25730162623acbf5d36b9ed98dbd88b6bf7bf1f55006f5ba2d16297557f966cc01baca56e3f6435b724c0b6fa4cc0074efb0bb2cf0cba9a1c73d3337db7dc0c78b87746db7bbe5fc003edf608ce5d91dbd8b3cec0f738de14c8e2b6df47df91805eab5635402ff26245430641abd9511cffa6bf8d352a1f0d97ce2b08561c97a5f07a07e0ac42a2a73366442e0bf125a718553794b021640ef9f9f07040068cce2337606af46f897b7ad8ced05e14f7ab3e2bd847f810058d665a0c3b6903efd8f398c31e356b48216111d30348acf93d28dbec8e603cd16ea5d3b24f38367c52f5629fd51bec34e86ff21d4f5466a53aea7048babf3afaecec2c9de099bcb2845f66689e02306760ef5274e65f36fc61edf8112b3b414a878b8dbdc2ced0d7dae0e95c5d6e7c80a3b4cbccfe13293e454b6c757a8d9496999fb0c4d4dfe5e7f3f40e11172324323556687e95a4a6bfc4dadbec000000000000000000000000000000101a2f" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-2.json b/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-2.json new file mode 100755 index 000000000..27b867d52 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-2.json @@ -0,0 +1,6 @@ +{ + "id": "short-signature-ml-dsa-2", + "expect": "INVALID (length)", + "alg": 2, + "raw": "0x50f914bd826d6180843b9aca008477359400830383209400000000000000000000000000000000000000010180c002b907a05424000ae9a496294dd6b99046cfdbb235ae71031b379ce274c13b0c96411740cb61021a5390fbe8fb56b642b4e5e5abb7aeab143e0037f8db283b9f2febd650265ed6b05f1b867c124aef245c1811422f92414447fd0b20844e0f1b1cb4eec052400aad52b9d773aae0015c0c390bfdde3d367bd8ef9c3c73bca3164b9d418ecbb2d25303bbd12739a858c5fac4cbfa0203b9f3c319e9bc89d17a7a244b57d6613b5caabdb528f077eff9727015b9c266d777c0ba11920118c7ec4dd59b380c40e361a5b23ce04be4c61e12a1c21e091fa0d890687cbf588944db3e34253c75cdf797378de79162e0b4ca309f550365a289f652dd6d559478912cff70a5417589f73f14640970694d7b5a6bd8f000a65c632f0326ed3d128fda96dbea68cb812634dd75e9f63813a5645336681378b6a63220c066550aba43a5b937131d41f08752d13949a115a74bf96fa1925ff4338e10df0301abe40aaa49e14a1a1d58eef005a0f1d0299267002cebeda20cadcea7419cd0c365c53aede1aa36efaf764d3d36169747cdc8ee9a09e0a0ac6bcaeaeded0cd303c965d705d1b91a8b35f408ad8a033b02ff57610bddbfa60e2114e53f20f8fcad15dffac6a494c3f4f631590f2be3422af14cba7c900c9c38796952e20c3069bea2ab54bf0edf9315903aa5cf68549f878eafcc77561b36f8b78d950871ed4914417316f868a2bc54c72d3c9929f0138a2f0cbccb7c4141e94bb8a7ae11f660861cbbe498697d7327709271460a75bd4e024de3d4d6fe5af066944c96ba87459fa948a95eeb61abbaf643190ccaa9cd18591eb6f249a6eb92db89fc95616d21b41d7d15424b80a750938a12cd57d50ef95aaf222025dc4d81df320d9bc32c608b1c5a1aac8bd14c0f7a4c4380cdd65c793a6287050ff4d609102fd91e47e7365fb55513aeca273618528c199f7bb151e9c11a0bf202147734d1be9d5d0e9318096fa567317ed9fa6a8efe201b915b9aa05ca0d19e15c9a80449cc130b398ebbac3d938f55eea8f74e024b0e33dfecdbea02b920ddc5b277146685916194bfa1f8ac7784c7ed76923d4ff9ed97d3ceac283f9b26977df0133c5fa4fb5fcec577bc152e926529f06ff50c204c083c0b4d6b8d474cf5cf7cfcf7acf76921225443eb0abf5e4c76d0a3f524243ee4e372e80ff0f76dd9d135f240114a2ebe6d69609b6c60d275f251d7dceadc600d18e0cf8bc8fa8392e61fa32b8f7481c4883e19d820b51af0f87d3f7faae44e3b908fc759c6de59361487d8e424ffbd662d57a68801110e9cb099214143253949cc479eaae0e321fecab90c63b06819ce3cf56fc2fc1419408075c658024a28950aa47d549bcdb8b5bc9aeab463466c7834ca7d73058c206a95a023f0c8ac95badd383e63041e1f0ef69f51634f5ce2f48d80f8f2e92f4a1fb5322930141fc50e1e20bd235a8b8d768d473b46711257d028e710f82f0b6bd923da05ca64ae805f708577e125b3fca2feb5656f61ded034eaae481a195628801c82db85345f9ffdc72c860cffe2264ba4be2a08fdb37a4f5f80276baba4ea637847335c89dbd35504389f68b2d61ea66d4eac5fd0057d9e757d929214a7d83daf2fc2b3f840e083792d20d772584b252ba955ae8ae8c36af648c59ae0b25d3bca19413fbd749077b6969db5847409d13e4a67387e59116fe3836a733f3253d47f9919f49618fac8edf5fd711a4239447655d6c40f479f86ef3c9d4dc1a6f9683a3f1bc5c9730025e76ea1588d43494f59823f42c207e34412f73c7e2a126501b8fb810f12995c213063d909a5a9c2653d3511ceb809efa69c638f4c977d46a2a305cc831ecc0feebf5d9356ede6c780da78fe2ad683b3312282d5142612c0d1f85108de04de5c3d5414b62826d5b75f8887dc2d932c40f306c08e5d4f69ef4d344fe4317552df9890d0961e3d857bd9b2c5b44536d8606f62f66d14ddd43b0e5d3379cf66d664616df12b1c62385a57f6a562c34e120b79d64ca39d8b23e1e07b2c03910d711f09df5b54cb0e133dd751bea7832fdb38de2f1dafae69fbdf82b6887ff0a92940299020a835b958bb01b25b8699a0846614cb256a6621ef92e4a0947df9141ed4f91eca527aef25862158a8fa712dd60dda947f6a16e077810e29542a56f9244c34a73454b9ad0d8e8c40bd503efe12c4e5bf7d0ff8e6ab642a039f4e8b575d33c0c3de77a1abfa60b0252d7a549dd791d9630c8b848988157608448d77938bfb27beaea8f9b4a259263797c5b2fbdc7f469b2769f7dcb7b9478cdf5f109322eb2f0a83163469b72d8121fe8e01df227563cbd941a1f63961e2a010c6322a812a014279583a0066492a17d1a15c07024f6b8b1561041b3db608ec1c7475ce4d086e60523e85d7a955841558a35535d6e52cb166669a69049646b94d2fdb901ffbb1446a2d7f58696bce000ccbbb6942b0ad6480d006602c228218d3a2f0bc6a5d5c73acda9fc4b0b496a7d527050f8d77b71641f030368e9494bfe8e9dbf6dd4040426da1b0423739b40450273f4a8d551637e5fe3ca8d54fc476e6278e75cebf4a4ac3ac8ef3807041c4b274568797c8caaffae7df08c6c158d92411db981ea02cc212064c3ad6a9cd1cc02087acce5ceb8d7cddaec429d199c3d90670288be6e88e6826d1f6c417df5f35139c71a62c0267adfce7cb3aa49e827165b28c8cc157a691cb52ef103d8d7ca0ebfc628904d0b2d365dd3401b620d6d93cef670e2fb90cec33fc1486a0e70aeb6fef62ce5a0dfb51fcec12164e4024b0c49ce8b65e01356d80a9571af8f69a9c7256ed549d699a31ceff21c13c482ee0c5759f96125b0099495feacf22a001b2c887b107a9ca9e84de461fbc6e143566de56c710156de5b5f4b7ffe29c0124c1fbb6a792110284c9ad713d89bbb5ed444d09408c65a9f74c5f6c4fd281d31738db82913dcd1ac1fccbba24dc933fb9a8e6c4e426fb98590d7da0252c34d866c114526ded1c9d96daea12ecbd8f2a44531dfb72f02c02b267edf0560b1fb06b087bb6ce02b2922d92f81bb7da99b90e4a2dd68aa858759584490be602369dd606a510b6228e3b941421a3006a697b79866cae011d8aa496de4f3bfffdc0a087d01323db849f6237d7ac476d18bb417f26a697388b4c0a78533f3dd763398719c9ee5bf0299786fb8c4143af8c1195103390d4494b735c06b5815c454dba2fcdd27d214c48712609ffe7ad7c082e835d7477de2358fb3c4b5162027f816ca85aa4a46c25105175e77c8e5394db6fb3999c25ce578f066329182b28fd5b68769cb07ebc67e47a537f6cb62bfd18af162113a4df7f8908e0ce953b6a9637c850f24de0fda239c25fe4352f3b381fc270384d51d1af1ef0dea8501f98ea71f26de97e98799c4b2a316a216bd4af4861ad83fa4570532029564581bb35ac543355ba3aa246b59c6a5d9a91b938f3c4f0ad6d6f567fffdb6fb78402ded5fdc544a0f5fd87e4677326ca003dffdba8fd390487a6469991506a18f376b12db5be3bdcf4a4bc2f5b34dd8f7066bec3b40a6502f414eac3cd1ed43431b033757e86cca57691b0e1f7eec68fad9423f8b0620aa94798546bc878cf29d74ae74af5244ed9b97107fb83abe25dc160ec05cda1c50b76db981aca781868a7913a3e7c98aa5a3ea8bc81270e6f565138dba33c9c7e887641fd3dafd458b9c64600151038db05725a976950307c662c2eb668e3067f943b9bfd805307729b39ed77309fd5e67ecfc56cc231057a6628fb6f528fb969378529dea2c58fa0b4d791ca591ced733e8cf93a8e19907538f45c2618612648d3e1a78492afc154b7bb0285aea97d618e74a74530b492c66c6bd31557cdc55476b3f163196ec8e87f110834ffb8c232dc77cbf2f7b490f520b3b328af44fecca860a19bee9af6a5f69f63487d7dc6b7bf1233c4735522fedd475f905f044a0a7f658a7a378958cca56a163a343a010f4b65d1bc38cd57d08e0f887293fbc106ad7b15aacca6d51558cb8478b119acde04a19b007802a8e9578121304622aee7858d1794ade88973d6fdf981ebabc98fc417d765c075bf8f76b9781dff7c60071878027c057aade8eaf820186035499e9e5fbf8791e6fc0a0e49047af312a8b1b1e80628dc4db4f45842e19096a54733d28028203aa668bd8655631a01c000c956c32ff10572fdbc95b2f26d09fca84c093ddaa122ad93598c03de9273873ece5096648a6251a27e993ec7b6ea4f2181c09bb06852799323f3e993a4b7461439f702cb9df183fcaab11b8bd2ad391924d5e6ef261fea01c91cdc10d9345c290dfc3c040318d11419563d407c8365fef3dd31d8f9d7d338f5f2cd00433d1d06547ae9c650d14d9a7e5b683f0458e7a909d90d4a57201ca5b8753c13bda3591f9cadffd0987d1c7fca1c5a0cec1e13c612d0390d7c0e2f422c97cda29959cd7b714fbeaa5da7b0bcf911c2744a9a25c7d49e93342f61e10a33fda80fadfed2668bfab8767ce80480093b4845cd5ec83082e8f9ad63236743e72842d1a3226640a549c2c1d002a176e2427b2ae612dc272e3d9fa80a904eb8f93f494a52706346c08b06c9d1d8a61a9c7112c0933910882f0da6eea3c389f4faeea51c03394eab4cc02056d704b8839afd76f0839be5ffdc873b88f9a755be6f0229b0843839a25d63c18da89be1c5da930a101913ffba01fd00f2a447d5f58ae8f21554feb47f42d40c32158219dbbb1e5e96ab3dc26cd6a435525c265b65b0bf48d68e9b3c9178a509833aa47c23e63aa9a6f74bef1e4ef863556b11c014b85ac7c157f1e64531b676eb28c68e82e0089d2bd798213c836cc354d4883dc0b607456ab7f894f0a1f73356fc05a5c97a9cf3b231890c39105b751f6fc54063a08f3d3a264ab90cb7de1d0e2f6acb92302cc9b4bb512e720e6ff8343004028ad223a70d395c5f974d3ddd380f798e80edb4b13555c3be0cb1a500e19a8b1b05f9cae85d7eed756ebcfa57828f1054296ffa48d426ceb83c69ebe1b983421f42316ca6f50bf8df0f4d4aeef85005638a304d88764ec26366a1437867c89800aee55ba428e0c07542e123d748c795560153007f768b20bb057fc2643b7db992c3b9cbfd88657b17fbe8a783da2050affb518cab4226cdf28fa97f48651bd142932835f061f8642e79d1f7ae8ff8665aa85aba24a850b2042dd37e61e665a451f17cbe9d57ed5ecb1dce9ec34c576762929dbf46964de7c44c9f6b10fcf52b48649ded2d491bbe4bb6ad578cd31cbdea6df8342dbb7f33857617250b014fc6d887a448f7a5cef25ff69dbc94733bfac1d5f8593af7fbe4759d23ba8da1f405ba179c96d8ae49eb760446d842f0d61ab08508a3e31e4953e13a1b197d00644303e8a9513199583709f41757740a0dff347c3859d3a4ec391481af349019f75ccfdba111a4c338fd8283733115ce7c114111abb157c1a5a84f7b39779a54f000827a250bff00dbe9cb7162d81f6c942b719f9eb973ac7d4652b911622396c517c6e9c7e5f839c049855567fb53ae84579388e3c87af420272558c686209fd92fc339a553f873995932d9dce52f5e60cc0889c3283f94a0d2d5d011154d9935e1dfbb7e747b393bdd8a84f601adca56d4ac5e8e6f28100a7d5522de50dbf1bd7f5604fdfa660a58dc681b4b230abbc4f594a972a73456de1b7f48975cd03313a80074f5d6701db61860f33dfcc9f06e313e8881c385a50de28ced014daf702f01c45368419b73383008b9191293f59fa87a1ceb0cee64d486842ed7c289dca3b3f2e261df644de0f739079ba5ea195468f0693a995dae8e0f7e4611196824f329fc803bc3588d7d941d1fe86a3ecdb3eb8f6d4066ecee371f9a14e5bd46a40b53e87325bab7255099b4fe7f7b09eddaefc6582feecb8dec02b5e58d735a927d052e263027fa879fceb852b9e08db4636c7152f272a43ae4037c50210e90caa3e008fbfa98ed42cd425259096fc06644edab9b768779dcd892747f18a9cecc6aa31dc27d3f12a540447653edd5bed68f50da71b7992434b74d0209746f93ea429691fcb99da0ca32df822ec4332f7eb4bbe6d2111ac84a55932b3e173e388ab96a5a8a17c7d8b8131cf566e0335b0c4a37c5ae24e73c81146031295b69ce3032fa8e4c7616558179cc561f14864190d458cb82370749d595966047de698256126a4ca23a6bbd39201b8649fbcd387474ecf5b9f732e65938fe393a2a1269b06b9b49c5d8882d70776fc823da5842d812be2a65d2f5ee0d64f8258e761e6f2d4c1a825963b367d70b9e81b46fc25e4804fe9decf3aa0e47f1eba573a24f0e4f7b8cf8a886c7ef4175bd317709feeabe46df9719e7d7a4bc2c1bbc15a58b5332ea558e160f5d3b7aa84fe54ea7a24bd8e394ab794e72db7946780272556be33b7f32a0ee651c013d8ed3b5d75bc1c4826dc94f9e3711c53be3bcdf361329544f2993a189b6431a6dda8b81cb1b7c3a69ba96c1ac84a55100c4985cc85ce272e8eb5a57c563a7ad782664d561c3400e779317122d425c9c4193414bebd4d6ad31ba916448f65e9a7ca1f856dacf9d88b695410c8491a759d2c0304e8368b39cf502d0abf7233b1ba9671bc422ce182833ead52597481ea3ea26a2cc35e12a8c83bbb263202d5e9e7a5bb8ab2a5a844d596c24fdac423981fc4dc4291944ae476d59c9a31a05f79f0fe4b39f145c4fba857fa553a17fb2d5f941d5dac8dd3dd07e48eabfe5b98f3c41e7a84986dc3a7a3bb0ed2d4232cffbc50f167d58fb52fa3b357e76430d7f0f1aff6e2d51ea8f5b98bb66c5b5687821f33b9b6c2e407ad0e8140c4d5d4f1739167f8d63284caf4a43688473cd97bab401218fbb2ea13be81bbc05a81042a02eb1843bd46ca535e778e207c79ce3fe511a55d21bf20b24bcdfb43fa62b3469fae2ebd61e362d5d663fb2c08cbde5df9d8cc1faaf6370b5328ffccde873849299d61477a9fcf7c5c96fbc51b24c0f2cc6e39a46f4a9c1f5214f2cd06db62a37e2c6f477ceac0b92eb882d7bcd1fc3721a89745473eb45eee9a4fe6ab323d28f4db957d0c5dc1ed25ebc194f744a2cfe98474868e6acf5641ad454b3626ac2a27a9db416eb1763935eaa5612e43c49e8959ebcf5133863e98c19618e936f33952699fc224f41a4e259b40228047ed6a17cf4f3a42dc76df1346acb0986984f1692b5ed28f0825a23094ddbb8c1750e9035b1df2166f142e7f179473098ed73acb9ffb8be530542f31de88d6677f805cc30ccc0b60787e61f9d195ceacf07a35d979f9c3521f23671f378a6cd58ed2b0620ff7e2def5025f878d70008744c6a53caf325293353747c94c5ddf12e3a42686f97adc4db62b5e2e91132345963b7292fc9d13b484f75d8da000000000000000000000000000000000a13171d21" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-3.json b/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-3.json new file mode 100755 index 000000000..25f29d47e --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/short-signature-ml-dsa-3.json @@ -0,0 +1,6 @@ +{ + "id": "short-signature-ml-dsa-3", + "expect": "INVALID (length)", + "alg": 3, + "raw": "0x50f91c63826d6180843b9aca00847735940083045f289400000000000000000000000000000000000000010180c003b90a20fd3c43f5fc7807747a73e1d8e78cd9e611ad6bbba9b264534594174b49082aeab827927b335526cc50c2f0368fc666efb79c34af8ee90427d1718736acaad47f5959b9b26457619c07c2dda553d55a7498e30a37c92909f6b37c246dca4e8fd24d4cccd811396d276e5d11f1e8d14bb9eb4d5ec49798202422edd57ea4d8c0e8c6388e9c93a0ff2e52f7ca2303e40300c50c926a7da22919be462e2dcbdb3ec235b14290a282ee76a04f4bf7c5e2ec5c8fc0aaac72ce4f8fcf0d42b9fc3c4049ab6dfdfa12623d89c0d96434a8e13cb6f79ad6f4a8102f9a0bfe582d967372d8928ff9d7d7393b22ec1386ee91dd196eb9c349a6a12f7504e66a096eec0a8ae98e62275f6b84fb40a81a390c6ef0102c8fd2c11d303745b8fc49e638e6f3004961724a977a18d81efc67e37d0d44558e28cf9015dfa08eff82004c4a53dfa40c2451fa03a987f70c855dbee37e36480863044165e6d46d4c43278091317beab6f301d61c8f54f94ee88fa358c9aed6e55b80b4196e79a3d7251ede25c4baef8129882a69789df3a8262941199ded7bd381de00c257199c18e9086d9ce3f72c6d95c0a4d109a3a15474805f0dc06649a16a7805e8d74bd1af7658f5f9ef726d560595ff9f072d4cfaaf61283087843b904b0f5670ca551079c759d4a2839a71505e007cb5d49b0437b87a080fab5e2efdedd1d01f0f1ab72f0e6129a2525fc6e9829b56ce9d9f287a5bd80be8b1556e4ca82eafc60ec22315448768a72e45d4d956c16ee48a0658e307f81ee0f695f1b1b747d1d533d8da720f088b64608b1edb2d4d27247b2cd35e3d94e1256a3c5c944bbafe07b55ca74df4ec0b869733ddb466717a16e98af4ec310d046c90046c024fb33fbb2ffbb105d41bdd0e0af27b1239aa4d92b6ef8d727e51372fefc3b5c8bc6eb585a0ae2dd9970009555c2c2ced5e5a1e97c659565b6139dc4f3bae788e21f9658affa8fdb6f4733f7fa83fefab91a030f8ec976b8263c17abcef46dc22456d5347eea7c30dd25bdc3caad7cb2010f06573d56b6e5d28e6e847d8df8f18d6a2655ea66fe3c8e7e4ef192b5a8aeb35f8469277657b77155142c7b1653d5eb9cf9c4d69bbc5746e0c1876e330f9016a2f5343ec60b2f35ea380169a2bdf102888e6aae7e797d0bce73834f418018e8e55492da8236a542a999d9eea55bd52ee2e59feb0329d716c78c0bfcd79dc27cd9639399d2fd99d2fc9c4900ad60bdb8221501038ec4baadd2ac4830b2bfe1e20804c818c8e089661e7d842bc4e566fa0bc2d7968a44f8df0d4e88e494fc7bebdb695d3a8edf6a2703817b0f8c1a55569ac4a8ff0931137f075797e9744135a3fec6c767af26d4592a9022271a4052b1f1f24f072bd5ceb1d19e02b0bbf31251a7bb8b723bd3da02f59ca1c0c91bc10896970a1e0f8e0fd5b755da58d70be8935f65661629a9f833b35810113ce80125f8ed7a031cfd5eb1475b597856b4ce7629a9429d840a3457bbd70c05c73c6ce84dd59f917a24d06ca8743225ab8c266e209fbadf57cdb587df96eedf54c04fb3f83ec0dddd1d8bf9051c6de4db3aa099f1779f3f30f61f432e5c8f6b7ac4ee6c6dd6fce667556df155ddb2002735fb7addd8acf74863ccfe04a3088317634eb47e56b18c79f31318ac5e448a9094b5c2c70b44dbbbff7c235cef4701d504723b032726d009c6d7f527e645a23fc1ab478e6e2699211694d575bd436d778e7ae53868c63dfb78f591d82b979585cec8bbcde61f375e783e97e8f787fb392fa4f0bc3e9010aa9ec3cf6471bb16355c3ed3fdf2ee5b95ade86371d60fb0699a851770a212d0e0eeb3f20df78ab180343fd79a9d04d8dc56d9fe3d820b27d98d12275a40d270f4181aa1a18305c8d3469a954b2e85405a394684cc234702a6cb01c04ccc941a4392cf64ba31bea700d339152fce6abb0dbe84823b8d3b18258a29414fd52c91ccbc198e101287b79d8bd0e5f4b05a14a07055e66ea37d781934840a204638bffda400113bb1344126fe1c2ac1e57bb861c3d35349b1fba0c11e12921262ae52fb2e0bee444f8197e2817b9356e10af67e794a7967055936bfcb51f4be6fc5602a8df97ddcd73afe83c02f00d4f1d8302bd2e826d4c50fd3ded9a74debd0e807b694e912a8a3a800f5b983e171898874b77ea305ede4abdf0db5ca84a8a60b184374c08066537b08d42a609b97039ff8905bccc4454188b051c5d1e574e1e8b74cc5cbded064a5374c55f17002ee9b17447fdc324a12e3f2f414b491cccf20c9f98820461f4c7d61355a30f1a6cbb2fe7403b90587298fcc9500519451e44225c750b8b32a649ea288eda389e596390a5386652dea5d0e096ee270bcab9da0c3c4ba464f44172732a748e339cbfc8f0c1ee3187225e2fb29e67ffbd84df8acf759c817d628e03a245e9ae0cf00939fa12964e8dc124659eea8798b097ba52480532fa11194e4623ff63f6cc1d17c7080bb2c1459fe8cc9b197b89ba91986b7bfa61e514bf5c60f981e63baffd9fce44af87ad73fba197e46790fc03f8a46aa6d7590f47e08daedd7f564685208ee87da84b04b11cdc0c020bb26b0abdad3c1340649130e26af9c7651533313301e8b517a84c807d86a4c0cff68566d34da4111d67bdc77ef5f49ec7d83af24a143bceaee020acce02499c725ebc341a86d91c7f63dd962ffcc09fc0b5673873ee55cea4bba69b5058e4b364fb3802832d5118774790dd12eed78330412dc877cc034309a7e292ebee955a431fd46faf7884cf3bd5ab03d02b8784af2a84bb907ba5f021fc332f638a2d4b6451ea0a2cdee6ff1621d698eadfc99d6f405003f300e321a9e80ed3b577a899fa7dd891b53cab8acaa9fd3ce02640eaa75646f134c190817675b9e4a688d0668528fa3b378749bb6b1a0bd16873e89dfc927dcf568fc3cf94ac49d289ba1fb9c58a74574c8fbac321db256bf919e9432d6a8ae9a0dae900901f436b13d0c2b753a5eb6fcef03301d7faa15ff32ec0730335b13394bff66ea83a7043f9e1df5962671ff2d2759db234a4a4fa47fd3a9359bb14ef5b5fc398836d42afcc5d5f252b1b061afc6a0815b3a7586d25eed5ee52c56d2389b8f2438649ee652b431d3cc4262c6e5ea1c0ccec21aa6123e88b4bc933098576bd78cf5bcbbc278ee682029e05e91aac2043ad3ec1d3d97f6ebc6bd5faffa5bc71328cd4351bcb9a0d8d1ea9253b97b08c8c53b20e29703568d5d7dfa2bfa6aeb3a93043e4123116a125311695a11c8538658210971d7763ed7870c1309893909e306df22fe968612531e58a91d19dfe2c658ade19c8e0900c779af8ec333d19552e42cdedbe13ff85d99b10baf8daf70951290db56bc7ea049e6b468b6546a7f3ae77c2e14770eed1ea345f0d139336af4eee686ac2e73bd4262cb802e0173fb872a77cd2c0f3421c497b0260be79ae29d04d9a9da9d7bc101ae3ec9dace1133332f05b7b82aaee577c06c0d2a8eaa8a96db8b899cb3240cc4dca4f8eab513ad5b3529063b5df3664dde0db1e0ae5c29e69f011076fc7edc4261d043f38f1c68645466c9a5e685a07393b7e2f8f74db86742ba5ac089b45a42df3f943842747674c1653aa2a8ef282f64e7ec2ce1fada994288a5f9b95da4bc083ea008308b91212c74a08868ea0fdad9fbb1b485b793bce6e4fa945668b2351232a7c8a084fb2d87a5c83e7dced6bde3743617a7c4babcbf9381694b64d7e0feeb6615440e927a63293c6b695900b1e7afad1ae612c324a88e6761c3b6fdc41d18f514be1ba3a1ca53fdbcf8c19f95bcd60223abe52d07fd7c4114dad9f347cf122f6241429da7e598959c22692910323a0a699595398f518c58deea7159920d89e3e65702bc2cabea7e9ca0bbb7002fb7be5243bba6a08a12238ead443ff4394510d25eb279885d9112c44529f294c5a2bf493a74ba8f4e38744e632680b3ce055a897d2a5468ef52e6e70dc5af55a9fb83739f6cfc6994871662b8263f2e07e21a6514624909369e0138755165dd2af5a791da63c0604b68ff160fad82a578a06e76f62bb7e951b81d8fde2dade6c3a314eec5913151c16a93a5abd5ceb59ad96197a349721ab123b42f799dbde36d7965e0e5dfcf43d8d1ae13f4a00afd8dde36137d3de87f4e2c0366c18f4b3a449ffd9afc7c742c50456f6e642f7d09e86d5aef224b20ce5d8a2bf164484df8fc87daf69e459fc78c6b974cdb8fb1dccbd5290f560e3114302886e2828ad73ce71b06186254206743076c6af0c3d1facc36695dc28db1d026686b141247e1c7a9323d544b0079023cd2adedc0479ceefc8e0c34782603d0c27d18768eb5485a85bc385ffdfd25f735688a3b9a0c6f532b2a7989c751804de0163582293a17f635fdde14e9067f12929b079f89a53dfc87b986f89f718320ede83cf4086d0d095b24b66d5e3f1bfdb08b79cd5b25657cf2b20faff1d199c16bb7f631b33970b34c12997637447e4127db1bf580b339807637a86e0248cbcf8e1d30ae6fe053e2f9b7b3d0f9e3f4813af908b633560779012f9e06af00e252bb0df9f0caf7d1e82f8deb2ede21d13f406dd9ea69445d50844c95c921d8d1cbc8afbc5ddcd4157e65cbfbbafe2670e9146a5643db049a8d696f0eae07c3d4099447ef78bdb90fc05d7cc97bf9b9dee8719464ec6b9e6de866f73914a80396dea3900a9f7b43a47e648e20a9504da92c47ac65368813e5453e82020f8861aba2534346e6137e71adb28a5ff080365d6ea26dfc30ef5500d0760749d6e4e0f93aaebed544832308b19f72e92ebb8eaec2492c6ea7972fd359a8b67a1f4053bfb1a3c6fb720b5925a7a827e59b3bd0651b8014c77b25d61db17eb169cc2fa2442c82f68fb42200c59baa468a9fc92f13273ff071124f8b31e2b4b2517ee622d29489997ecb5676fb52e3002371c01004c214757b1f510091c2377a08d058209d18feb9b524a41712b6df4b92f2b14c583d3196749f367b3bbc8ab5e9e2615c511f23ba5fb1bac2ee9436dd8d162bd96f1fb663d2b520ba7e8ddfc2a4d549b63714654cfbb37ee1dca5f723139187ada8f8d5b42ad09ff196b70720d2527b4466d44f33cce486ef2e86311c75ead31a17b16989dc63bacf0d465379d9138df7ea2ebc71f4cc3b6662e24895050e2553dbc160a567d6722964a904d43bf2684206cee3562256e98addf3038e968cf6c09c921e2c89c9c249f6ba7afd20dd27587b4143f704f2738315a91c2d40c467111b4f3bae4f77bae402145e742ba83a527aeffca13ee2290988df882feaf5a3c24b416d59e06cf4f8832a016ce55419b7bd2028545557528a0af23f17942433e13fad089fdb79449bd9d99b0324b1828791249b6789a09cdfb6ec40c0fbaf8b28ea4f72d3df5159bea7a7965b94beb1bb01d87d76ae7ce47fc333fc152038ab4e7ca64a802f96f2e92bcc53ad9cae0242c622c99b2daf005e554cd6ba127991d84841ffe3ba0674eb7930509045dd00ab91a7c6acd2f4a40e7ffc9959929851e40d417f488a29f7bb5af3847a8caa5daa0682aea870ac8b866ccfdc435971e3d862c2f651cc6eb8a33fca313a56ab8228ee9ac7dce14ea3c3fba4f58c70888ae558d8cd632a2723ba54a3d538f4e20936a2ee543e9b2141e06095c72d4ee19908febf7c248c03a78655420da644746e2d508c31ceb0b648800d95dceec72f7576502046e5dce54b5a097f625001bfc92d6e4633b293cdfa63b1fca5de9e26d03ba2f1cf3647dbdad5359ed76bf702f0621c057dea3617af678016aa13360ebb02c6cb2fa0d3f137a1a3c639c989e12383841ab7ca5a84f84c08af4b85416ce7ec3ed91636a79add207bedf9dfb2ff626387f20cb3315502b2b06f361cbf6a51fb507598af41c5a5b9cd95ba1894ca372c5e1851e62a0d3d78dab6f92bd43ba6fcd71230b6cfd843d89268872b75e3c5b471db530b7ab5451dbe63fa0bdaa7d74907cb376643e129febbe6ce10b5dffbf323dc973f097d2081e06aad65e674c5a41bb81b80556fd78691fe6b5bfad47fd1b64db577f27f22f17973cbff3a7c4aa43569bbe6843d773a2f933f472650e88e0ec6643f87dfd37e7fba915c7386a130b8d4f0ff4d0e99a633d1f863f3e8ce4e1ac5e31438d89c3b6d5ace3aa6e14e7073164ea01e853958bece389316023127f9916297a47c5d6ab5513bab874c1ae3bf2850cfab9018cbf50a7febe03ff3e8e4e55ae5632812b6a147edf051b461bfe56f01a6ab571e0553e37a57a3a9811f4fda2e189d79b74215d6fe199595d18c6543c747572f8cdc61a53ce09d9ca96b43a5af5b56b53148dd4fdfc1e22c9958caa783f2d112d8d5fd39e6955df75d35c59a1967fc0d8d3293e39a6cdf82d6846b39a74b1a538372c266b3f12d7ccf464ff7e32fe54342994f51d344302b3b2e11eed2187a741eec99ef0a79a19a854c03d8bd3fcd557b9d8bfb35f0976da327fc7e8d95fb43db8e66be5b373385fc1b68099566c7e88aefe92c7c521d084c15c8d403d87bbc975e8d687e2a51e5ce53191e3db5bdc50f475853cda7cc5a7365c41035aecb61444c2a48492a600b58300b2805be97b4e9e30526e9e62bb3248a17c3809219307ca85351495c943a865359c783cf615a809c739cce0786c6045d9c8071797001434cbae571d42cef415e28ed6adab09ed10e0713dc1412ed80b8d26d549964321559137483c81b19203080b36abcd68e841f4c78b5302da79fd6e555f390322ae67e54c55749491889d79eb2982fc4428086bd1060c4113137ddb4dd7c9b690b802e805999d4f5127f66f6b1d397dc3509504e2196513b5787407b45b928cfc3c437523daa4f876dfe061e351cb3bad99ea205ab276c4f2a5ccee1027104f09adaf55cd282d4e9e44ac2b65f7e423da1cebb0ac70691347e7a7bd0de8bc9fb2e7a08afc0075a0e85902316cd6ec9a5802c51a6d65bf3251ae712ae0f66de6cba1e51efbad53ad7e769f851799caf5fb81ef35b4da814915dcfa67553f1c67158154707d16804be27af2115559e4758b313b9da4a1131718b29a75970b3f0a5e2f2c11a0a1ed47f238c145dc4fe9e8e963d8395c67dfa94a232b8133a0d953b05455f79e0bdff0bc3de9c04d93d97084ab99229622cfe3958ac5fda6757de1696b575f6250b441e6368386751b1d2f6007d254d152fe76578fbbe164af49cda805b9325f7ea47f5e18f3de1ce38006ae1bf027d3e354d6f923d8bc6286aaf9b9a7b9e7a7fbd36a31db0d88166dc68e7eb567d8164bed1e279a8810fc21656621ff7cb42a21ee04e6086924bb62dddd16c3343db69250f7ed95aba953202640bef18dfb6c00f1ee03c670a5cc6c0f3cd7cb006590dddffa6f19d450860e289f85edb4fb0dbbd2f992eebba09cddc1b20a3c98d8739ad1875a514b09b1f23cf406c4c55cc4266e0b8b283fa445849316c30bd19254e9d035756d2773cab7f5fd56d6d3a094a717ccca43251201cfddf80ba1aa0dad34f5a3acf8476b784fd53a1aff1307a7838705112650bd25dfea21b991d801f018a5dae26edb9dd5a0ab940a94b7bbb90fd1f30f9d1dd2ea3aad6d0a2a3c42fd2641233c7d624314c3a54ce616d2ca5683d04f6fc0924f0b667be32f4de8820f9cfab963a287a1c708857ebabed9b5bcc35d539ef9bc170636cd528ba86a620195134cacbc2b8e742376124b67ed8155ab53979e281f97b184c60355b008f15f45c8b7a506b1c1f511e4aaf0bc32fee27b656b01ed6afaa4053ed674a60175b6c89a77d42963111d0940730db02ff67534fe6a296e0e01e2db6b3f0fe9648286a0f3420cd4393163662751deed6457abbb370f83ed92e9da86a0181df13b8ef33e5718ce524a700ba5f2b40f3f973a67c1c412dc251c19e6b7ceb279dc1dfc36a3567e3a98a9d96ef52b0d0734f57bd9edebedd925167f230b1c81ca938e94ceebe43d2573735873a436331a8b76c1169c6a869889cb74e5d33721bbb99ec87f160c025f570f1d11c2e3ae6a52580785d854790139510179b003418dbcee1f4fd4fa39fc134521ffd7f29cee650472638dd04d8331ee439eaa32c57b56c4fd9c9ba87516a8236dc99b8d6e4c2a48e53a6779d5e13bbd73cc7917f0cfb8e231218bf33bc3c213599eb76476558f0e38a3979cdaad6ac6b03bd0ef0aefec634fbe0e1e87bd78123a19b7352326b9def856ecfc02b06622f94e8cb2a1cb6cf10d020f789a7db775063030f15b463f08878219636f2bb94ed11a3ed9689d797a3253809c7f2e0c60672e8476a9e272075c7f808258901e611c4d535a11bfe01daccaec3a26a187ab45a9fd0bb9a7ecf2e9c4aa3177ddaca1449f19f78ebe26be2e25bca012a10649b56899339f5418925648f3253bd716336dcf65e6b4f16d2ae51fed1acbc8335c103f721f46023cc2043f568ddb033aa5f2157e52b89eed4571cb523fcc66ef5cddc90679633c2a46f45f1a86c975db4f6f37f9fcfe54809ccf75305bc9f242f26f30a0ad5f3cd71cbd31ac45ceed2dc8571142a09b7d3091a4838727b9a067927e17b7559076649b405dfd480627881489d52339d4a8943ca396e92b92066e45d525acf7785a944345d25d721d6a354b1a9f3e2afd379d1c341badd0dd913a3471a5b78a81c0b338a2984e115d003b1deec1b44fd19824279d742017248fb4434cf47ad07fc87df86e634b2d8f6e0aa572088678b9a9f767404f06c84ea8cbf65d46effbde7de1f090d3d4b9e7c7c3b2b1dfa9e591efe12ffe0fc82c9eeb7fcd9f25fe438b39c46614438d0be7e1dad11bce8b91396f867531e8c45d8c01119abc2b20be253779b5e651bd80536854e2aabccddc5f4fbfb3497111fe9a8f8a417ab4dd806745c82126524ec325c931ac1f31a3cea19e159e1dbfbfcff761cccabefad38062872fe8a45a14781ba12551befb31c21150a56ccacf9815d8f458b1f591c71ba7b0459e7c09a4eac5c9e5b2984314ecd2f7054ed055ba082204f7ed62b1d513cd0992bc10c28bc745e30b27f6ca28ac84dec6cf0ef73c971ce12b2ddcc0d6264d8f7dfbba0a20f8ff1d7387cd9d9872f4b345b409950d66ababa9852f7f5ee634dad6085666956b97e4c9142dbdce96bf42d1334c61d04ffed5ac8f12a5075ac87a7416fd52579a876c89e22008759a93ebc57279215e178662a064bca65670089ec688532468c07161f56bbafbfa5655768123e713c7aff52852978e9d6004ab3a434d9b5c73f0d90dd1fe742a169a84f0e96a189bfc5265d8c5e2d9e42f5503d04ce01f9a912bf8b9bd8c282a4d40bbeca55d14971d1d305a16eb85d02b4edd8d35baea56156ba12f4e344dc4cb34509fc780ee97d24173a75e49960ec32055710bf8119d005447c6c391365737a0cff68d9f44868b97b2357dc051ed7fcf590b32292624545935e87f25e56b3e4a2b9c39c4936b5be9030b4711f246623264e0370291b675e75e1ce9cb425e5fabcfb55e25f084ea8a1b84870135ad997f7b700876691939cf268204669790a10ddd3d38cd22252226a09fddd395482deb561ee834ba452750d5b8e0de63c77c85a7446dd5bb29df2620f98e07bdac4cb59af8b9dc64d427dab780257e252e8d6793fd1b99f7c3162b4233a418526ab227d40b9deadc943d0f108a38d7a6b075465a44c920c0146338504eadf826cae345e864452e94706c8dceac5cca87469f2183a9c918295c09eef65f747b7a3d7fb3d259c4f531ffe48a5c338717ceb45efb557a47a593fac85cfaa4c263c109d385c01a3193a6ad1be5923d6a53e6c369a2b5e704cd6ac3ac255954c3fca1079895c596596873c1309fdcc5f36fe039d06806dd16cb00bd028edd6b44fb1e9ce4a020362824bef6a59502cce4e1d3d3884d7d865823deb092916a215ee73bdae1d4baf7f294caac7f63a36c2a15a40517438b8cecb93a5da3e11c25ff228ef3e7281360a2ce3ac66e69a2f136a83fbdbc44dd1737e9a31bdce16df9e118345ec1d9a9c47bfa60502722c9813d31c9f1b0364e2e25d77a0816db52f7e86bade9aff644df50b1cea9a339e76e869fa1fa50101f8182a2a6aee2e90d242d4b4d6b999d1c358a8d9297b6e0e2ec141c2b3692d70b141a213d477e87c52a2c87a5c6d1f0fb091f35f50915878ac70000000000000000000000000000000009111b212a3236" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/unknown-alg-0x10.json b/ethereum/core/src/test/resources/aere/pqtx/unknown-alg-0x10.json new file mode 100755 index 000000000..397c978c2 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/unknown-alg-0x10.json @@ -0,0 +1,6 @@ +{ + "id": "unknown-alg-0x10", + "expect": "INVALID (unknown alg_id)", + "alg": 16, + "raw": "0x50f90ec5826d6180843b9aca0084773594008302d5709400000000000000000000000000000000000000010180c010b90520caf597b4848d085dd620001a7707a9e0c120226d4551a49d4b6e0cbf82ad3dd96f26ac5e395a26aa1f3b569e89fc4914cec8fb3acd07350d1b8e0f6b66f7ac3e4f07395d148f5ba65789908df3cced072e5a56934264354556f4655afb86d9e892fa9926e44f74a340ec5a92bff6211740ecb879366826987e5556a513d8c2f585eb5ad5baffe6cf50aed2b96bb1f963bb124f2cc3b95ba6ec5c4f272e7e457bb1c6547e284ffd1c7b149b877c1a9856a3303f9aa5c4005c376767af6d7f00097e97d7a5bee0c196a12293ff2cef34a09f0f594fc12a2e40a4d7652fa8db49c02d76fb76320e29a0d6b15e97a65147429fdc70e4838ba9f60e0318132aebca93b564960caeef51770e45d8a6ea2171f9e9482441610de9fc8c56d80e952fe7c2ef0dfccdc0a337bcceebc20a8a2df53b4f61f289ebdfa2f134437e21fddcfa394bcd16562e41d1715724afb398f8312eacb3ad606fbafc00954407f83cdeee3bb5a3c565f50f9d54ebc8215817deae80e42c66dd0960ba23c3b1e99d710da8e1efecc89c76f769bb5e40b9ac5ae998216c3eef8f039fee88e43dbfd056be1c43145690c1c9d3775446c80d93214a89ff60892b4ad7c55bf56926b834cd21a3e09de040e2ad9b6499c0840957b6661ab1f149cf79ebee095b8c481e0feb761164b4fa5360e79987a0dd601a60de09ace752b5ab69fd73ff111e1410957ec95bedb2a9dcf307037463248e4b4d8c0fd1b455969145d2a77ccec9e101f5e9142e4f1629e19662269a9f422cd64f1ddc6d7bcaa30c949a7c67bd6e14fbf8dd7244ba465875df788b1d932631d6b749c37bccb00b04efb9a5c8d05dc73564bbeafe507c7e36eecd957c2054696602ec27892c88953fb9a5019899bc3ce475c4a2931ac49a4bc206b27b40ce3021096729ee2482bea5001985bb22a0f62dc36cbb38b8fad11d6a7c055312e69f8966a59b5c9b6237d7a8e59f43d94bfd5dd8e1589f3143ed4252f6fecf4bd40ee30b1382256fcd3218d4864dd281cf99d83c1ed4a766b26698a914f044d45405db8d7745b3d7aebac37e668c6e8c5ca09a0e4ec2190300c19990d96742ce7f539e05b8bfaacd2d3bbfc07faefe22d5e8795fc8a6e8cbaec0ed1489ce625ce9727ff52660025002ea692dfb39935ed30280363cd818a324d9bc782b46ff730e2e5955640bcbcbd285d2f2fa773154d3fef5bf13cfe81b857bbb576506ed5dafe4477e487171ee64c9e37d49df5ca7529dae30916b72965a391f4d3437303f7cce8c45dc187febd2a949fa7278f7f8775dd2bdd66b794945b0e96a0b58b6cd934deff1f4ccf156e8942c7533c8a45314ef5e3210fd5a3f063982211a122f9a3f1f99c253c37d981f223dccdda18a34bf3bfdf9e02ff607ab7c92ec4388dbb7fa210c7106bf570d60e5321ac1e1ed5fe32b4053759bdc3b87b1fb7920371b6c206d6f4f871d1667b41bb8e661f48144a312e3d7e0d372322d0a3dd8641574419c49f2ca4228328a089e97e86c4294b9b60af0998495379248325299e3846741ebaaa69994ce536201665cf6cd23de4958fff41f0601722df54d2111d845806c013b336d73c8461f9bf5a16eb05b08140c1a2291f78747c74cc2568e956f307e97b01bb3a67eb9cd51be8fd7ee8cbcdcc5b2b2c27950f5ff0f7e8330fc2f95e3a4ae49fb7512a6106c5cbbe4a5fda693dea445fc7e792676b5fded44d7da271c63e76e310ae988ff6885685868fa72e57e38d1b3c80318dbd5e075b29db1e038c56dabf7ba39fdf525f08aa69baba0817a0e289d5c12448eb4d07cd397fa39c312ecafeb9a846fd0b20667933c4c34bc5adcca7df159bfd5b909740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-1.json b/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-1.json new file mode 100755 index 000000000..d38c774bb --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-1.json @@ -0,0 +1,28 @@ +{ + "id": "valid-ml-dsa-1", + "expect": "valid", + "alg": 1, + "chainId": 28001, + "publicKey": "0x372c0f4874450fb92ace74d41bc0326c7f739589f9b86a97afa87ef65d5939e608c81a44909e41f41931349f744b7aedff8d5270b91c4a2f61192e2bb6e3e6d12231deab235359e78ccada386becb6a6a1105afc0999243ab8b363f7cd2c19b2b741c9969dcf20252f20d130dc05d9244f58d6de9b4fb4b6f0125c43b60ebe3c7272b6ae7578f1abb4bb5e2dcb31eebf4aa7089aa2bf40a0ba5eb73aaa90e45472168738cb0e866547e079075d0341c4728ed794cd449d0cdeceaf64d09173a2677e3f2621b56014df58ee8de2bbcf8cb2bf369e57a28e40b24df6d0b15d3417b7b7fce3c49230b3bb7c7080c4f1344380db37299d8c0c29a7c9e95bfc4f3ec70b767895be6ad798449f94c92f320696f8f9ec844fc9451f5ab30874e6c78673b932e24a918d5bc03f4fa647c8679631ad8b30ba4f9a1a790a535104f5079f781fa4c4aad807777327e08bd6e14b957e527650d39e2de7d30da7b2b27457d3539c2f99903054bd1a6d6301b2f83249db80dedc911059b047b5552407ed32b79b57ea4968198decf978fed532277fb189841d0c17f261f1a7c4618c33b258a71cb6b2b921c48735c1fbc375a80fe2d702e9f70db34547147f6d65153f1c508ff90aaf57dfde59ce6e56c5c52049b10fbc2640cd937bf5027d755444cd5e84aad66be4ccf04f710f0b970cbe7fc5e4e7a44f5d8fc2af94ec6df87862dabe0d85dd17e43728800d5dc8ff9e9e1fd349b9d6431f264836a447646a1ee2d73e6a4d1803d71b98510d94d53b5d07764400f413b7837f463e273980296ad5e78a62c83fb91354c25c2e28bfa19480ca41b0ca2d8beed456029eabc0ba69cf3504cf1207ab21bed0e3a60795f5b066019132212a9bd20e98b43bb32484454b7693bc63764d0ba8768da4336ad16a979b1d3e8b06e89afc4caafaddead83ad861a4596814062468d8cb2e131e71cf38c4e335bb3d1d9629251fd50a4273999a20e11d9a881fa2465c2ef32301fa8805ccb38b4656e3c815b54ef42f292d05847c0e5149b0a2ffd1719fcad10730b763406e9e453d2e4a556c397a984a7d8622466522e79f715f980279cb2d1d74d5fd15f8beb8df9c0a1fb93f0d5494ab701cd60cf2b613b484a191d873449c4815f44eebb62658ef90f7033a5e48d40c8f4ec9a25d4f1b73a150e5b03a4feec9142362e77d74d364bb8a40f9873efa2d9f458d84277fdb0063642d9ebc794356368a0b4e53f6ab0d9acf4418fa42d05c11db12cb67d6c4cbbfde4d85358abaf8042510db53c1540fcb40045b334bc54a17608e82433d1e9e53c99769b86b69b8cf1914584cdef479061718a2cc5bec5c31272e0463139721c0c3523a6ea31832b5c15aa59819304c217fbc51a2636bfff331e6dc1037e89be15c17d6708762976329353612f312b828e525c09b81afafa5ae5c25d82b70b6e55f892429a93e5eb4048ade675583e828da988f9d253123a06c0ed047adf4d93d20cc6c865f5a761fec27811305165cd4bda05f563215d0612944b88ade9d64477ae8fb441978720e70b0d77e2edafd3a2c571cd28a42cca2f289d157cec813c24e7f56051b4f28c153adfbb2c1ff90ea1fbc03cb89603387169072442f5d3081140e2256ebadcd775d2f1da92c15a9ff1ce6e980b3b1e91a7e379081ed46a4259fada21536af318eb2043ea16cece60b73acd415d239389cad9212e15bad1b1ae38f93c756635a9b87417faa844e4f43bae1f1ae68641a04f0ff1d55f9045cf7e3ed59fde5c07219b9113329356d4300885ee19c9955c5757db33c6ae75b49d035003171d02ccbd7321d6a14db0bd011d4877f04070dbda3b67bf22d083e", + "seed": "0xfa8e8bc1e5b9aa3d7e7c7f7a5975ab8ee22b1f9bc118a3c20ca50f4f0e737aca", + "tx": { + "alg": 1, + "publicKey": "0x372c0f4874450fb92ace74d41bc0326c7f739589f9b86a97afa87ef65d5939e608c81a44909e41f41931349f744b7aedff8d5270b91c4a2f61192e2bb6e3e6d12231deab235359e78ccada386becb6a6a1105afc0999243ab8b363f7cd2c19b2b741c9969dcf20252f20d130dc05d9244f58d6de9b4fb4b6f0125c43b60ebe3c7272b6ae7578f1abb4bb5e2dcb31eebf4aa7089aa2bf40a0ba5eb73aaa90e45472168738cb0e866547e079075d0341c4728ed794cd449d0cdeceaf64d09173a2677e3f2621b56014df58ee8de2bbcf8cb2bf369e57a28e40b24df6d0b15d3417b7b7fce3c49230b3bb7c7080c4f1344380db37299d8c0c29a7c9e95bfc4f3ec70b767895be6ad798449f94c92f320696f8f9ec844fc9451f5ab30874e6c78673b932e24a918d5bc03f4fa647c8679631ad8b30ba4f9a1a790a535104f5079f781fa4c4aad807777327e08bd6e14b957e527650d39e2de7d30da7b2b27457d3539c2f99903054bd1a6d6301b2f83249db80dedc911059b047b5552407ed32b79b57ea4968198decf978fed532277fb189841d0c17f261f1a7c4618c33b258a71cb6b2b921c48735c1fbc375a80fe2d702e9f70db34547147f6d65153f1c508ff90aaf57dfde59ce6e56c5c52049b10fbc2640cd937bf5027d755444cd5e84aad66be4ccf04f710f0b970cbe7fc5e4e7a44f5d8fc2af94ec6df87862dabe0d85dd17e43728800d5dc8ff9e9e1fd349b9d6431f264836a447646a1ee2d73e6a4d1803d71b98510d94d53b5d07764400f413b7837f463e273980296ad5e78a62c83fb91354c25c2e28bfa19480ca41b0ca2d8beed456029eabc0ba69cf3504cf1207ab21bed0e3a60795f5b066019132212a9bd20e98b43bb32484454b7693bc63764d0ba8768da4336ad16a979b1d3e8b06e89afc4caafaddead83ad861a4596814062468d8cb2e131e71cf38c4e335bb3d1d9629251fd50a4273999a20e11d9a881fa2465c2ef32301fa8805ccb38b4656e3c815b54ef42f292d05847c0e5149b0a2ffd1719fcad10730b763406e9e453d2e4a556c397a984a7d8622466522e79f715f980279cb2d1d74d5fd15f8beb8df9c0a1fb93f0d5494ab701cd60cf2b613b484a191d873449c4815f44eebb62658ef90f7033a5e48d40c8f4ec9a25d4f1b73a150e5b03a4feec9142362e77d74d364bb8a40f9873efa2d9f458d84277fdb0063642d9ebc794356368a0b4e53f6ab0d9acf4418fa42d05c11db12cb67d6c4cbbfde4d85358abaf8042510db53c1540fcb40045b334bc54a17608e82433d1e9e53c99769b86b69b8cf1914584cdef479061718a2cc5bec5c31272e0463139721c0c3523a6ea31832b5c15aa59819304c217fbc51a2636bfff331e6dc1037e89be15c17d6708762976329353612f312b828e525c09b81afafa5ae5c25d82b70b6e55f892429a93e5eb4048ade675583e828da988f9d253123a06c0ed047adf4d93d20cc6c865f5a761fec27811305165cd4bda05f563215d0612944b88ade9d64477ae8fb441978720e70b0d77e2edafd3a2c571cd28a42cca2f289d157cec813c24e7f56051b4f28c153adfbb2c1ff90ea1fbc03cb89603387169072442f5d3081140e2256ebadcd775d2f1da92c15a9ff1ce6e980b3b1e91a7e379081ed46a4259fada21536af318eb2043ea16cece60b73acd415d239389cad9212e15bad1b1ae38f93c756635a9b87417faa844e4f43bae1f1ae68641a04f0ff1d55f9045cf7e3ed59fde5c07219b9113329356d4300885ee19c9955c5757db33c6ae75b49d035003171d02ccbd7321d6a14db0bd011d4877f04070dbda3b67bf22d083e", + "chainId": 28001, + "nonce": 0, + "maxPriorityFeePerGas": "1000000000", + "maxFeePerGas": "2000000000", + "to": "0x0000000000000000000000000000000000000001", + "value": "1", + "data": "0x", + "accessList": [] + }, + "algName": "ML-DSA-44", + "sender": "0xa4fe6cb101b79c0531f265f6b2584b37073087a5", + "signingPreimage": "0x50f9054e826d6180843b9aca0084773594008302d5709400000000000000000000000000000000000000010180c001b90520372c0f4874450fb92ace74d41bc0326c7f739589f9b86a97afa87ef65d5939e608c81a44909e41f41931349f744b7aedff8d5270b91c4a2f61192e2bb6e3e6d12231deab235359e78ccada386becb6a6a1105afc0999243ab8b363f7cd2c19b2b741c9969dcf20252f20d130dc05d9244f58d6de9b4fb4b6f0125c43b60ebe3c7272b6ae7578f1abb4bb5e2dcb31eebf4aa7089aa2bf40a0ba5eb73aaa90e45472168738cb0e866547e079075d0341c4728ed794cd449d0cdeceaf64d09173a2677e3f2621b56014df58ee8de2bbcf8cb2bf369e57a28e40b24df6d0b15d3417b7b7fce3c49230b3bb7c7080c4f1344380db37299d8c0c29a7c9e95bfc4f3ec70b767895be6ad798449f94c92f320696f8f9ec844fc9451f5ab30874e6c78673b932e24a918d5bc03f4fa647c8679631ad8b30ba4f9a1a790a535104f5079f781fa4c4aad807777327e08bd6e14b957e527650d39e2de7d30da7b2b27457d3539c2f99903054bd1a6d6301b2f83249db80dedc911059b047b5552407ed32b79b57ea4968198decf978fed532277fb189841d0c17f261f1a7c4618c33b258a71cb6b2b921c48735c1fbc375a80fe2d702e9f70db34547147f6d65153f1c508ff90aaf57dfde59ce6e56c5c52049b10fbc2640cd937bf5027d755444cd5e84aad66be4ccf04f710f0b970cbe7fc5e4e7a44f5d8fc2af94ec6df87862dabe0d85dd17e43728800d5dc8ff9e9e1fd349b9d6431f264836a447646a1ee2d73e6a4d1803d71b98510d94d53b5d07764400f413b7837f463e273980296ad5e78a62c83fb91354c25c2e28bfa19480ca41b0ca2d8beed456029eabc0ba69cf3504cf1207ab21bed0e3a60795f5b066019132212a9bd20e98b43bb32484454b7693bc63764d0ba8768da4336ad16a979b1d3e8b06e89afc4caafaddead83ad861a4596814062468d8cb2e131e71cf38c4e335bb3d1d9629251fd50a4273999a20e11d9a881fa2465c2ef32301fa8805ccb38b4656e3c815b54ef42f292d05847c0e5149b0a2ffd1719fcad10730b763406e9e453d2e4a556c397a984a7d8622466522e79f715f980279cb2d1d74d5fd15f8beb8df9c0a1fb93f0d5494ab701cd60cf2b613b484a191d873449c4815f44eebb62658ef90f7033a5e48d40c8f4ec9a25d4f1b73a150e5b03a4feec9142362e77d74d364bb8a40f9873efa2d9f458d84277fdb0063642d9ebc794356368a0b4e53f6ab0d9acf4418fa42d05c11db12cb67d6c4cbbfde4d85358abaf8042510db53c1540fcb40045b334bc54a17608e82433d1e9e53c99769b86b69b8cf1914584cdef479061718a2cc5bec5c31272e0463139721c0c3523a6ea31832b5c15aa59819304c217fbc51a2636bfff331e6dc1037e89be15c17d6708762976329353612f312b828e525c09b81afafa5ae5c25d82b70b6e55f892429a93e5eb4048ade675583e828da988f9d253123a06c0ed047adf4d93d20cc6c865f5a761fec27811305165cd4bda05f563215d0612944b88ade9d64477ae8fb441978720e70b0d77e2edafd3a2c571cd28a42cca2f289d157cec813c24e7f56051b4f28c153adfbb2c1ff90ea1fbc03cb89603387169072442f5d3081140e2256ebadcd775d2f1da92c15a9ff1ce6e980b3b1e91a7e379081ed46a4259fada21536af318eb2043ea16cece60b73acd415d239389cad9212e15bad1b1ae38f93c756635a9b87417faa844e4f43bae1f1ae68641a04f0ff1d55f9045cf7e3ed59fde5c07219b9113329356d4300885ee19c9955c5757db33c6ae75b49d035003171d02ccbd7321d6a14db0bd011d4877f04070dbda3b67bf22d083e", + "signingHash": "0xa998fed4c5f710305a6944f263d3d26edd3f4e3949d404f547eece43c10afd94", + "signature": "0x664be581b59cd495740a8a9aaaf7c6801a8bcedb531ace47da1be56ab30f1c4ccdaad6e81aa97352baca12b6c69754123bdee38c0d57bf15f0850572dc9b456234eaf37eb478f9117f952ae95a0d165d12d948b51672a03c9610a98cf332d6ad7ab8a87defb3ef7249cf8c3a815129ecf5600500702b7916ffe570cef0714e0c083a581c2971c45c4aa6b1c5226400e5fd594ea3ae97fe94a0dc7f1e0979b11a2f3d15ad54fea957992ada816f97cd76168a53ebffae36e5787b0f69e94b3e08eadefe4937ce8b383b5022e57ba7135cccd5b48e38916f1f0bdcbc5858bf93cad75195d4329ab41a518d820262b1b610f7bdbe1d6749d006a0dfe18d0be1a19fb3d8e37795b5bc37ebcd884f91459164cd2536b3496c4b25a4c74282ece5d64ab861184e942cf97f0edbe6e1293c4504d861e60d98c4f6523df27a1e80843005ad21665b3adcf46f349fb0d905d70631d2ee51c0086b252778eac27346eee65c0fc88c6db5936337b0afa7d8cec656612c81e11cc55abf421df770e6c2588c743d5540e1280be76309defaffde2b82c808976c337ee13735a21900a4686423625a0ba4819581edbe574e6d7053c5fd98d288db4104ea64fbc0e7ad11d50eb1470a882aa00ebfd983cdda14db34f7f968ccc93097cf037dceeb1375f2df4de09c8785f5fef8fbbe284566e5c9a2d38f5d2f9145b7f5087f6a89a56679680ca4180ad7da3ee45da685f0255a45db806e1379c1ed59bfe63feb7d74a239334c80ab9c1859d205ba798810adf8afc569170f94167439d137215d2ce0b2fa983ac138a3ce201cec4927c62b740912e7287417f86beb07af9c83fff843df1abd6e6f81865b82b3168528d1c473b4999b0179f1de8ae22e8ed7f698ee8463eb93fcfd4e017f29ab3f15a2e061de6deb09459d4ecc62741ffd8514d5c1f10eb3b1525ad60512ffad00e360e0d6add8ed6d6df48d63cf1e36f306bd76b1a245cdd09951727367e45b3a02d748dbfcbeea342be4cb0e1e3108e57993581409f8c6b34e2d38becfcf15c653b92c88412c087eddb0bc21eeb620317f49a9bf5d6164418a26322e1964fd676a547862c2a7ce5f13898e3fadec79a638f257532cfe977fe8ba5e96782f9e1e3e8b5f896a80d816141f0c988ea59ea321cffd23f298b76e49e92189e7f65718d14091daeb82d432470a2e472a39a154226a43c543db2bb933adad08344259ba08a65c543d2ee07b67328ca2d4e60e550b85215ea5873fedb505cc1e4db49e129249fb632ba22f11b897b9423d08f96ceaa863cd29dc16af6ac76c4388c2795250c04377277626992b085ed7be2cf1d63a2eda4b65e287081fdc4e9a3224ff57d81b3ba8d04eb88430a01c5eba35fad028e8de1812920cee2576d0bd291407c5fb70c5ce07104b9af7b98c4c709c7f019d4a66b136120b92612ad5e73dfcfc1da0fec3a7928e57d7d4769eecbaa4c269f2859d31d47d1ae40e4da5bfa6592074c5bf54b04c707b8d97455a0a606686e06bf5ef7617da2532f305267f61c5f627216b06ecc3da6c6f7b420e2dfecaa41657eab20c89927ad6eb5c4fcd513da89a637755f4a98c45cfa108f37415bbf49ee6cacfda8f22f7101a9798d844709a38f9168685f105157a937bb10d4f5b342deab8b8be8231490da52cc0c407bf942270ad93d4a9bed5c06499584835dbba75577dbbc47fd3d397f0417ade99549de4412c8893cf3e1a2ed74c234a7b60461efad57d9c9fed9eec3ebd652282b045174e19355d8cfcc10add9192ffffd428150dc3f48e0417e47d6407008c62486cd4057535a5a9ffc45ef559a51fbbece64306f64da9740108d0b51d01423379bb0a72fe050d2abf5f5acd25cff57f8e3bcdf938749c7bbf77437424ada88c167bcb6addc309b949a8e200b9a5b6797522635731b250e2405f98d054aaff4179ccb4b24159e4c033329100cadbef3da262203622d27899166f6c3c79a35daf7840853b9a3ce494bf035235cada8c31e28be56f0976ef9b96f15de57e6896a5aed57a7b5ce77cacd1c806ecf83566bee5d577f7414a106ce16ca6e8cbc144f571b1a37647041694a6409f68d15604960417a60bc4f1a878eb01e89159e701bb8fd96be45395a8b8c4f0cc5b982582741c4ccaff8961ea892f084b10646c7a27687a2d3c92324cc3a19a5b38ca2d5c573167ad54486ab3adfe9219882f947cc6a93a3827f4b51d76e90ffd1587646d921482022db8b5a22519be3a1e62e9a13ff9926e75c42e07aa295c8486df69dc96168e920e13c85eeda86dc560b9f5d4c77cb8ff001d390dc6c5a911c573ab1711df534930ef28832936c80cafcde731e999ce90741e669d93f653efba12466726fa997e7ad24d34395a02b8a4286f3604f120bf47e8ec41954e6def2de896be477ef7916f18214d28f58ae91ed8d7eae9e2df600d313b6cdb952195e9d030e0b8fc98a68cced3070f4abd2d252727320eb54b602ec861ba630ed3c5d6fc8c8b39f4f1e9c198a6dc8d5f825159ce15fcd7bea5701a225ac41bb152d1a077adc03ecf06870375f2d2618094a648b40244e4a981e7efeadc608c082dc1824c4ffdbc39afcc8c464ed5ca8dfc1540ae3a6c034364c356bf13f880abe8633fa041db78f4be0d17a4bb00959a697935c844c6ddc02222f7aebb1af2c96a757536159dc1dbc31131aefe4c198ccd2123eb5d0ca6147bbc9ab43e993508ef4ca383e2847d9fcb4c975dcb240bcfd164daa835311cf7dbde0f256deb5f3748b55c312a29a042725ecf07caa904513e71b4c0ebd3b31c2938e710e7c6be819bb3125e638ee4b54b4c8fe16df1cee7587e6bdfdcccf2e3b2aa4a54c86b0ae711f056c229c644f519f60570aed60fd3d0638dc341625fb4949d355e7d84cb478133d25730162623acbf5d36b9ed98dbd88b6bf7bf1f55006f5ba2d16297557f966cc01baca56e3f6435b724c0b6fa4cc0074efb0bb2cf0cba9a1c73d3337db7dc0c78b87746db7bbe5fc003edf608ce5d91dbd8b3cec0f738de14c8e2b6df47df91805eab5635402ff26245430641abd9511cffa6bf8d352a1f0d97ce2b08561c97a5f07a07e0ac42a2a73366442e0bf125a718553794b021640ef9f9f07040068cce2337606af46f897b7ad8ced05e14f7ab3e2bd847f810058d665a0c3b6903efd8f398c31e356b48216111d30348acf93d28dbec8e603cd16ea5d3b24f38367c52f5629fd51bec34e86ff21d4f5466a53aea7048babf3afaecec2c9de099bcb2845f66689e02306760ef5274e65f36fc61edf8112b3b414a878b8dbdc2ced0d7dae0e95c5d6e7c80a3b4cbccfe13293e454b6c757a8d9496999fb0c4d4dfe5e7f3f40e11172324323556687e95a4a6bfc4dadbec000000000000000000000000000000101a2f41", + "raw": "0x50f90ec5826d6180843b9aca0084773594008302d5709400000000000000000000000000000000000000010180c001b90520372c0f4874450fb92ace74d41bc0326c7f739589f9b86a97afa87ef65d5939e608c81a44909e41f41931349f744b7aedff8d5270b91c4a2f61192e2bb6e3e6d12231deab235359e78ccada386becb6a6a1105afc0999243ab8b363f7cd2c19b2b741c9969dcf20252f20d130dc05d9244f58d6de9b4fb4b6f0125c43b60ebe3c7272b6ae7578f1abb4bb5e2dcb31eebf4aa7089aa2bf40a0ba5eb73aaa90e45472168738cb0e866547e079075d0341c4728ed794cd449d0cdeceaf64d09173a2677e3f2621b56014df58ee8de2bbcf8cb2bf369e57a28e40b24df6d0b15d3417b7b7fce3c49230b3bb7c7080c4f1344380db37299d8c0c29a7c9e95bfc4f3ec70b767895be6ad798449f94c92f320696f8f9ec844fc9451f5ab30874e6c78673b932e24a918d5bc03f4fa647c8679631ad8b30ba4f9a1a790a535104f5079f781fa4c4aad807777327e08bd6e14b957e527650d39e2de7d30da7b2b27457d3539c2f99903054bd1a6d6301b2f83249db80dedc911059b047b5552407ed32b79b57ea4968198decf978fed532277fb189841d0c17f261f1a7c4618c33b258a71cb6b2b921c48735c1fbc375a80fe2d702e9f70db34547147f6d65153f1c508ff90aaf57dfde59ce6e56c5c52049b10fbc2640cd937bf5027d755444cd5e84aad66be4ccf04f710f0b970cbe7fc5e4e7a44f5d8fc2af94ec6df87862dabe0d85dd17e43728800d5dc8ff9e9e1fd349b9d6431f264836a447646a1ee2d73e6a4d1803d71b98510d94d53b5d07764400f413b7837f463e273980296ad5e78a62c83fb91354c25c2e28bfa19480ca41b0ca2d8beed456029eabc0ba69cf3504cf1207ab21bed0e3a60795f5b066019132212a9bd20e98b43bb32484454b7693bc63764d0ba8768da4336ad16a979b1d3e8b06e89afc4caafaddead83ad861a4596814062468d8cb2e131e71cf38c4e335bb3d1d9629251fd50a4273999a20e11d9a881fa2465c2ef32301fa8805ccb38b4656e3c815b54ef42f292d05847c0e5149b0a2ffd1719fcad10730b763406e9e453d2e4a556c397a984a7d8622466522e79f715f980279cb2d1d74d5fd15f8beb8df9c0a1fb93f0d5494ab701cd60cf2b613b484a191d873449c4815f44eebb62658ef90f7033a5e48d40c8f4ec9a25d4f1b73a150e5b03a4feec9142362e77d74d364bb8a40f9873efa2d9f458d84277fdb0063642d9ebc794356368a0b4e53f6ab0d9acf4418fa42d05c11db12cb67d6c4cbbfde4d85358abaf8042510db53c1540fcb40045b334bc54a17608e82433d1e9e53c99769b86b69b8cf1914584cdef479061718a2cc5bec5c31272e0463139721c0c3523a6ea31832b5c15aa59819304c217fbc51a2636bfff331e6dc1037e89be15c17d6708762976329353612f312b828e525c09b81afafa5ae5c25d82b70b6e55f892429a93e5eb4048ade675583e828da988f9d253123a06c0ed047adf4d93d20cc6c865f5a761fec27811305165cd4bda05f563215d0612944b88ade9d64477ae8fb441978720e70b0d77e2edafd3a2c571cd28a42cca2f289d157cec813c24e7f56051b4f28c153adfbb2c1ff90ea1fbc03cb89603387169072442f5d3081140e2256ebadcd775d2f1da92c15a9ff1ce6e980b3b1e91a7e379081ed46a4259fada21536af318eb2043ea16cece60b73acd415d239389cad9212e15bad1b1ae38f93c756635a9b87417faa844e4f43bae1f1ae68641a04f0ff1d55f9045cf7e3ed59fde5c07219b9113329356d4300885ee19c9955c5757db33c6ae75b49d035003171d02ccbd7321d6a14db0bd011d4877f04070dbda3b67bf22d083eb90974664be581b59cd495740a8a9aaaf7c6801a8bcedb531ace47da1be56ab30f1c4ccdaad6e81aa97352baca12b6c69754123bdee38c0d57bf15f0850572dc9b456234eaf37eb478f9117f952ae95a0d165d12d948b51672a03c9610a98cf332d6ad7ab8a87defb3ef7249cf8c3a815129ecf5600500702b7916ffe570cef0714e0c083a581c2971c45c4aa6b1c5226400e5fd594ea3ae97fe94a0dc7f1e0979b11a2f3d15ad54fea957992ada816f97cd76168a53ebffae36e5787b0f69e94b3e08eadefe4937ce8b383b5022e57ba7135cccd5b48e38916f1f0bdcbc5858bf93cad75195d4329ab41a518d820262b1b610f7bdbe1d6749d006a0dfe18d0be1a19fb3d8e37795b5bc37ebcd884f91459164cd2536b3496c4b25a4c74282ece5d64ab861184e942cf97f0edbe6e1293c4504d861e60d98c4f6523df27a1e80843005ad21665b3adcf46f349fb0d905d70631d2ee51c0086b252778eac27346eee65c0fc88c6db5936337b0afa7d8cec656612c81e11cc55abf421df770e6c2588c743d5540e1280be76309defaffde2b82c808976c337ee13735a21900a4686423625a0ba4819581edbe574e6d7053c5fd98d288db4104ea64fbc0e7ad11d50eb1470a882aa00ebfd983cdda14db34f7f968ccc93097cf037dceeb1375f2df4de09c8785f5fef8fbbe284566e5c9a2d38f5d2f9145b7f5087f6a89a56679680ca4180ad7da3ee45da685f0255a45db806e1379c1ed59bfe63feb7d74a239334c80ab9c1859d205ba798810adf8afc569170f94167439d137215d2ce0b2fa983ac138a3ce201cec4927c62b740912e7287417f86beb07af9c83fff843df1abd6e6f81865b82b3168528d1c473b4999b0179f1de8ae22e8ed7f698ee8463eb93fcfd4e017f29ab3f15a2e061de6deb09459d4ecc62741ffd8514d5c1f10eb3b1525ad60512ffad00e360e0d6add8ed6d6df48d63cf1e36f306bd76b1a245cdd09951727367e45b3a02d748dbfcbeea342be4cb0e1e3108e57993581409f8c6b34e2d38becfcf15c653b92c88412c087eddb0bc21eeb620317f49a9bf5d6164418a26322e1964fd676a547862c2a7ce5f13898e3fadec79a638f257532cfe977fe8ba5e96782f9e1e3e8b5f896a80d816141f0c988ea59ea321cffd23f298b76e49e92189e7f65718d14091daeb82d432470a2e472a39a154226a43c543db2bb933adad08344259ba08a65c543d2ee07b67328ca2d4e60e550b85215ea5873fedb505cc1e4db49e129249fb632ba22f11b897b9423d08f96ceaa863cd29dc16af6ac76c4388c2795250c04377277626992b085ed7be2cf1d63a2eda4b65e287081fdc4e9a3224ff57d81b3ba8d04eb88430a01c5eba35fad028e8de1812920cee2576d0bd291407c5fb70c5ce07104b9af7b98c4c709c7f019d4a66b136120b92612ad5e73dfcfc1da0fec3a7928e57d7d4769eecbaa4c269f2859d31d47d1ae40e4da5bfa6592074c5bf54b04c707b8d97455a0a606686e06bf5ef7617da2532f305267f61c5f627216b06ecc3da6c6f7b420e2dfecaa41657eab20c89927ad6eb5c4fcd513da89a637755f4a98c45cfa108f37415bbf49ee6cacfda8f22f7101a9798d844709a38f9168685f105157a937bb10d4f5b342deab8b8be8231490da52cc0c407bf942270ad93d4a9bed5c06499584835dbba75577dbbc47fd3d397f0417ade99549de4412c8893cf3e1a2ed74c234a7b60461efad57d9c9fed9eec3ebd652282b045174e19355d8cfcc10add9192ffffd428150dc3f48e0417e47d6407008c62486cd4057535a5a9ffc45ef559a51fbbece64306f64da9740108d0b51d01423379bb0a72fe050d2abf5f5acd25cff57f8e3bcdf938749c7bbf77437424ada88c167bcb6addc309b949a8e200b9a5b6797522635731b250e2405f98d054aaff4179ccb4b24159e4c033329100cadbef3da262203622d27899166f6c3c79a35daf7840853b9a3ce494bf035235cada8c31e28be56f0976ef9b96f15de57e6896a5aed57a7b5ce77cacd1c806ecf83566bee5d577f7414a106ce16ca6e8cbc144f571b1a37647041694a6409f68d15604960417a60bc4f1a878eb01e89159e701bb8fd96be45395a8b8c4f0cc5b982582741c4ccaff8961ea892f084b10646c7a27687a2d3c92324cc3a19a5b38ca2d5c573167ad54486ab3adfe9219882f947cc6a93a3827f4b51d76e90ffd1587646d921482022db8b5a22519be3a1e62e9a13ff9926e75c42e07aa295c8486df69dc96168e920e13c85eeda86dc560b9f5d4c77cb8ff001d390dc6c5a911c573ab1711df534930ef28832936c80cafcde731e999ce90741e669d93f653efba12466726fa997e7ad24d34395a02b8a4286f3604f120bf47e8ec41954e6def2de896be477ef7916f18214d28f58ae91ed8d7eae9e2df600d313b6cdb952195e9d030e0b8fc98a68cced3070f4abd2d252727320eb54b602ec861ba630ed3c5d6fc8c8b39f4f1e9c198a6dc8d5f825159ce15fcd7bea5701a225ac41bb152d1a077adc03ecf06870375f2d2618094a648b40244e4a981e7efeadc608c082dc1824c4ffdbc39afcc8c464ed5ca8dfc1540ae3a6c034364c356bf13f880abe8633fa041db78f4be0d17a4bb00959a697935c844c6ddc02222f7aebb1af2c96a757536159dc1dbc31131aefe4c198ccd2123eb5d0ca6147bbc9ab43e993508ef4ca383e2847d9fcb4c975dcb240bcfd164daa835311cf7dbde0f256deb5f3748b55c312a29a042725ecf07caa904513e71b4c0ebd3b31c2938e710e7c6be819bb3125e638ee4b54b4c8fe16df1cee7587e6bdfdcccf2e3b2aa4a54c86b0ae711f056c229c644f519f60570aed60fd3d0638dc341625fb4949d355e7d84cb478133d25730162623acbf5d36b9ed98dbd88b6bf7bf1f55006f5ba2d16297557f966cc01baca56e3f6435b724c0b6fa4cc0074efb0bb2cf0cba9a1c73d3337db7dc0c78b87746db7bbe5fc003edf608ce5d91dbd8b3cec0f738de14c8e2b6df47df91805eab5635402ff26245430641abd9511cffa6bf8d352a1f0d97ce2b08561c97a5f07a07e0ac42a2a73366442e0bf125a718553794b021640ef9f9f07040068cce2337606af46f897b7ad8ced05e14f7ab3e2bd847f810058d665a0c3b6903efd8f398c31e356b48216111d30348acf93d28dbec8e603cd16ea5d3b24f38367c52f5629fd51bec34e86ff21d4f5466a53aea7048babf3afaecec2c9de099bcb2845f66689e02306760ef5274e65f36fc61edf8112b3b414a878b8dbdc2ced0d7dae0e95c5d6e7c80a3b4cbccfe13293e454b6c757a8d9496999fb0c4d4dfe5e7f3f40e11172324323556687e95a4a6bfc4dadbec000000000000000000000000000000101a2f41", + "hash": "0x5ee00afa7d595efaffab2cf573a82e50c7d0f37bc1c2a53a11f7120155bf57b6", + "intrinsicGasEstimate": "135712" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-2.json b/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-2.json new file mode 100755 index 000000000..3a93c378b --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-2.json @@ -0,0 +1,28 @@ +{ + "id": "valid-ml-dsa-2", + "expect": "valid", + "alg": 2, + "chainId": 28001, + "publicKey": "0x5424000ae9a496294dd6b99046cfdbb235ae71031b379ce274c13b0c96411740cb61021a5390fbe8fb56b642b4e5e5abb7aeab143e0037f8db283b9f2febd650265ed6b05f1b867c124aef245c1811422f92414447fd0b20844e0f1b1cb4eec052400aad52b9d773aae0015c0c390bfdde3d367bd8ef9c3c73bca3164b9d418ecbb2d25303bbd12739a858c5fac4cbfa0203b9f3c319e9bc89d17a7a244b57d6613b5caabdb528f077eff9727015b9c266d777c0ba11920118c7ec4dd59b380c40e361a5b23ce04be4c61e12a1c21e091fa0d890687cbf588944db3e34253c75cdf797378de79162e0b4ca309f550365a289f652dd6d559478912cff70a5417589f73f14640970694d7b5a6bd8f000a65c632f0326ed3d128fda96dbea68cb812634dd75e9f63813a5645336681378b6a63220c066550aba43a5b937131d41f08752d13949a115a74bf96fa1925ff4338e10df0301abe40aaa49e14a1a1d58eef005a0f1d0299267002cebeda20cadcea7419cd0c365c53aede1aa36efaf764d3d36169747cdc8ee9a09e0a0ac6bcaeaeded0cd303c965d705d1b91a8b35f408ad8a033b02ff57610bddbfa60e2114e53f20f8fcad15dffac6a494c3f4f631590f2be3422af14cba7c900c9c38796952e20c3069bea2ab54bf0edf9315903aa5cf68549f878eafcc77561b36f8b78d950871ed4914417316f868a2bc54c72d3c9929f0138a2f0cbccb7c4141e94bb8a7ae11f660861cbbe498697d7327709271460a75bd4e024de3d4d6fe5af066944c96ba87459fa948a95eeb61abbaf643190ccaa9cd18591eb6f249a6eb92db89fc95616d21b41d7d15424b80a750938a12cd57d50ef95aaf222025dc4d81df320d9bc32c608b1c5a1aac8bd14c0f7a4c4380cdd65c793a6287050ff4d609102fd91e47e7365fb55513aeca273618528c199f7bb151e9c11a0bf202147734d1be9d5d0e9318096fa567317ed9fa6a8efe201b915b9aa05ca0d19e15c9a80449cc130b398ebbac3d938f55eea8f74e024b0e33dfecdbea02b920ddc5b277146685916194bfa1f8ac7784c7ed76923d4ff9ed97d3ceac283f9b26977df0133c5fa4fb5fcec577bc152e926529f06ff50c204c083c0b4d6b8d474cf5cf7cfcf7acf76921225443eb0abf5e4c76d0a3f524243ee4e372e80ff0f76dd9d135f240114a2ebe6d69609b6c60d275f251d7dceadc600d18e0cf8bc8fa8392e61fa32b8f7481c4883e19d820b51af0f87d3f7faae44e3b908fc759c6de59361487d8e424ffbd662d57a68801110e9cb099214143253949cc479eaae0e321fecab90c63b06819ce3cf56fc2fc1419408075c658024a28950aa47d549bcdb8b5bc9aeab463466c7834ca7d73058c206a95a023f0c8ac95badd383e63041e1f0ef69f51634f5ce2f48d80f8f2e92f4a1fb5322930141fc50e1e20bd235a8b8d768d473b46711257d028e710f82f0b6bd923da05ca64ae805f708577e125b3fca2feb5656f61ded034eaae481a195628801c82db85345f9ffdc72c860cffe2264ba4be2a08fdb37a4f5f80276baba4ea637847335c89dbd35504389f68b2d61ea66d4eac5fd0057d9e757d929214a7d83daf2fc2b3f840e083792d20d772584b252ba955ae8ae8c36af648c59ae0b25d3bca19413fbd749077b6969db5847409d13e4a67387e59116fe3836a733f3253d47f9919f49618fac8edf5fd711a4239447655d6c40f479f86ef3c9d4dc1a6f9683a3f1bc5c9730025e76ea1588d43494f59823f42c207e34412f73c7e2a126501b8fb810f12995c213063d909a5a9c2653d3511ceb809efa69c638f4c977d46a2a305cc831ecc0feebf5d9356ede6c780da78fe2ad683b3312282d5142612c0d1f85108de04de5c3d5414b62826d5b75f8887dc2d932c40f306c08e5d4f69ef4d344fe4317552df9890d0961e3d857bd9b2c5b44536d8606f62f66d14ddd43b0e5d3379cf66d664616df12b1c62385a57f6a562c34e120b79d64ca39d8b23e1e07b2c03910d711f09df5b54cb0e133dd751bea7832fdb38de2f1dafae69fbdf82b6887ff0a92940299020a835b958bb01b25b8699a0846614cb256a6621ef92e4a0947df9141ed4f91eca527aef25862158a8fa712dd60dda947f6a16e077810e29542a56f9244c34a73454b9ad0d8e8c40bd503efe12c4e5bf7d0ff8e6ab642a039f4e8b575d33c0c3de77a1abfa60b0252d7a549dd791d9630c8b848988157608448d77938bfb27beaea8f9b4a259263797c5b2fbdc7f469b2769f7dcb7b9478cdf5f109322eb2f0a83163469b72d8121fe8e01df227563cbd941a1f63961e2a010c6322a812a014279583a0066492a17d1a15c07024f6b8b1561041b3db608ec1c7475ce4d086e60523e85d7a955841558a35535d6e52cb166669a69049646b94d2fdb901ffbb1446a2d7f58696bce000ccbbb6942b0ad6480d006602c228218d3a2f0bc6a5d5c73acda9fc4b0b496a7d527050f8d77b71641f030368e9494bfe8e9dbf6dd4040426da1b0423739b40450273f4a8d551637e5fe3ca8d54fc476e6278e75cebf4a4ac3ac8ef3807041c4b274568797c8caaffae7df08c6c158d92411db981ea02cc212064c3ad6a9cd1cc02087acce5ceb8d7cddaec429d199c3d90670288be6e88e6826d1f6c417df5f35139c71a62c0267adfce7cb3aa49e827165b28c8cc157a691cb52ef103d8d7ca0ebfc628904d0b2d365dd3401b620d6d93cef670e2f", + "seed": "0xdaaaf3ca4a40b10b8d8329296d5a0eb0ea604486c8bb582e6d7cd3d7f7dacc63", + "tx": { + "alg": 2, + "publicKey": "0x5424000ae9a496294dd6b99046cfdbb235ae71031b379ce274c13b0c96411740cb61021a5390fbe8fb56b642b4e5e5abb7aeab143e0037f8db283b9f2febd650265ed6b05f1b867c124aef245c1811422f92414447fd0b20844e0f1b1cb4eec052400aad52b9d773aae0015c0c390bfdde3d367bd8ef9c3c73bca3164b9d418ecbb2d25303bbd12739a858c5fac4cbfa0203b9f3c319e9bc89d17a7a244b57d6613b5caabdb528f077eff9727015b9c266d777c0ba11920118c7ec4dd59b380c40e361a5b23ce04be4c61e12a1c21e091fa0d890687cbf588944db3e34253c75cdf797378de79162e0b4ca309f550365a289f652dd6d559478912cff70a5417589f73f14640970694d7b5a6bd8f000a65c632f0326ed3d128fda96dbea68cb812634dd75e9f63813a5645336681378b6a63220c066550aba43a5b937131d41f08752d13949a115a74bf96fa1925ff4338e10df0301abe40aaa49e14a1a1d58eef005a0f1d0299267002cebeda20cadcea7419cd0c365c53aede1aa36efaf764d3d36169747cdc8ee9a09e0a0ac6bcaeaeded0cd303c965d705d1b91a8b35f408ad8a033b02ff57610bddbfa60e2114e53f20f8fcad15dffac6a494c3f4f631590f2be3422af14cba7c900c9c38796952e20c3069bea2ab54bf0edf9315903aa5cf68549f878eafcc77561b36f8b78d950871ed4914417316f868a2bc54c72d3c9929f0138a2f0cbccb7c4141e94bb8a7ae11f660861cbbe498697d7327709271460a75bd4e024de3d4d6fe5af066944c96ba87459fa948a95eeb61abbaf643190ccaa9cd18591eb6f249a6eb92db89fc95616d21b41d7d15424b80a750938a12cd57d50ef95aaf222025dc4d81df320d9bc32c608b1c5a1aac8bd14c0f7a4c4380cdd65c793a6287050ff4d609102fd91e47e7365fb55513aeca273618528c199f7bb151e9c11a0bf202147734d1be9d5d0e9318096fa567317ed9fa6a8efe201b915b9aa05ca0d19e15c9a80449cc130b398ebbac3d938f55eea8f74e024b0e33dfecdbea02b920ddc5b277146685916194bfa1f8ac7784c7ed76923d4ff9ed97d3ceac283f9b26977df0133c5fa4fb5fcec577bc152e926529f06ff50c204c083c0b4d6b8d474cf5cf7cfcf7acf76921225443eb0abf5e4c76d0a3f524243ee4e372e80ff0f76dd9d135f240114a2ebe6d69609b6c60d275f251d7dceadc600d18e0cf8bc8fa8392e61fa32b8f7481c4883e19d820b51af0f87d3f7faae44e3b908fc759c6de59361487d8e424ffbd662d57a68801110e9cb099214143253949cc479eaae0e321fecab90c63b06819ce3cf56fc2fc1419408075c658024a28950aa47d549bcdb8b5bc9aeab463466c7834ca7d73058c206a95a023f0c8ac95badd383e63041e1f0ef69f51634f5ce2f48d80f8f2e92f4a1fb5322930141fc50e1e20bd235a8b8d768d473b46711257d028e710f82f0b6bd923da05ca64ae805f708577e125b3fca2feb5656f61ded034eaae481a195628801c82db85345f9ffdc72c860cffe2264ba4be2a08fdb37a4f5f80276baba4ea637847335c89dbd35504389f68b2d61ea66d4eac5fd0057d9e757d929214a7d83daf2fc2b3f840e083792d20d772584b252ba955ae8ae8c36af648c59ae0b25d3bca19413fbd749077b6969db5847409d13e4a67387e59116fe3836a733f3253d47f9919f49618fac8edf5fd711a4239447655d6c40f479f86ef3c9d4dc1a6f9683a3f1bc5c9730025e76ea1588d43494f59823f42c207e34412f73c7e2a126501b8fb810f12995c213063d909a5a9c2653d3511ceb809efa69c638f4c977d46a2a305cc831ecc0feebf5d9356ede6c780da78fe2ad683b3312282d5142612c0d1f85108de04de5c3d5414b62826d5b75f8887dc2d932c40f306c08e5d4f69ef4d344fe4317552df9890d0961e3d857bd9b2c5b44536d8606f62f66d14ddd43b0e5d3379cf66d664616df12b1c62385a57f6a562c34e120b79d64ca39d8b23e1e07b2c03910d711f09df5b54cb0e133dd751bea7832fdb38de2f1dafae69fbdf82b6887ff0a92940299020a835b958bb01b25b8699a0846614cb256a6621ef92e4a0947df9141ed4f91eca527aef25862158a8fa712dd60dda947f6a16e077810e29542a56f9244c34a73454b9ad0d8e8c40bd503efe12c4e5bf7d0ff8e6ab642a039f4e8b575d33c0c3de77a1abfa60b0252d7a549dd791d9630c8b848988157608448d77938bfb27beaea8f9b4a259263797c5b2fbdc7f469b2769f7dcb7b9478cdf5f109322eb2f0a83163469b72d8121fe8e01df227563cbd941a1f63961e2a010c6322a812a014279583a0066492a17d1a15c07024f6b8b1561041b3db608ec1c7475ce4d086e60523e85d7a955841558a35535d6e52cb166669a69049646b94d2fdb901ffbb1446a2d7f58696bce000ccbbb6942b0ad6480d006602c228218d3a2f0bc6a5d5c73acda9fc4b0b496a7d527050f8d77b71641f030368e9494bfe8e9dbf6dd4040426da1b0423739b40450273f4a8d551637e5fe3ca8d54fc476e6278e75cebf4a4ac3ac8ef3807041c4b274568797c8caaffae7df08c6c158d92411db981ea02cc212064c3ad6a9cd1cc02087acce5ceb8d7cddaec429d199c3d90670288be6e88e6826d1f6c417df5f35139c71a62c0267adfce7cb3aa49e827165b28c8cc157a691cb52ef103d8d7ca0ebfc628904d0b2d365dd3401b620d6d93cef670e2f", + "chainId": 28001, + "nonce": 0, + "maxPriorityFeePerGas": "1000000000", + "maxFeePerGas": "2000000000", + "to": "0x0000000000000000000000000000000000000001", + "value": "1", + "data": "0x", + "accessList": [] + }, + "algName": "ML-DSA-65", + "sender": "0x0602be26ec9e01dd88121f7c203ead9eecb9ad3e", + "signingPreimage": "0x50f907ce826d6180843b9aca008477359400830383209400000000000000000000000000000000000000010180c002b907a05424000ae9a496294dd6b99046cfdbb235ae71031b379ce274c13b0c96411740cb61021a5390fbe8fb56b642b4e5e5abb7aeab143e0037f8db283b9f2febd650265ed6b05f1b867c124aef245c1811422f92414447fd0b20844e0f1b1cb4eec052400aad52b9d773aae0015c0c390bfdde3d367bd8ef9c3c73bca3164b9d418ecbb2d25303bbd12739a858c5fac4cbfa0203b9f3c319e9bc89d17a7a244b57d6613b5caabdb528f077eff9727015b9c266d777c0ba11920118c7ec4dd59b380c40e361a5b23ce04be4c61e12a1c21e091fa0d890687cbf588944db3e34253c75cdf797378de79162e0b4ca309f550365a289f652dd6d559478912cff70a5417589f73f14640970694d7b5a6bd8f000a65c632f0326ed3d128fda96dbea68cb812634dd75e9f63813a5645336681378b6a63220c066550aba43a5b937131d41f08752d13949a115a74bf96fa1925ff4338e10df0301abe40aaa49e14a1a1d58eef005a0f1d0299267002cebeda20cadcea7419cd0c365c53aede1aa36efaf764d3d36169747cdc8ee9a09e0a0ac6bcaeaeded0cd303c965d705d1b91a8b35f408ad8a033b02ff57610bddbfa60e2114e53f20f8fcad15dffac6a494c3f4f631590f2be3422af14cba7c900c9c38796952e20c3069bea2ab54bf0edf9315903aa5cf68549f878eafcc77561b36f8b78d950871ed4914417316f868a2bc54c72d3c9929f0138a2f0cbccb7c4141e94bb8a7ae11f660861cbbe498697d7327709271460a75bd4e024de3d4d6fe5af066944c96ba87459fa948a95eeb61abbaf643190ccaa9cd18591eb6f249a6eb92db89fc95616d21b41d7d15424b80a750938a12cd57d50ef95aaf222025dc4d81df320d9bc32c608b1c5a1aac8bd14c0f7a4c4380cdd65c793a6287050ff4d609102fd91e47e7365fb55513aeca273618528c199f7bb151e9c11a0bf202147734d1be9d5d0e9318096fa567317ed9fa6a8efe201b915b9aa05ca0d19e15c9a80449cc130b398ebbac3d938f55eea8f74e024b0e33dfecdbea02b920ddc5b277146685916194bfa1f8ac7784c7ed76923d4ff9ed97d3ceac283f9b26977df0133c5fa4fb5fcec577bc152e926529f06ff50c204c083c0b4d6b8d474cf5cf7cfcf7acf76921225443eb0abf5e4c76d0a3f524243ee4e372e80ff0f76dd9d135f240114a2ebe6d69609b6c60d275f251d7dceadc600d18e0cf8bc8fa8392e61fa32b8f7481c4883e19d820b51af0f87d3f7faae44e3b908fc759c6de59361487d8e424ffbd662d57a68801110e9cb099214143253949cc479eaae0e321fecab90c63b06819ce3cf56fc2fc1419408075c658024a28950aa47d549bcdb8b5bc9aeab463466c7834ca7d73058c206a95a023f0c8ac95badd383e63041e1f0ef69f51634f5ce2f48d80f8f2e92f4a1fb5322930141fc50e1e20bd235a8b8d768d473b46711257d028e710f82f0b6bd923da05ca64ae805f708577e125b3fca2feb5656f61ded034eaae481a195628801c82db85345f9ffdc72c860cffe2264ba4be2a08fdb37a4f5f80276baba4ea637847335c89dbd35504389f68b2d61ea66d4eac5fd0057d9e757d929214a7d83daf2fc2b3f840e083792d20d772584b252ba955ae8ae8c36af648c59ae0b25d3bca19413fbd749077b6969db5847409d13e4a67387e59116fe3836a733f3253d47f9919f49618fac8edf5fd711a4239447655d6c40f479f86ef3c9d4dc1a6f9683a3f1bc5c9730025e76ea1588d43494f59823f42c207e34412f73c7e2a126501b8fb810f12995c213063d909a5a9c2653d3511ceb809efa69c638f4c977d46a2a305cc831ecc0feebf5d9356ede6c780da78fe2ad683b3312282d5142612c0d1f85108de04de5c3d5414b62826d5b75f8887dc2d932c40f306c08e5d4f69ef4d344fe4317552df9890d0961e3d857bd9b2c5b44536d8606f62f66d14ddd43b0e5d3379cf66d664616df12b1c62385a57f6a562c34e120b79d64ca39d8b23e1e07b2c03910d711f09df5b54cb0e133dd751bea7832fdb38de2f1dafae69fbdf82b6887ff0a92940299020a835b958bb01b25b8699a0846614cb256a6621ef92e4a0947df9141ed4f91eca527aef25862158a8fa712dd60dda947f6a16e077810e29542a56f9244c34a73454b9ad0d8e8c40bd503efe12c4e5bf7d0ff8e6ab642a039f4e8b575d33c0c3de77a1abfa60b0252d7a549dd791d9630c8b848988157608448d77938bfb27beaea8f9b4a259263797c5b2fbdc7f469b2769f7dcb7b9478cdf5f109322eb2f0a83163469b72d8121fe8e01df227563cbd941a1f63961e2a010c6322a812a014279583a0066492a17d1a15c07024f6b8b1561041b3db608ec1c7475ce4d086e60523e85d7a955841558a35535d6e52cb166669a69049646b94d2fdb901ffbb1446a2d7f58696bce000ccbbb6942b0ad6480d006602c228218d3a2f0bc6a5d5c73acda9fc4b0b496a7d527050f8d77b71641f030368e9494bfe8e9dbf6dd4040426da1b0423739b40450273f4a8d551637e5fe3ca8d54fc476e6278e75cebf4a4ac3ac8ef3807041c4b274568797c8caaffae7df08c6c158d92411db981ea02cc212064c3ad6a9cd1cc02087acce5ceb8d7cddaec429d199c3d90670288be6e88e6826d1f6c417df5f35139c71a62c0267adfce7cb3aa49e827165b28c8cc157a691cb52ef103d8d7ca0ebfc628904d0b2d365dd3401b620d6d93cef670e2f", + "signingHash": "0xce8c919ee46badc976518a728e7720c6afe65322bb25ff83a28c364c7ba1999e", + "signature": "0x33fc1486a0e70aeb6fef62ce5a0dfb51fcec12164e4024b0c49ce8b65e01356d80a9571af8f69a9c7256ed549d699a31ceff21c13c482ee0c5759f96125b0099495feacf22a001b2c887b107a9ca9e84de461fbc6e143566de56c710156de5b5f4b7ffe29c0124c1fbb6a792110284c9ad713d89bbb5ed444d09408c65a9f74c5f6c4fd281d31738db82913dcd1ac1fccbba24dc933fb9a8e6c4e426fb98590d7da0252c34d866c114526ded1c9d96daea12ecbd8f2a44531dfb72f02c02b267edf0560b1fb06b087bb6ce02b2922d92f81bb7da99b90e4a2dd68aa858759584490be602369dd606a510b6228e3b941421a3006a697b79866cae011d8aa496de4f3bfffdc0a087d01323db849f6237d7ac476d18bb417f26a697388b4c0a78533f3dd763398719c9ee5bf0299786fb8c4143af8c1195103390d4494b735c06b5815c454dba2fcdd27d214c48712609ffe7ad7c082e835d7477de2358fb3c4b5162027f816ca85aa4a46c25105175e77c8e5394db6fb3999c25ce578f066329182b28fd5b68769cb07ebc67e47a537f6cb62bfd18af162113a4df7f8908e0ce953b6a9637c850f24de0fda239c25fe4352f3b381fc270384d51d1af1ef0dea8501f98ea71f26de97e98799c4b2a316a216bd4af4861ad83fa4570532029564581bb35ac543355ba3aa246b59c6a5d9a91b938f3c4f0ad6d6f567fffdb6fb78402ded5fdc544a0f5fd87e4677326ca003dffdba8fd390487a6469991506a18f376b12db5be3bdcf4a4bc2f5b34dd8f7066bec3b40a6502f414eac3cd1ed43431b033757e86cca57691b0e1f7eec68fad9423f8b0620aa94798546bc878cf29d74ae74af5244ed9b97107fb83abe25dc160ec05cda1c50b76db981aca781868a7913a3e7c98aa5a3ea8bc81270e6f565138dba33c9c7e887641fd3dafd458b9c64600151038db05725a976950307c662c2eb668e3067f943b9bfd805307729b39ed77309fd5e67ecfc56cc231057a6628fb6f528fb969378529dea2c58fa0b4d791ca591ced733e8cf93a8e19907538f45c2618612648d3e1a78492afc154b7bb0285aea97d618e74a74530b492c66c6bd31557cdc55476b3f163196ec8e87f110834ffb8c232dc77cbf2f7b490f520b3b328af44fecca860a19bee9af6a5f69f63487d7dc6b7bf1233c4735522fedd475f905f044a0a7f658a7a378958cca56a163a343a010f4b65d1bc38cd57d08e0f887293fbc106ad7b15aacca6d51558cb8478b119acde04a19b007802a8e9578121304622aee7858d1794ade88973d6fdf981ebabc98fc417d765c075bf8f76b9781dff7c60071878027c057aade8eaf820186035499e9e5fbf8791e6fc0a0e49047af312a8b1b1e80628dc4db4f45842e19096a54733d28028203aa668bd8655631a01c000c956c32ff10572fdbc95b2f26d09fca84c093ddaa122ad93598c03de9273873ece5096648a6251a27e993ec7b6ea4f2181c09bb06852799323f3e993a4b7461439f702cb9df183fcaab11b8bd2ad391924d5e6ef261fea01c91cdc10d9345c290dfc3c040318d11419563d407c8365fef3dd31d8f9d7d338f5f2cd00433d1d06547ae9c650d14d9a7e5b683f0458e7a909d90d4a57201ca5b8753c13bda3591f9cadffd0987d1c7fca1c5a0cec1e13c612d0390d7c0e2f422c97cda29959cd7b714fbeaa5da7b0bcf911c2744a9a25c7d49e93342f61e10a33fda80fadfed2668bfab8767ce80480093b4845cd5ec83082e8f9ad63236743e72842d1a3226640a549c2c1d002a176e2427b2ae612dc272e3d9fa80a904eb8f93f494a52706346c08b06c9d1d8a61a9c7112c0933910882f0da6eea3c389f4faeea51c03394eab4cc02056d704b8839afd76f0839be5ffdc873b88f9a755be6f0229b0843839a25d63c18da89be1c5da930a101913ffba01fd00f2a447d5f58ae8f21554feb47f42d40c32158219dbbb1e5e96ab3dc26cd6a435525c265b65b0bf48d68e9b3c9178a509833aa47c23e63aa9a6f74bef1e4ef863556b11c014b85ac7c157f1e64531b676eb28c68e82e0089d2bd798213c836cc354d4883dc0b607456ab7f894f0a1f73356fc05a5c97a9cf3b231890c39105b751f6fc54063a08f3d3a264ab90cb7de1d0e2f6acb92302cc9b4bb512e720e6ff8343004028ad223a70d395c5f974d3ddd380f798e80edb4b13555c3be0cb1a500e19a8b1b05f9cae85d7eed756ebcfa57828f1054296ffa48d426ceb83c69ebe1b983421f42316ca6f50bf8df0f4d4aeef85005638a304d88764ec26366a1437867c89800aee55ba428e0c07542e123d748c795560153007f768b20bb057fc2643b7db992c3b9cbfd88657b17fbe8a783da2050affb518cab4226cdf28fa97f48651bd142932835f061f8642e79d1f7ae8ff8665aa85aba24a850b2042dd37e61e665a451f17cbe9d57ed5ecb1dce9ec34c576762929dbf46964de7c44c9f6b10fcf52b48649ded2d491bbe4bb6ad578cd31cbdea6df8342dbb7f33857617250b014fc6d887a448f7a5cef25ff69dbc94733bfac1d5f8593af7fbe4759d23ba8da1f405ba179c96d8ae49eb760446d842f0d61ab08508a3e31e4953e13a1b197d00644303e8a9513199583709f41757740a0dff347c3859d3a4ec391481af349019f75ccfdba111a4c338fd8283733115ce7c114111abb157c1a5a84f7b39779a54f000827a250bff00dbe9cb7162d81f6c942b719f9eb973ac7d4652b911622396c517c6e9c7e5f839c049855567fb53ae84579388e3c87af420272558c686209fd92fc339a553f873995932d9dce52f5e60cc0889c3283f94a0d2d5d011154d9935e1dfbb7e747b393bdd8a84f601adca56d4ac5e8e6f28100a7d5522de50dbf1bd7f5604fdfa660a58dc681b4b230abbc4f594a972a73456de1b7f48975cd03313a80074f5d6701db61860f33dfcc9f06e313e8881c385a50de28ced014daf702f01c45368419b73383008b9191293f59fa87a1ceb0cee64d486842ed7c289dca3b3f2e261df644de0f739079ba5ea195468f0693a995dae8e0f7e4611196824f329fc803bc3588d7d941d1fe86a3ecdb3eb8f6d4066ecee371f9a14e5bd46a40b53e87325bab7255099b4fe7f7b09eddaefc6582feecb8dec02b5e58d735a927d052e263027fa879fceb852b9e08db4636c7152f272a43ae4037c50210e90caa3e008fbfa98ed42cd425259096fc06644edab9b768779dcd892747f18a9cecc6aa31dc27d3f12a540447653edd5bed68f50da71b7992434b74d0209746f93ea429691fcb99da0ca32df822ec4332f7eb4bbe6d2111ac84a55932b3e173e388ab96a5a8a17c7d8b8131cf566e0335b0c4a37c5ae24e73c81146031295b69ce3032fa8e4c7616558179cc561f14864190d458cb82370749d595966047de698256126a4ca23a6bbd39201b8649fbcd387474ecf5b9f732e65938fe393a2a1269b06b9b49c5d8882d70776fc823da5842d812be2a65d2f5ee0d64f8258e761e6f2d4c1a825963b367d70b9e81b46fc25e4804fe9decf3aa0e47f1eba573a24f0e4f7b8cf8a886c7ef4175bd317709feeabe46df9719e7d7a4bc2c1bbc15a58b5332ea558e160f5d3b7aa84fe54ea7a24bd8e394ab794e72db7946780272556be33b7f32a0ee651c013d8ed3b5d75bc1c4826dc94f9e3711c53be3bcdf361329544f2993a189b6431a6dda8b81cb1b7c3a69ba96c1ac84a55100c4985cc85ce272e8eb5a57c563a7ad782664d561c3400e779317122d425c9c4193414bebd4d6ad31ba916448f65e9a7ca1f856dacf9d88b695410c8491a759d2c0304e8368b39cf502d0abf7233b1ba9671bc422ce182833ead52597481ea3ea26a2cc35e12a8c83bbb263202d5e9e7a5bb8ab2a5a844d596c24fdac423981fc4dc4291944ae476d59c9a31a05f79f0fe4b39f145c4fba857fa553a17fb2d5f941d5dac8dd3dd07e48eabfe5b98f3c41e7a84986dc3a7a3bb0ed2d4232cffbc50f167d58fb52fa3b357e76430d7f0f1aff6e2d51ea8f5b98bb66c5b5687821f33b9b6c2e407ad0e8140c4d5d4f1739167f8d63284caf4a43688473cd97bab401218fbb2ea13be81bbc05a81042a02eb1843bd46ca535e778e207c79ce3fe511a55d21bf20b24bcdfb43fa62b3469fae2ebd61e362d5d663fb2c08cbde5df9d8cc1faaf6370b5328ffccde873849299d61477a9fcf7c5c96fbc51b24c0f2cc6e39a46f4a9c1f5214f2cd06db62a37e2c6f477ceac0b92eb882d7bcd1fc3721a89745473eb45eee9a4fe6ab323d28f4db957d0c5dc1ed25ebc194f744a2cfe98474868e6acf5641ad454b3626ac2a27a9db416eb1763935eaa5612e43c49e8959ebcf5133863e98c19618e936f33952699fc224f41a4e259b40228047ed6a17cf4f3a42dc76df1346acb0986984f1692b5ed28f0825a23094ddbb8c1750e9035b1df2166f142e7f179473098ed73acb9ffb8be530542f31de88d6677f805cc30ccc0b60787e61f9d195ceacf07a35d979f9c3521f23671f378a6cd58ed2b0620ff7e2def5025f878d70008744c6a53caf325293353747c94c5ddf12e3a42686f97adc4db62b5e2e91132345963b7292fc9d13b484f75d8da000000000000000000000000000000000a13171d2127", + "raw": "0x50f914be826d6180843b9aca008477359400830383209400000000000000000000000000000000000000010180c002b907a05424000ae9a496294dd6b99046cfdbb235ae71031b379ce274c13b0c96411740cb61021a5390fbe8fb56b642b4e5e5abb7aeab143e0037f8db283b9f2febd650265ed6b05f1b867c124aef245c1811422f92414447fd0b20844e0f1b1cb4eec052400aad52b9d773aae0015c0c390bfdde3d367bd8ef9c3c73bca3164b9d418ecbb2d25303bbd12739a858c5fac4cbfa0203b9f3c319e9bc89d17a7a244b57d6613b5caabdb528f077eff9727015b9c266d777c0ba11920118c7ec4dd59b380c40e361a5b23ce04be4c61e12a1c21e091fa0d890687cbf588944db3e34253c75cdf797378de79162e0b4ca309f550365a289f652dd6d559478912cff70a5417589f73f14640970694d7b5a6bd8f000a65c632f0326ed3d128fda96dbea68cb812634dd75e9f63813a5645336681378b6a63220c066550aba43a5b937131d41f08752d13949a115a74bf96fa1925ff4338e10df0301abe40aaa49e14a1a1d58eef005a0f1d0299267002cebeda20cadcea7419cd0c365c53aede1aa36efaf764d3d36169747cdc8ee9a09e0a0ac6bcaeaeded0cd303c965d705d1b91a8b35f408ad8a033b02ff57610bddbfa60e2114e53f20f8fcad15dffac6a494c3f4f631590f2be3422af14cba7c900c9c38796952e20c3069bea2ab54bf0edf9315903aa5cf68549f878eafcc77561b36f8b78d950871ed4914417316f868a2bc54c72d3c9929f0138a2f0cbccb7c4141e94bb8a7ae11f660861cbbe498697d7327709271460a75bd4e024de3d4d6fe5af066944c96ba87459fa948a95eeb61abbaf643190ccaa9cd18591eb6f249a6eb92db89fc95616d21b41d7d15424b80a750938a12cd57d50ef95aaf222025dc4d81df320d9bc32c608b1c5a1aac8bd14c0f7a4c4380cdd65c793a6287050ff4d609102fd91e47e7365fb55513aeca273618528c199f7bb151e9c11a0bf202147734d1be9d5d0e9318096fa567317ed9fa6a8efe201b915b9aa05ca0d19e15c9a80449cc130b398ebbac3d938f55eea8f74e024b0e33dfecdbea02b920ddc5b277146685916194bfa1f8ac7784c7ed76923d4ff9ed97d3ceac283f9b26977df0133c5fa4fb5fcec577bc152e926529f06ff50c204c083c0b4d6b8d474cf5cf7cfcf7acf76921225443eb0abf5e4c76d0a3f524243ee4e372e80ff0f76dd9d135f240114a2ebe6d69609b6c60d275f251d7dceadc600d18e0cf8bc8fa8392e61fa32b8f7481c4883e19d820b51af0f87d3f7faae44e3b908fc759c6de59361487d8e424ffbd662d57a68801110e9cb099214143253949cc479eaae0e321fecab90c63b06819ce3cf56fc2fc1419408075c658024a28950aa47d549bcdb8b5bc9aeab463466c7834ca7d73058c206a95a023f0c8ac95badd383e63041e1f0ef69f51634f5ce2f48d80f8f2e92f4a1fb5322930141fc50e1e20bd235a8b8d768d473b46711257d028e710f82f0b6bd923da05ca64ae805f708577e125b3fca2feb5656f61ded034eaae481a195628801c82db85345f9ffdc72c860cffe2264ba4be2a08fdb37a4f5f80276baba4ea637847335c89dbd35504389f68b2d61ea66d4eac5fd0057d9e757d929214a7d83daf2fc2b3f840e083792d20d772584b252ba955ae8ae8c36af648c59ae0b25d3bca19413fbd749077b6969db5847409d13e4a67387e59116fe3836a733f3253d47f9919f49618fac8edf5fd711a4239447655d6c40f479f86ef3c9d4dc1a6f9683a3f1bc5c9730025e76ea1588d43494f59823f42c207e34412f73c7e2a126501b8fb810f12995c213063d909a5a9c2653d3511ceb809efa69c638f4c977d46a2a305cc831ecc0feebf5d9356ede6c780da78fe2ad683b3312282d5142612c0d1f85108de04de5c3d5414b62826d5b75f8887dc2d932c40f306c08e5d4f69ef4d344fe4317552df9890d0961e3d857bd9b2c5b44536d8606f62f66d14ddd43b0e5d3379cf66d664616df12b1c62385a57f6a562c34e120b79d64ca39d8b23e1e07b2c03910d711f09df5b54cb0e133dd751bea7832fdb38de2f1dafae69fbdf82b6887ff0a92940299020a835b958bb01b25b8699a0846614cb256a6621ef92e4a0947df9141ed4f91eca527aef25862158a8fa712dd60dda947f6a16e077810e29542a56f9244c34a73454b9ad0d8e8c40bd503efe12c4e5bf7d0ff8e6ab642a039f4e8b575d33c0c3de77a1abfa60b0252d7a549dd791d9630c8b848988157608448d77938bfb27beaea8f9b4a259263797c5b2fbdc7f469b2769f7dcb7b9478cdf5f109322eb2f0a83163469b72d8121fe8e01df227563cbd941a1f63961e2a010c6322a812a014279583a0066492a17d1a15c07024f6b8b1561041b3db608ec1c7475ce4d086e60523e85d7a955841558a35535d6e52cb166669a69049646b94d2fdb901ffbb1446a2d7f58696bce000ccbbb6942b0ad6480d006602c228218d3a2f0bc6a5d5c73acda9fc4b0b496a7d527050f8d77b71641f030368e9494bfe8e9dbf6dd4040426da1b0423739b40450273f4a8d551637e5fe3ca8d54fc476e6278e75cebf4a4ac3ac8ef3807041c4b274568797c8caaffae7df08c6c158d92411db981ea02cc212064c3ad6a9cd1cc02087acce5ceb8d7cddaec429d199c3d90670288be6e88e6826d1f6c417df5f35139c71a62c0267adfce7cb3aa49e827165b28c8cc157a691cb52ef103d8d7ca0ebfc628904d0b2d365dd3401b620d6d93cef670e2fb90ced33fc1486a0e70aeb6fef62ce5a0dfb51fcec12164e4024b0c49ce8b65e01356d80a9571af8f69a9c7256ed549d699a31ceff21c13c482ee0c5759f96125b0099495feacf22a001b2c887b107a9ca9e84de461fbc6e143566de56c710156de5b5f4b7ffe29c0124c1fbb6a792110284c9ad713d89bbb5ed444d09408c65a9f74c5f6c4fd281d31738db82913dcd1ac1fccbba24dc933fb9a8e6c4e426fb98590d7da0252c34d866c114526ded1c9d96daea12ecbd8f2a44531dfb72f02c02b267edf0560b1fb06b087bb6ce02b2922d92f81bb7da99b90e4a2dd68aa858759584490be602369dd606a510b6228e3b941421a3006a697b79866cae011d8aa496de4f3bfffdc0a087d01323db849f6237d7ac476d18bb417f26a697388b4c0a78533f3dd763398719c9ee5bf0299786fb8c4143af8c1195103390d4494b735c06b5815c454dba2fcdd27d214c48712609ffe7ad7c082e835d7477de2358fb3c4b5162027f816ca85aa4a46c25105175e77c8e5394db6fb3999c25ce578f066329182b28fd5b68769cb07ebc67e47a537f6cb62bfd18af162113a4df7f8908e0ce953b6a9637c850f24de0fda239c25fe4352f3b381fc270384d51d1af1ef0dea8501f98ea71f26de97e98799c4b2a316a216bd4af4861ad83fa4570532029564581bb35ac543355ba3aa246b59c6a5d9a91b938f3c4f0ad6d6f567fffdb6fb78402ded5fdc544a0f5fd87e4677326ca003dffdba8fd390487a6469991506a18f376b12db5be3bdcf4a4bc2f5b34dd8f7066bec3b40a6502f414eac3cd1ed43431b033757e86cca57691b0e1f7eec68fad9423f8b0620aa94798546bc878cf29d74ae74af5244ed9b97107fb83abe25dc160ec05cda1c50b76db981aca781868a7913a3e7c98aa5a3ea8bc81270e6f565138dba33c9c7e887641fd3dafd458b9c64600151038db05725a976950307c662c2eb668e3067f943b9bfd805307729b39ed77309fd5e67ecfc56cc231057a6628fb6f528fb969378529dea2c58fa0b4d791ca591ced733e8cf93a8e19907538f45c2618612648d3e1a78492afc154b7bb0285aea97d618e74a74530b492c66c6bd31557cdc55476b3f163196ec8e87f110834ffb8c232dc77cbf2f7b490f520b3b328af44fecca860a19bee9af6a5f69f63487d7dc6b7bf1233c4735522fedd475f905f044a0a7f658a7a378958cca56a163a343a010f4b65d1bc38cd57d08e0f887293fbc106ad7b15aacca6d51558cb8478b119acde04a19b007802a8e9578121304622aee7858d1794ade88973d6fdf981ebabc98fc417d765c075bf8f76b9781dff7c60071878027c057aade8eaf820186035499e9e5fbf8791e6fc0a0e49047af312a8b1b1e80628dc4db4f45842e19096a54733d28028203aa668bd8655631a01c000c956c32ff10572fdbc95b2f26d09fca84c093ddaa122ad93598c03de9273873ece5096648a6251a27e993ec7b6ea4f2181c09bb06852799323f3e993a4b7461439f702cb9df183fcaab11b8bd2ad391924d5e6ef261fea01c91cdc10d9345c290dfc3c040318d11419563d407c8365fef3dd31d8f9d7d338f5f2cd00433d1d06547ae9c650d14d9a7e5b683f0458e7a909d90d4a57201ca5b8753c13bda3591f9cadffd0987d1c7fca1c5a0cec1e13c612d0390d7c0e2f422c97cda29959cd7b714fbeaa5da7b0bcf911c2744a9a25c7d49e93342f61e10a33fda80fadfed2668bfab8767ce80480093b4845cd5ec83082e8f9ad63236743e72842d1a3226640a549c2c1d002a176e2427b2ae612dc272e3d9fa80a904eb8f93f494a52706346c08b06c9d1d8a61a9c7112c0933910882f0da6eea3c389f4faeea51c03394eab4cc02056d704b8839afd76f0839be5ffdc873b88f9a755be6f0229b0843839a25d63c18da89be1c5da930a101913ffba01fd00f2a447d5f58ae8f21554feb47f42d40c32158219dbbb1e5e96ab3dc26cd6a435525c265b65b0bf48d68e9b3c9178a509833aa47c23e63aa9a6f74bef1e4ef863556b11c014b85ac7c157f1e64531b676eb28c68e82e0089d2bd798213c836cc354d4883dc0b607456ab7f894f0a1f73356fc05a5c97a9cf3b231890c39105b751f6fc54063a08f3d3a264ab90cb7de1d0e2f6acb92302cc9b4bb512e720e6ff8343004028ad223a70d395c5f974d3ddd380f798e80edb4b13555c3be0cb1a500e19a8b1b05f9cae85d7eed756ebcfa57828f1054296ffa48d426ceb83c69ebe1b983421f42316ca6f50bf8df0f4d4aeef85005638a304d88764ec26366a1437867c89800aee55ba428e0c07542e123d748c795560153007f768b20bb057fc2643b7db992c3b9cbfd88657b17fbe8a783da2050affb518cab4226cdf28fa97f48651bd142932835f061f8642e79d1f7ae8ff8665aa85aba24a850b2042dd37e61e665a451f17cbe9d57ed5ecb1dce9ec34c576762929dbf46964de7c44c9f6b10fcf52b48649ded2d491bbe4bb6ad578cd31cbdea6df8342dbb7f33857617250b014fc6d887a448f7a5cef25ff69dbc94733bfac1d5f8593af7fbe4759d23ba8da1f405ba179c96d8ae49eb760446d842f0d61ab08508a3e31e4953e13a1b197d00644303e8a9513199583709f41757740a0dff347c3859d3a4ec391481af349019f75ccfdba111a4c338fd8283733115ce7c114111abb157c1a5a84f7b39779a54f000827a250bff00dbe9cb7162d81f6c942b719f9eb973ac7d4652b911622396c517c6e9c7e5f839c049855567fb53ae84579388e3c87af420272558c686209fd92fc339a553f873995932d9dce52f5e60cc0889c3283f94a0d2d5d011154d9935e1dfbb7e747b393bdd8a84f601adca56d4ac5e8e6f28100a7d5522de50dbf1bd7f5604fdfa660a58dc681b4b230abbc4f594a972a73456de1b7f48975cd03313a80074f5d6701db61860f33dfcc9f06e313e8881c385a50de28ced014daf702f01c45368419b73383008b9191293f59fa87a1ceb0cee64d486842ed7c289dca3b3f2e261df644de0f739079ba5ea195468f0693a995dae8e0f7e4611196824f329fc803bc3588d7d941d1fe86a3ecdb3eb8f6d4066ecee371f9a14e5bd46a40b53e87325bab7255099b4fe7f7b09eddaefc6582feecb8dec02b5e58d735a927d052e263027fa879fceb852b9e08db4636c7152f272a43ae4037c50210e90caa3e008fbfa98ed42cd425259096fc06644edab9b768779dcd892747f18a9cecc6aa31dc27d3f12a540447653edd5bed68f50da71b7992434b74d0209746f93ea429691fcb99da0ca32df822ec4332f7eb4bbe6d2111ac84a55932b3e173e388ab96a5a8a17c7d8b8131cf566e0335b0c4a37c5ae24e73c81146031295b69ce3032fa8e4c7616558179cc561f14864190d458cb82370749d595966047de698256126a4ca23a6bbd39201b8649fbcd387474ecf5b9f732e65938fe393a2a1269b06b9b49c5d8882d70776fc823da5842d812be2a65d2f5ee0d64f8258e761e6f2d4c1a825963b367d70b9e81b46fc25e4804fe9decf3aa0e47f1eba573a24f0e4f7b8cf8a886c7ef4175bd317709feeabe46df9719e7d7a4bc2c1bbc15a58b5332ea558e160f5d3b7aa84fe54ea7a24bd8e394ab794e72db7946780272556be33b7f32a0ee651c013d8ed3b5d75bc1c4826dc94f9e3711c53be3bcdf361329544f2993a189b6431a6dda8b81cb1b7c3a69ba96c1ac84a55100c4985cc85ce272e8eb5a57c563a7ad782664d561c3400e779317122d425c9c4193414bebd4d6ad31ba916448f65e9a7ca1f856dacf9d88b695410c8491a759d2c0304e8368b39cf502d0abf7233b1ba9671bc422ce182833ead52597481ea3ea26a2cc35e12a8c83bbb263202d5e9e7a5bb8ab2a5a844d596c24fdac423981fc4dc4291944ae476d59c9a31a05f79f0fe4b39f145c4fba857fa553a17fb2d5f941d5dac8dd3dd07e48eabfe5b98f3c41e7a84986dc3a7a3bb0ed2d4232cffbc50f167d58fb52fa3b357e76430d7f0f1aff6e2d51ea8f5b98bb66c5b5687821f33b9b6c2e407ad0e8140c4d5d4f1739167f8d63284caf4a43688473cd97bab401218fbb2ea13be81bbc05a81042a02eb1843bd46ca535e778e207c79ce3fe511a55d21bf20b24bcdfb43fa62b3469fae2ebd61e362d5d663fb2c08cbde5df9d8cc1faaf6370b5328ffccde873849299d61477a9fcf7c5c96fbc51b24c0f2cc6e39a46f4a9c1f5214f2cd06db62a37e2c6f477ceac0b92eb882d7bcd1fc3721a89745473eb45eee9a4fe6ab323d28f4db957d0c5dc1ed25ebc194f744a2cfe98474868e6acf5641ad454b3626ac2a27a9db416eb1763935eaa5612e43c49e8959ebcf5133863e98c19618e936f33952699fc224f41a4e259b40228047ed6a17cf4f3a42dc76df1346acb0986984f1692b5ed28f0825a23094ddbb8c1750e9035b1df2166f142e7f179473098ed73acb9ffb8be530542f31de88d6677f805cc30ccc0b60787e61f9d195ceacf07a35d979f9c3521f23671f378a6cd58ed2b0620ff7e2def5025f878d70008744c6a53caf325293353747c94c5ddf12e3a42686f97adc4db62b5e2e91132345963b7292fc9d13b484f75d8da000000000000000000000000000000000a13171d2127", + "hash": "0xc7903f14f8aa0ffc09cdfcd433e20f07ceaa63ab9b56b84ba41fc8dab7204952", + "intrinsicGasEstimate": "180176" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-3.json b/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-3.json new file mode 100755 index 000000000..5ccfbf6e4 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/valid-ml-dsa-3.json @@ -0,0 +1,28 @@ +{ + "id": "valid-ml-dsa-3", + "expect": "valid", + "alg": 3, + "chainId": 28001, + "publicKey": "0xfd3c43f5fc7807747a73e1d8e78cd9e611ad6bbba9b264534594174b49082aeab827927b335526cc50c2f0368fc666efb79c34af8ee90427d1718736acaad47f5959b9b26457619c07c2dda553d55a7498e30a37c92909f6b37c246dca4e8fd24d4cccd811396d276e5d11f1e8d14bb9eb4d5ec49798202422edd57ea4d8c0e8c6388e9c93a0ff2e52f7ca2303e40300c50c926a7da22919be462e2dcbdb3ec235b14290a282ee76a04f4bf7c5e2ec5c8fc0aaac72ce4f8fcf0d42b9fc3c4049ab6dfdfa12623d89c0d96434a8e13cb6f79ad6f4a8102f9a0bfe582d967372d8928ff9d7d7393b22ec1386ee91dd196eb9c349a6a12f7504e66a096eec0a8ae98e62275f6b84fb40a81a390c6ef0102c8fd2c11d303745b8fc49e638e6f3004961724a977a18d81efc67e37d0d44558e28cf9015dfa08eff82004c4a53dfa40c2451fa03a987f70c855dbee37e36480863044165e6d46d4c43278091317beab6f301d61c8f54f94ee88fa358c9aed6e55b80b4196e79a3d7251ede25c4baef8129882a69789df3a8262941199ded7bd381de00c257199c18e9086d9ce3f72c6d95c0a4d109a3a15474805f0dc06649a16a7805e8d74bd1af7658f5f9ef726d560595ff9f072d4cfaaf61283087843b904b0f5670ca551079c759d4a2839a71505e007cb5d49b0437b87a080fab5e2efdedd1d01f0f1ab72f0e6129a2525fc6e9829b56ce9d9f287a5bd80be8b1556e4ca82eafc60ec22315448768a72e45d4d956c16ee48a0658e307f81ee0f695f1b1b747d1d533d8da720f088b64608b1edb2d4d27247b2cd35e3d94e1256a3c5c944bbafe07b55ca74df4ec0b869733ddb466717a16e98af4ec310d046c90046c024fb33fbb2ffbb105d41bdd0e0af27b1239aa4d92b6ef8d727e51372fefc3b5c8bc6eb585a0ae2dd9970009555c2c2ced5e5a1e97c659565b6139dc4f3bae788e21f9658affa8fdb6f4733f7fa83fefab91a030f8ec976b8263c17abcef46dc22456d5347eea7c30dd25bdc3caad7cb2010f06573d56b6e5d28e6e847d8df8f18d6a2655ea66fe3c8e7e4ef192b5a8aeb35f8469277657b77155142c7b1653d5eb9cf9c4d69bbc5746e0c1876e330f9016a2f5343ec60b2f35ea380169a2bdf102888e6aae7e797d0bce73834f418018e8e55492da8236a542a999d9eea55bd52ee2e59feb0329d716c78c0bfcd79dc27cd9639399d2fd99d2fc9c4900ad60bdb8221501038ec4baadd2ac4830b2bfe1e20804c818c8e089661e7d842bc4e566fa0bc2d7968a44f8df0d4e88e494fc7bebdb695d3a8edf6a2703817b0f8c1a55569ac4a8ff0931137f075797e9744135a3fec6c767af26d4592a9022271a4052b1f1f24f072bd5ceb1d19e02b0bbf31251a7bb8b723bd3da02f59ca1c0c91bc10896970a1e0f8e0fd5b755da58d70be8935f65661629a9f833b35810113ce80125f8ed7a031cfd5eb1475b597856b4ce7629a9429d840a3457bbd70c05c73c6ce84dd59f917a24d06ca8743225ab8c266e209fbadf57cdb587df96eedf54c04fb3f83ec0dddd1d8bf9051c6de4db3aa099f1779f3f30f61f432e5c8f6b7ac4ee6c6dd6fce667556df155ddb2002735fb7addd8acf74863ccfe04a3088317634eb47e56b18c79f31318ac5e448a9094b5c2c70b44dbbbff7c235cef4701d504723b032726d009c6d7f527e645a23fc1ab478e6e2699211694d575bd436d778e7ae53868c63dfb78f591d82b979585cec8bbcde61f375e783e97e8f787fb392fa4f0bc3e9010aa9ec3cf6471bb16355c3ed3fdf2ee5b95ade86371d60fb0699a851770a212d0e0eeb3f20df78ab180343fd79a9d04d8dc56d9fe3d820b27d98d12275a40d270f4181aa1a18305c8d3469a954b2e85405a394684cc234702a6cb01c04ccc941a4392cf64ba31bea700d339152fce6abb0dbe84823b8d3b18258a29414fd52c91ccbc198e101287b79d8bd0e5f4b05a14a07055e66ea37d781934840a204638bffda400113bb1344126fe1c2ac1e57bb861c3d35349b1fba0c11e12921262ae52fb2e0bee444f8197e2817b9356e10af67e794a7967055936bfcb51f4be6fc5602a8df97ddcd73afe83c02f00d4f1d8302bd2e826d4c50fd3ded9a74debd0e807b694e912a8a3a800f5b983e171898874b77ea305ede4abdf0db5ca84a8a60b184374c08066537b08d42a609b97039ff8905bccc4454188b051c5d1e574e1e8b74cc5cbded064a5374c55f17002ee9b17447fdc324a12e3f2f414b491cccf20c9f98820461f4c7d61355a30f1a6cbb2fe7403b90587298fcc9500519451e44225c750b8b32a649ea288eda389e596390a5386652dea5d0e096ee270bcab9da0c3c4ba464f44172732a748e339cbfc8f0c1ee3187225e2fb29e67ffbd84df8acf759c817d628e03a245e9ae0cf00939fa12964e8dc124659eea8798b097ba52480532fa11194e4623ff63f6cc1d17c7080bb2c1459fe8cc9b197b89ba91986b7bfa61e514bf5c60f981e63baffd9fce44af87ad73fba197e46790fc03f8a46aa6d7590f47e08daedd7f564685208ee87da84b04b11cdc0c020bb26b0abdad3c1340649130e26af9c7651533313301e8b517a84c807d86a4c0cff68566d34da4111d67bdc77ef5f49ec7d83af24a143bceaee020acce02499c725ebc341a86d91c7f63dd962ffcc09fc0b5673873ee55cea4bba69b5058e4b364fb3802832d5118774790dd12eed78330412dc877cc034309a7e292ebee955a431fd46faf7884cf3bd5ab03d02b8784af2a84bb907ba5f021fc332f638a2d4b6451ea0a2cdee6ff1621d698eadfc99d6f405003f300e321a9e80ed3b577a899fa7dd891b53cab8acaa9fd3ce02640eaa75646f134c190817675b9e4a688d0668528fa3b378749bb6b1a0bd16873e89dfc927dcf568fc3cf94ac49d289ba1fb9c58a74574c8fbac321db256bf919e9432d6a8ae9a0dae900901f436b13d0c2b753a5eb6fcef03301d7faa15ff32ec0730335b13394bff66ea83a7043f9e1df5962671ff2d2759db234a4a4fa47fd3a9359bb14ef5b5fc398836d42afcc5d5f252b1b061afc6a0815b3a7586d25eed5ee52c56d2389b8f2438649ee652b431d3cc4262c6e5ea1c0ccec21aa6123e88b4bc933098576bd78cf5bcbbc278ee682029e05e91aac2043ad3ec1d3d97f6ebc6bd5faffa5bc71328cd4351bcb9a0d8d1ea9253b97b08c8c53b20e29703568d5d7dfa2bfa6aeb3a93043e4123116a125311695a11c8538658210971d7763ed7870c1309893909e306df22fe968612531e58a91d19dfe2c658ade19c8e0900c779af8ec333d19552e42cdedbe13ff85d99b10baf8daf70951290db56bc7ea049e6b468b6546a7f3ae77c2e14770eed1ea345f0d139336af4eee686ac2e73bd4262cb802e0173fb872a77cd2c0f3421c497b0260be79ae29d04d9a9da9d7bc101ae3ec9dace1133332f05b7b82aaee577c06c0d2a8eaa8a96db8b899cb3240cc4dca4f8eab513ad5b3529063b5df3664dde0db1e0ae5c29e69f011076fc7edc4261d043f38f1c68645466c9a5e685a07393b7e2f8f74db86742ba5ac089b45a42df3f943842747674c1653aa2a8ef282f64e7ec2ce1fada994288a5f9b95da4bc083ea008308", + "seed": "0xa8af8968099758df7640e2c9f1713fe31d70766e2c2b18bc2ae82f5b1e1e8fa5", + "tx": { + "alg": 3, + "publicKey": "0xfd3c43f5fc7807747a73e1d8e78cd9e611ad6bbba9b264534594174b49082aeab827927b335526cc50c2f0368fc666efb79c34af8ee90427d1718736acaad47f5959b9b26457619c07c2dda553d55a7498e30a37c92909f6b37c246dca4e8fd24d4cccd811396d276e5d11f1e8d14bb9eb4d5ec49798202422edd57ea4d8c0e8c6388e9c93a0ff2e52f7ca2303e40300c50c926a7da22919be462e2dcbdb3ec235b14290a282ee76a04f4bf7c5e2ec5c8fc0aaac72ce4f8fcf0d42b9fc3c4049ab6dfdfa12623d89c0d96434a8e13cb6f79ad6f4a8102f9a0bfe582d967372d8928ff9d7d7393b22ec1386ee91dd196eb9c349a6a12f7504e66a096eec0a8ae98e62275f6b84fb40a81a390c6ef0102c8fd2c11d303745b8fc49e638e6f3004961724a977a18d81efc67e37d0d44558e28cf9015dfa08eff82004c4a53dfa40c2451fa03a987f70c855dbee37e36480863044165e6d46d4c43278091317beab6f301d61c8f54f94ee88fa358c9aed6e55b80b4196e79a3d7251ede25c4baef8129882a69789df3a8262941199ded7bd381de00c257199c18e9086d9ce3f72c6d95c0a4d109a3a15474805f0dc06649a16a7805e8d74bd1af7658f5f9ef726d560595ff9f072d4cfaaf61283087843b904b0f5670ca551079c759d4a2839a71505e007cb5d49b0437b87a080fab5e2efdedd1d01f0f1ab72f0e6129a2525fc6e9829b56ce9d9f287a5bd80be8b1556e4ca82eafc60ec22315448768a72e45d4d956c16ee48a0658e307f81ee0f695f1b1b747d1d533d8da720f088b64608b1edb2d4d27247b2cd35e3d94e1256a3c5c944bbafe07b55ca74df4ec0b869733ddb466717a16e98af4ec310d046c90046c024fb33fbb2ffbb105d41bdd0e0af27b1239aa4d92b6ef8d727e51372fefc3b5c8bc6eb585a0ae2dd9970009555c2c2ced5e5a1e97c659565b6139dc4f3bae788e21f9658affa8fdb6f4733f7fa83fefab91a030f8ec976b8263c17abcef46dc22456d5347eea7c30dd25bdc3caad7cb2010f06573d56b6e5d28e6e847d8df8f18d6a2655ea66fe3c8e7e4ef192b5a8aeb35f8469277657b77155142c7b1653d5eb9cf9c4d69bbc5746e0c1876e330f9016a2f5343ec60b2f35ea380169a2bdf102888e6aae7e797d0bce73834f418018e8e55492da8236a542a999d9eea55bd52ee2e59feb0329d716c78c0bfcd79dc27cd9639399d2fd99d2fc9c4900ad60bdb8221501038ec4baadd2ac4830b2bfe1e20804c818c8e089661e7d842bc4e566fa0bc2d7968a44f8df0d4e88e494fc7bebdb695d3a8edf6a2703817b0f8c1a55569ac4a8ff0931137f075797e9744135a3fec6c767af26d4592a9022271a4052b1f1f24f072bd5ceb1d19e02b0bbf31251a7bb8b723bd3da02f59ca1c0c91bc10896970a1e0f8e0fd5b755da58d70be8935f65661629a9f833b35810113ce80125f8ed7a031cfd5eb1475b597856b4ce7629a9429d840a3457bbd70c05c73c6ce84dd59f917a24d06ca8743225ab8c266e209fbadf57cdb587df96eedf54c04fb3f83ec0dddd1d8bf9051c6de4db3aa099f1779f3f30f61f432e5c8f6b7ac4ee6c6dd6fce667556df155ddb2002735fb7addd8acf74863ccfe04a3088317634eb47e56b18c79f31318ac5e448a9094b5c2c70b44dbbbff7c235cef4701d504723b032726d009c6d7f527e645a23fc1ab478e6e2699211694d575bd436d778e7ae53868c63dfb78f591d82b979585cec8bbcde61f375e783e97e8f787fb392fa4f0bc3e9010aa9ec3cf6471bb16355c3ed3fdf2ee5b95ade86371d60fb0699a851770a212d0e0eeb3f20df78ab180343fd79a9d04d8dc56d9fe3d820b27d98d12275a40d270f4181aa1a18305c8d3469a954b2e85405a394684cc234702a6cb01c04ccc941a4392cf64ba31bea700d339152fce6abb0dbe84823b8d3b18258a29414fd52c91ccbc198e101287b79d8bd0e5f4b05a14a07055e66ea37d781934840a204638bffda400113bb1344126fe1c2ac1e57bb861c3d35349b1fba0c11e12921262ae52fb2e0bee444f8197e2817b9356e10af67e794a7967055936bfcb51f4be6fc5602a8df97ddcd73afe83c02f00d4f1d8302bd2e826d4c50fd3ded9a74debd0e807b694e912a8a3a800f5b983e171898874b77ea305ede4abdf0db5ca84a8a60b184374c08066537b08d42a609b97039ff8905bccc4454188b051c5d1e574e1e8b74cc5cbded064a5374c55f17002ee9b17447fdc324a12e3f2f414b491cccf20c9f98820461f4c7d61355a30f1a6cbb2fe7403b90587298fcc9500519451e44225c750b8b32a649ea288eda389e596390a5386652dea5d0e096ee270bcab9da0c3c4ba464f44172732a748e339cbfc8f0c1ee3187225e2fb29e67ffbd84df8acf759c817d628e03a245e9ae0cf00939fa12964e8dc124659eea8798b097ba52480532fa11194e4623ff63f6cc1d17c7080bb2c1459fe8cc9b197b89ba91986b7bfa61e514bf5c60f981e63baffd9fce44af87ad73fba197e46790fc03f8a46aa6d7590f47e08daedd7f564685208ee87da84b04b11cdc0c020bb26b0abdad3c1340649130e26af9c7651533313301e8b517a84c807d86a4c0cff68566d34da4111d67bdc77ef5f49ec7d83af24a143bceaee020acce02499c725ebc341a86d91c7f63dd962ffcc09fc0b5673873ee55cea4bba69b5058e4b364fb3802832d5118774790dd12eed78330412dc877cc034309a7e292ebee955a431fd46faf7884cf3bd5ab03d02b8784af2a84bb907ba5f021fc332f638a2d4b6451ea0a2cdee6ff1621d698eadfc99d6f405003f300e321a9e80ed3b577a899fa7dd891b53cab8acaa9fd3ce02640eaa75646f134c190817675b9e4a688d0668528fa3b378749bb6b1a0bd16873e89dfc927dcf568fc3cf94ac49d289ba1fb9c58a74574c8fbac321db256bf919e9432d6a8ae9a0dae900901f436b13d0c2b753a5eb6fcef03301d7faa15ff32ec0730335b13394bff66ea83a7043f9e1df5962671ff2d2759db234a4a4fa47fd3a9359bb14ef5b5fc398836d42afcc5d5f252b1b061afc6a0815b3a7586d25eed5ee52c56d2389b8f2438649ee652b431d3cc4262c6e5ea1c0ccec21aa6123e88b4bc933098576bd78cf5bcbbc278ee682029e05e91aac2043ad3ec1d3d97f6ebc6bd5faffa5bc71328cd4351bcb9a0d8d1ea9253b97b08c8c53b20e29703568d5d7dfa2bfa6aeb3a93043e4123116a125311695a11c8538658210971d7763ed7870c1309893909e306df22fe968612531e58a91d19dfe2c658ade19c8e0900c779af8ec333d19552e42cdedbe13ff85d99b10baf8daf70951290db56bc7ea049e6b468b6546a7f3ae77c2e14770eed1ea345f0d139336af4eee686ac2e73bd4262cb802e0173fb872a77cd2c0f3421c497b0260be79ae29d04d9a9da9d7bc101ae3ec9dace1133332f05b7b82aaee577c06c0d2a8eaa8a96db8b899cb3240cc4dca4f8eab513ad5b3529063b5df3664dde0db1e0ae5c29e69f011076fc7edc4261d043f38f1c68645466c9a5e685a07393b7e2f8f74db86742ba5ac089b45a42df3f943842747674c1653aa2a8ef282f64e7ec2ce1fada994288a5f9b95da4bc083ea008308", + "chainId": 28001, + "nonce": 0, + "maxPriorityFeePerGas": "1000000000", + "maxFeePerGas": "2000000000", + "to": "0x0000000000000000000000000000000000000001", + "value": "1", + "data": "0x", + "accessList": [] + }, + "algName": "ML-DSA-87", + "sender": "0xaee69521a942a58325bd694f2cc3d64752465d4a", + "signingPreimage": "0x50f90a4e826d6180843b9aca00847735940083045f289400000000000000000000000000000000000000010180c003b90a20fd3c43f5fc7807747a73e1d8e78cd9e611ad6bbba9b264534594174b49082aeab827927b335526cc50c2f0368fc666efb79c34af8ee90427d1718736acaad47f5959b9b26457619c07c2dda553d55a7498e30a37c92909f6b37c246dca4e8fd24d4cccd811396d276e5d11f1e8d14bb9eb4d5ec49798202422edd57ea4d8c0e8c6388e9c93a0ff2e52f7ca2303e40300c50c926a7da22919be462e2dcbdb3ec235b14290a282ee76a04f4bf7c5e2ec5c8fc0aaac72ce4f8fcf0d42b9fc3c4049ab6dfdfa12623d89c0d96434a8e13cb6f79ad6f4a8102f9a0bfe582d967372d8928ff9d7d7393b22ec1386ee91dd196eb9c349a6a12f7504e66a096eec0a8ae98e62275f6b84fb40a81a390c6ef0102c8fd2c11d303745b8fc49e638e6f3004961724a977a18d81efc67e37d0d44558e28cf9015dfa08eff82004c4a53dfa40c2451fa03a987f70c855dbee37e36480863044165e6d46d4c43278091317beab6f301d61c8f54f94ee88fa358c9aed6e55b80b4196e79a3d7251ede25c4baef8129882a69789df3a8262941199ded7bd381de00c257199c18e9086d9ce3f72c6d95c0a4d109a3a15474805f0dc06649a16a7805e8d74bd1af7658f5f9ef726d560595ff9f072d4cfaaf61283087843b904b0f5670ca551079c759d4a2839a71505e007cb5d49b0437b87a080fab5e2efdedd1d01f0f1ab72f0e6129a2525fc6e9829b56ce9d9f287a5bd80be8b1556e4ca82eafc60ec22315448768a72e45d4d956c16ee48a0658e307f81ee0f695f1b1b747d1d533d8da720f088b64608b1edb2d4d27247b2cd35e3d94e1256a3c5c944bbafe07b55ca74df4ec0b869733ddb466717a16e98af4ec310d046c90046c024fb33fbb2ffbb105d41bdd0e0af27b1239aa4d92b6ef8d727e51372fefc3b5c8bc6eb585a0ae2dd9970009555c2c2ced5e5a1e97c659565b6139dc4f3bae788e21f9658affa8fdb6f4733f7fa83fefab91a030f8ec976b8263c17abcef46dc22456d5347eea7c30dd25bdc3caad7cb2010f06573d56b6e5d28e6e847d8df8f18d6a2655ea66fe3c8e7e4ef192b5a8aeb35f8469277657b77155142c7b1653d5eb9cf9c4d69bbc5746e0c1876e330f9016a2f5343ec60b2f35ea380169a2bdf102888e6aae7e797d0bce73834f418018e8e55492da8236a542a999d9eea55bd52ee2e59feb0329d716c78c0bfcd79dc27cd9639399d2fd99d2fc9c4900ad60bdb8221501038ec4baadd2ac4830b2bfe1e20804c818c8e089661e7d842bc4e566fa0bc2d7968a44f8df0d4e88e494fc7bebdb695d3a8edf6a2703817b0f8c1a55569ac4a8ff0931137f075797e9744135a3fec6c767af26d4592a9022271a4052b1f1f24f072bd5ceb1d19e02b0bbf31251a7bb8b723bd3da02f59ca1c0c91bc10896970a1e0f8e0fd5b755da58d70be8935f65661629a9f833b35810113ce80125f8ed7a031cfd5eb1475b597856b4ce7629a9429d840a3457bbd70c05c73c6ce84dd59f917a24d06ca8743225ab8c266e209fbadf57cdb587df96eedf54c04fb3f83ec0dddd1d8bf9051c6de4db3aa099f1779f3f30f61f432e5c8f6b7ac4ee6c6dd6fce667556df155ddb2002735fb7addd8acf74863ccfe04a3088317634eb47e56b18c79f31318ac5e448a9094b5c2c70b44dbbbff7c235cef4701d504723b032726d009c6d7f527e645a23fc1ab478e6e2699211694d575bd436d778e7ae53868c63dfb78f591d82b979585cec8bbcde61f375e783e97e8f787fb392fa4f0bc3e9010aa9ec3cf6471bb16355c3ed3fdf2ee5b95ade86371d60fb0699a851770a212d0e0eeb3f20df78ab180343fd79a9d04d8dc56d9fe3d820b27d98d12275a40d270f4181aa1a18305c8d3469a954b2e85405a394684cc234702a6cb01c04ccc941a4392cf64ba31bea700d339152fce6abb0dbe84823b8d3b18258a29414fd52c91ccbc198e101287b79d8bd0e5f4b05a14a07055e66ea37d781934840a204638bffda400113bb1344126fe1c2ac1e57bb861c3d35349b1fba0c11e12921262ae52fb2e0bee444f8197e2817b9356e10af67e794a7967055936bfcb51f4be6fc5602a8df97ddcd73afe83c02f00d4f1d8302bd2e826d4c50fd3ded9a74debd0e807b694e912a8a3a800f5b983e171898874b77ea305ede4abdf0db5ca84a8a60b184374c08066537b08d42a609b97039ff8905bccc4454188b051c5d1e574e1e8b74cc5cbded064a5374c55f17002ee9b17447fdc324a12e3f2f414b491cccf20c9f98820461f4c7d61355a30f1a6cbb2fe7403b90587298fcc9500519451e44225c750b8b32a649ea288eda389e596390a5386652dea5d0e096ee270bcab9da0c3c4ba464f44172732a748e339cbfc8f0c1ee3187225e2fb29e67ffbd84df8acf759c817d628e03a245e9ae0cf00939fa12964e8dc124659eea8798b097ba52480532fa11194e4623ff63f6cc1d17c7080bb2c1459fe8cc9b197b89ba91986b7bfa61e514bf5c60f981e63baffd9fce44af87ad73fba197e46790fc03f8a46aa6d7590f47e08daedd7f564685208ee87da84b04b11cdc0c020bb26b0abdad3c1340649130e26af9c7651533313301e8b517a84c807d86a4c0cff68566d34da4111d67bdc77ef5f49ec7d83af24a143bceaee020acce02499c725ebc341a86d91c7f63dd962ffcc09fc0b5673873ee55cea4bba69b5058e4b364fb3802832d5118774790dd12eed78330412dc877cc034309a7e292ebee955a431fd46faf7884cf3bd5ab03d02b8784af2a84bb907ba5f021fc332f638a2d4b6451ea0a2cdee6ff1621d698eadfc99d6f405003f300e321a9e80ed3b577a899fa7dd891b53cab8acaa9fd3ce02640eaa75646f134c190817675b9e4a688d0668528fa3b378749bb6b1a0bd16873e89dfc927dcf568fc3cf94ac49d289ba1fb9c58a74574c8fbac321db256bf919e9432d6a8ae9a0dae900901f436b13d0c2b753a5eb6fcef03301d7faa15ff32ec0730335b13394bff66ea83a7043f9e1df5962671ff2d2759db234a4a4fa47fd3a9359bb14ef5b5fc398836d42afcc5d5f252b1b061afc6a0815b3a7586d25eed5ee52c56d2389b8f2438649ee652b431d3cc4262c6e5ea1c0ccec21aa6123e88b4bc933098576bd78cf5bcbbc278ee682029e05e91aac2043ad3ec1d3d97f6ebc6bd5faffa5bc71328cd4351bcb9a0d8d1ea9253b97b08c8c53b20e29703568d5d7dfa2bfa6aeb3a93043e4123116a125311695a11c8538658210971d7763ed7870c1309893909e306df22fe968612531e58a91d19dfe2c658ade19c8e0900c779af8ec333d19552e42cdedbe13ff85d99b10baf8daf70951290db56bc7ea049e6b468b6546a7f3ae77c2e14770eed1ea345f0d139336af4eee686ac2e73bd4262cb802e0173fb872a77cd2c0f3421c497b0260be79ae29d04d9a9da9d7bc101ae3ec9dace1133332f05b7b82aaee577c06c0d2a8eaa8a96db8b899cb3240cc4dca4f8eab513ad5b3529063b5df3664dde0db1e0ae5c29e69f011076fc7edc4261d043f38f1c68645466c9a5e685a07393b7e2f8f74db86742ba5ac089b45a42df3f943842747674c1653aa2a8ef282f64e7ec2ce1fada994288a5f9b95da4bc083ea008308", + "signingHash": "0x3ef7803edb46bad878a1a585571475b75bba9b66e2407b73c6d5794ec507790d", + "signature": "0xc74a08868ea0fdad9fbb1b485b793bce6e4fa945668b2351232a7c8a084fb2d87a5c83e7dced6bde3743617a7c4babcbf9381694b64d7e0feeb6615440e927a63293c6b695900b1e7afad1ae612c324a88e6761c3b6fdc41d18f514be1ba3a1ca53fdbcf8c19f95bcd60223abe52d07fd7c4114dad9f347cf122f6241429da7e598959c22692910323a0a699595398f518c58deea7159920d89e3e65702bc2cabea7e9ca0bbb7002fb7be5243bba6a08a12238ead443ff4394510d25eb279885d9112c44529f294c5a2bf493a74ba8f4e38744e632680b3ce055a897d2a5468ef52e6e70dc5af55a9fb83739f6cfc6994871662b8263f2e07e21a6514624909369e0138755165dd2af5a791da63c0604b68ff160fad82a578a06e76f62bb7e951b81d8fde2dade6c3a314eec5913151c16a93a5abd5ceb59ad96197a349721ab123b42f799dbde36d7965e0e5dfcf43d8d1ae13f4a00afd8dde36137d3de87f4e2c0366c18f4b3a449ffd9afc7c742c50456f6e642f7d09e86d5aef224b20ce5d8a2bf164484df8fc87daf69e459fc78c6b974cdb8fb1dccbd5290f560e3114302886e2828ad73ce71b06186254206743076c6af0c3d1facc36695dc28db1d026686b141247e1c7a9323d544b0079023cd2adedc0479ceefc8e0c34782603d0c27d18768eb5485a85bc385ffdfd25f735688a3b9a0c6f532b2a7989c751804de0163582293a17f635fdde14e9067f12929b079f89a53dfc87b986f89f718320ede83cf4086d0d095b24b66d5e3f1bfdb08b79cd5b25657cf2b20faff1d199c16bb7f631b33970b34c12997637447e4127db1bf580b339807637a86e0248cbcf8e1d30ae6fe053e2f9b7b3d0f9e3f4813af908b633560779012f9e06af00e252bb0df9f0caf7d1e82f8deb2ede21d13f406dd9ea69445d50844c95c921d8d1cbc8afbc5ddcd4157e65cbfbbafe2670e9146a5643db049a8d696f0eae07c3d4099447ef78bdb90fc05d7cc97bf9b9dee8719464ec6b9e6de866f73914a80396dea3900a9f7b43a47e648e20a9504da92c47ac65368813e5453e82020f8861aba2534346e6137e71adb28a5ff080365d6ea26dfc30ef5500d0760749d6e4e0f93aaebed544832308b19f72e92ebb8eaec2492c6ea7972fd359a8b67a1f4053bfb1a3c6fb720b5925a7a827e59b3bd0651b8014c77b25d61db17eb169cc2fa2442c82f68fb42200c59baa468a9fc92f13273ff071124f8b31e2b4b2517ee622d29489997ecb5676fb52e3002371c01004c214757b1f510091c2377a08d058209d18feb9b524a41712b6df4b92f2b14c583d3196749f367b3bbc8ab5e9e2615c511f23ba5fb1bac2ee9436dd8d162bd96f1fb663d2b520ba7e8ddfc2a4d549b63714654cfbb37ee1dca5f723139187ada8f8d5b42ad09ff196b70720d2527b4466d44f33cce486ef2e86311c75ead31a17b16989dc63bacf0d465379d9138df7ea2ebc71f4cc3b6662e24895050e2553dbc160a567d6722964a904d43bf2684206cee3562256e98addf3038e968cf6c09c921e2c89c9c249f6ba7afd20dd27587b4143f704f2738315a91c2d40c467111b4f3bae4f77bae402145e742ba83a527aeffca13ee2290988df882feaf5a3c24b416d59e06cf4f8832a016ce55419b7bd2028545557528a0af23f17942433e13fad089fdb79449bd9d99b0324b1828791249b6789a09cdfb6ec40c0fbaf8b28ea4f72d3df5159bea7a7965b94beb1bb01d87d76ae7ce47fc333fc152038ab4e7ca64a802f96f2e92bcc53ad9cae0242c622c99b2daf005e554cd6ba127991d84841ffe3ba0674eb7930509045dd00ab91a7c6acd2f4a40e7ffc9959929851e40d417f488a29f7bb5af3847a8caa5daa0682aea870ac8b866ccfdc435971e3d862c2f651cc6eb8a33fca313a56ab8228ee9ac7dce14ea3c3fba4f58c70888ae558d8cd632a2723ba54a3d538f4e20936a2ee543e9b2141e06095c72d4ee19908febf7c248c03a78655420da644746e2d508c31ceb0b648800d95dceec72f7576502046e5dce54b5a097f625001bfc92d6e4633b293cdfa63b1fca5de9e26d03ba2f1cf3647dbdad5359ed76bf702f0621c057dea3617af678016aa13360ebb02c6cb2fa0d3f137a1a3c639c989e12383841ab7ca5a84f84c08af4b85416ce7ec3ed91636a79add207bedf9dfb2ff626387f20cb3315502b2b06f361cbf6a51fb507598af41c5a5b9cd95ba1894ca372c5e1851e62a0d3d78dab6f92bd43ba6fcd71230b6cfd843d89268872b75e3c5b471db530b7ab5451dbe63fa0bdaa7d74907cb376643e129febbe6ce10b5dffbf323dc973f097d2081e06aad65e674c5a41bb81b80556fd78691fe6b5bfad47fd1b64db577f27f22f17973cbff3a7c4aa43569bbe6843d773a2f933f472650e88e0ec6643f87dfd37e7fba915c7386a130b8d4f0ff4d0e99a633d1f863f3e8ce4e1ac5e31438d89c3b6d5ace3aa6e14e7073164ea01e853958bece389316023127f9916297a47c5d6ab5513bab874c1ae3bf2850cfab9018cbf50a7febe03ff3e8e4e55ae5632812b6a147edf051b461bfe56f01a6ab571e0553e37a57a3a9811f4fda2e189d79b74215d6fe199595d18c6543c747572f8cdc61a53ce09d9ca96b43a5af5b56b53148dd4fdfc1e22c9958caa783f2d112d8d5fd39e6955df75d35c59a1967fc0d8d3293e39a6cdf82d6846b39a74b1a538372c266b3f12d7ccf464ff7e32fe54342994f51d344302b3b2e11eed2187a741eec99ef0a79a19a854c03d8bd3fcd557b9d8bfb35f0976da327fc7e8d95fb43db8e66be5b373385fc1b68099566c7e88aefe92c7c521d084c15c8d403d87bbc975e8d687e2a51e5ce53191e3db5bdc50f475853cda7cc5a7365c41035aecb61444c2a48492a600b58300b2805be97b4e9e30526e9e62bb3248a17c3809219307ca85351495c943a865359c783cf615a809c739cce0786c6045d9c8071797001434cbae571d42cef415e28ed6adab09ed10e0713dc1412ed80b8d26d549964321559137483c81b19203080b36abcd68e841f4c78b5302da79fd6e555f390322ae67e54c55749491889d79eb2982fc4428086bd1060c4113137ddb4dd7c9b690b802e805999d4f5127f66f6b1d397dc3509504e2196513b5787407b45b928cfc3c437523daa4f876dfe061e351cb3bad99ea205ab276c4f2a5ccee1027104f09adaf55cd282d4e9e44ac2b65f7e423da1cebb0ac70691347e7a7bd0de8bc9fb2e7a08afc0075a0e85902316cd6ec9a5802c51a6d65bf3251ae712ae0f66de6cba1e51efbad53ad7e769f851799caf5fb81ef35b4da814915dcfa67553f1c67158154707d16804be27af2115559e4758b313b9da4a1131718b29a75970b3f0a5e2f2c11a0a1ed47f238c145dc4fe9e8e963d8395c67dfa94a232b8133a0d953b05455f79e0bdff0bc3de9c04d93d97084ab99229622cfe3958ac5fda6757de1696b575f6250b441e6368386751b1d2f6007d254d152fe76578fbbe164af49cda805b9325f7ea47f5e18f3de1ce38006ae1bf027d3e354d6f923d8bc6286aaf9b9a7b9e7a7fbd36a31db0d88166dc68e7eb567d8164bed1e279a8810fc21656621ff7cb42a21ee04e6086924bb62dddd16c3343db69250f7ed95aba953202640bef18dfb6c00f1ee03c670a5cc6c0f3cd7cb006590dddffa6f19d450860e289f85edb4fb0dbbd2f992eebba09cddc1b20a3c98d8739ad1875a514b09b1f23cf406c4c55cc4266e0b8b283fa445849316c30bd19254e9d035756d2773cab7f5fd56d6d3a094a717ccca43251201cfddf80ba1aa0dad34f5a3acf8476b784fd53a1aff1307a7838705112650bd25dfea21b991d801f018a5dae26edb9dd5a0ab940a94b7bbb90fd1f30f9d1dd2ea3aad6d0a2a3c42fd2641233c7d624314c3a54ce616d2ca5683d04f6fc0924f0b667be32f4de8820f9cfab963a287a1c708857ebabed9b5bcc35d539ef9bc170636cd528ba86a620195134cacbc2b8e742376124b67ed8155ab53979e281f97b184c60355b008f15f45c8b7a506b1c1f511e4aaf0bc32fee27b656b01ed6afaa4053ed674a60175b6c89a77d42963111d0940730db02ff67534fe6a296e0e01e2db6b3f0fe9648286a0f3420cd4393163662751deed6457abbb370f83ed92e9da86a0181df13b8ef33e5718ce524a700ba5f2b40f3f973a67c1c412dc251c19e6b7ceb279dc1dfc36a3567e3a98a9d96ef52b0d0734f57bd9edebedd925167f230b1c81ca938e94ceebe43d2573735873a436331a8b76c1169c6a869889cb74e5d33721bbb99ec87f160c025f570f1d11c2e3ae6a52580785d854790139510179b003418dbcee1f4fd4fa39fc134521ffd7f29cee650472638dd04d8331ee439eaa32c57b56c4fd9c9ba87516a8236dc99b8d6e4c2a48e53a6779d5e13bbd73cc7917f0cfb8e231218bf33bc3c213599eb76476558f0e38a3979cdaad6ac6b03bd0ef0aefec634fbe0e1e87bd78123a19b7352326b9def856ecfc02b06622f94e8cb2a1cb6cf10d020f789a7db775063030f15b463f08878219636f2bb94ed11a3ed9689d797a3253809c7f2e0c60672e8476a9e272075c7f808258901e611c4d535a11bfe01daccaec3a26a187ab45a9fd0bb9a7ecf2e9c4aa3177ddaca1449f19f78ebe26be2e25bca012a10649b56899339f5418925648f3253bd716336dcf65e6b4f16d2ae51fed1acbc8335c103f721f46023cc2043f568ddb033aa5f2157e52b89eed4571cb523fcc66ef5cddc90679633c2a46f45f1a86c975db4f6f37f9fcfe54809ccf75305bc9f242f26f30a0ad5f3cd71cbd31ac45ceed2dc8571142a09b7d3091a4838727b9a067927e17b7559076649b405dfd480627881489d52339d4a8943ca396e92b92066e45d525acf7785a944345d25d721d6a354b1a9f3e2afd379d1c341badd0dd913a3471a5b78a81c0b338a2984e115d003b1deec1b44fd19824279d742017248fb4434cf47ad07fc87df86e634b2d8f6e0aa572088678b9a9f767404f06c84ea8cbf65d46effbde7de1f090d3d4b9e7c7c3b2b1dfa9e591efe12ffe0fc82c9eeb7fcd9f25fe438b39c46614438d0be7e1dad11bce8b91396f867531e8c45d8c01119abc2b20be253779b5e651bd80536854e2aabccddc5f4fbfb3497111fe9a8f8a417ab4dd806745c82126524ec325c931ac1f31a3cea19e159e1dbfbfcff761cccabefad38062872fe8a45a14781ba12551befb31c21150a56ccacf9815d8f458b1f591c71ba7b0459e7c09a4eac5c9e5b2984314ecd2f7054ed055ba082204f7ed62b1d513cd0992bc10c28bc745e30b27f6ca28ac84dec6cf0ef73c971ce12b2ddcc0d6264d8f7dfbba0a20f8ff1d7387cd9d9872f4b345b409950d66ababa9852f7f5ee634dad6085666956b97e4c9142dbdce96bf42d1334c61d04ffed5ac8f12a5075ac87a7416fd52579a876c89e22008759a93ebc57279215e178662a064bca65670089ec688532468c07161f56bbafbfa5655768123e713c7aff52852978e9d6004ab3a434d9b5c73f0d90dd1fe742a169a84f0e96a189bfc5265d8c5e2d9e42f5503d04ce01f9a912bf8b9bd8c282a4d40bbeca55d14971d1d305a16eb85d02b4edd8d35baea56156ba12f4e344dc4cb34509fc780ee97d24173a75e49960ec32055710bf8119d005447c6c391365737a0cff68d9f44868b97b2357dc051ed7fcf590b32292624545935e87f25e56b3e4a2b9c39c4936b5be9030b4711f246623264e0370291b675e75e1ce9cb425e5fabcfb55e25f084ea8a1b84870135ad997f7b700876691939cf268204669790a10ddd3d38cd22252226a09fddd395482deb561ee834ba452750d5b8e0de63c77c85a7446dd5bb29df2620f98e07bdac4cb59af8b9dc64d427dab780257e252e8d6793fd1b99f7c3162b4233a418526ab227d40b9deadc943d0f108a38d7a6b075465a44c920c0146338504eadf826cae345e864452e94706c8dceac5cca87469f2183a9c918295c09eef65f747b7a3d7fb3d259c4f531ffe48a5c338717ceb45efb557a47a593fac85cfaa4c263c109d385c01a3193a6ad1be5923d6a53e6c369a2b5e704cd6ac3ac255954c3fca1079895c596596873c1309fdcc5f36fe039d06806dd16cb00bd028edd6b44fb1e9ce4a020362824bef6a59502cce4e1d3d3884d7d865823deb092916a215ee73bdae1d4baf7f294caac7f63a36c2a15a40517438b8cecb93a5da3e11c25ff228ef3e7281360a2ce3ac66e69a2f136a83fbdbc44dd1737e9a31bdce16df9e118345ec1d9a9c47bfa60502722c9813d31c9f1b0364e2e25d77a0816db52f7e86bade9aff644df50b1cea9a339e76e869fa1fa50101f8182a2a6aee2e90d242d4b4d6b999d1c358a8d9297b6e0e2ec141c2b3692d70b141a213d477e87c52a2c87a5c6d1f0fb091f35f50915878ac70000000000000000000000000000000009111b212a32363b", + "raw": "0x50f91c64826d6180843b9aca00847735940083045f289400000000000000000000000000000000000000010180c003b90a20fd3c43f5fc7807747a73e1d8e78cd9e611ad6bbba9b264534594174b49082aeab827927b335526cc50c2f0368fc666efb79c34af8ee90427d1718736acaad47f5959b9b26457619c07c2dda553d55a7498e30a37c92909f6b37c246dca4e8fd24d4cccd811396d276e5d11f1e8d14bb9eb4d5ec49798202422edd57ea4d8c0e8c6388e9c93a0ff2e52f7ca2303e40300c50c926a7da22919be462e2dcbdb3ec235b14290a282ee76a04f4bf7c5e2ec5c8fc0aaac72ce4f8fcf0d42b9fc3c4049ab6dfdfa12623d89c0d96434a8e13cb6f79ad6f4a8102f9a0bfe582d967372d8928ff9d7d7393b22ec1386ee91dd196eb9c349a6a12f7504e66a096eec0a8ae98e62275f6b84fb40a81a390c6ef0102c8fd2c11d303745b8fc49e638e6f3004961724a977a18d81efc67e37d0d44558e28cf9015dfa08eff82004c4a53dfa40c2451fa03a987f70c855dbee37e36480863044165e6d46d4c43278091317beab6f301d61c8f54f94ee88fa358c9aed6e55b80b4196e79a3d7251ede25c4baef8129882a69789df3a8262941199ded7bd381de00c257199c18e9086d9ce3f72c6d95c0a4d109a3a15474805f0dc06649a16a7805e8d74bd1af7658f5f9ef726d560595ff9f072d4cfaaf61283087843b904b0f5670ca551079c759d4a2839a71505e007cb5d49b0437b87a080fab5e2efdedd1d01f0f1ab72f0e6129a2525fc6e9829b56ce9d9f287a5bd80be8b1556e4ca82eafc60ec22315448768a72e45d4d956c16ee48a0658e307f81ee0f695f1b1b747d1d533d8da720f088b64608b1edb2d4d27247b2cd35e3d94e1256a3c5c944bbafe07b55ca74df4ec0b869733ddb466717a16e98af4ec310d046c90046c024fb33fbb2ffbb105d41bdd0e0af27b1239aa4d92b6ef8d727e51372fefc3b5c8bc6eb585a0ae2dd9970009555c2c2ced5e5a1e97c659565b6139dc4f3bae788e21f9658affa8fdb6f4733f7fa83fefab91a030f8ec976b8263c17abcef46dc22456d5347eea7c30dd25bdc3caad7cb2010f06573d56b6e5d28e6e847d8df8f18d6a2655ea66fe3c8e7e4ef192b5a8aeb35f8469277657b77155142c7b1653d5eb9cf9c4d69bbc5746e0c1876e330f9016a2f5343ec60b2f35ea380169a2bdf102888e6aae7e797d0bce73834f418018e8e55492da8236a542a999d9eea55bd52ee2e59feb0329d716c78c0bfcd79dc27cd9639399d2fd99d2fc9c4900ad60bdb8221501038ec4baadd2ac4830b2bfe1e20804c818c8e089661e7d842bc4e566fa0bc2d7968a44f8df0d4e88e494fc7bebdb695d3a8edf6a2703817b0f8c1a55569ac4a8ff0931137f075797e9744135a3fec6c767af26d4592a9022271a4052b1f1f24f072bd5ceb1d19e02b0bbf31251a7bb8b723bd3da02f59ca1c0c91bc10896970a1e0f8e0fd5b755da58d70be8935f65661629a9f833b35810113ce80125f8ed7a031cfd5eb1475b597856b4ce7629a9429d840a3457bbd70c05c73c6ce84dd59f917a24d06ca8743225ab8c266e209fbadf57cdb587df96eedf54c04fb3f83ec0dddd1d8bf9051c6de4db3aa099f1779f3f30f61f432e5c8f6b7ac4ee6c6dd6fce667556df155ddb2002735fb7addd8acf74863ccfe04a3088317634eb47e56b18c79f31318ac5e448a9094b5c2c70b44dbbbff7c235cef4701d504723b032726d009c6d7f527e645a23fc1ab478e6e2699211694d575bd436d778e7ae53868c63dfb78f591d82b979585cec8bbcde61f375e783e97e8f787fb392fa4f0bc3e9010aa9ec3cf6471bb16355c3ed3fdf2ee5b95ade86371d60fb0699a851770a212d0e0eeb3f20df78ab180343fd79a9d04d8dc56d9fe3d820b27d98d12275a40d270f4181aa1a18305c8d3469a954b2e85405a394684cc234702a6cb01c04ccc941a4392cf64ba31bea700d339152fce6abb0dbe84823b8d3b18258a29414fd52c91ccbc198e101287b79d8bd0e5f4b05a14a07055e66ea37d781934840a204638bffda400113bb1344126fe1c2ac1e57bb861c3d35349b1fba0c11e12921262ae52fb2e0bee444f8197e2817b9356e10af67e794a7967055936bfcb51f4be6fc5602a8df97ddcd73afe83c02f00d4f1d8302bd2e826d4c50fd3ded9a74debd0e807b694e912a8a3a800f5b983e171898874b77ea305ede4abdf0db5ca84a8a60b184374c08066537b08d42a609b97039ff8905bccc4454188b051c5d1e574e1e8b74cc5cbded064a5374c55f17002ee9b17447fdc324a12e3f2f414b491cccf20c9f98820461f4c7d61355a30f1a6cbb2fe7403b90587298fcc9500519451e44225c750b8b32a649ea288eda389e596390a5386652dea5d0e096ee270bcab9da0c3c4ba464f44172732a748e339cbfc8f0c1ee3187225e2fb29e67ffbd84df8acf759c817d628e03a245e9ae0cf00939fa12964e8dc124659eea8798b097ba52480532fa11194e4623ff63f6cc1d17c7080bb2c1459fe8cc9b197b89ba91986b7bfa61e514bf5c60f981e63baffd9fce44af87ad73fba197e46790fc03f8a46aa6d7590f47e08daedd7f564685208ee87da84b04b11cdc0c020bb26b0abdad3c1340649130e26af9c7651533313301e8b517a84c807d86a4c0cff68566d34da4111d67bdc77ef5f49ec7d83af24a143bceaee020acce02499c725ebc341a86d91c7f63dd962ffcc09fc0b5673873ee55cea4bba69b5058e4b364fb3802832d5118774790dd12eed78330412dc877cc034309a7e292ebee955a431fd46faf7884cf3bd5ab03d02b8784af2a84bb907ba5f021fc332f638a2d4b6451ea0a2cdee6ff1621d698eadfc99d6f405003f300e321a9e80ed3b577a899fa7dd891b53cab8acaa9fd3ce02640eaa75646f134c190817675b9e4a688d0668528fa3b378749bb6b1a0bd16873e89dfc927dcf568fc3cf94ac49d289ba1fb9c58a74574c8fbac321db256bf919e9432d6a8ae9a0dae900901f436b13d0c2b753a5eb6fcef03301d7faa15ff32ec0730335b13394bff66ea83a7043f9e1df5962671ff2d2759db234a4a4fa47fd3a9359bb14ef5b5fc398836d42afcc5d5f252b1b061afc6a0815b3a7586d25eed5ee52c56d2389b8f2438649ee652b431d3cc4262c6e5ea1c0ccec21aa6123e88b4bc933098576bd78cf5bcbbc278ee682029e05e91aac2043ad3ec1d3d97f6ebc6bd5faffa5bc71328cd4351bcb9a0d8d1ea9253b97b08c8c53b20e29703568d5d7dfa2bfa6aeb3a93043e4123116a125311695a11c8538658210971d7763ed7870c1309893909e306df22fe968612531e58a91d19dfe2c658ade19c8e0900c779af8ec333d19552e42cdedbe13ff85d99b10baf8daf70951290db56bc7ea049e6b468b6546a7f3ae77c2e14770eed1ea345f0d139336af4eee686ac2e73bd4262cb802e0173fb872a77cd2c0f3421c497b0260be79ae29d04d9a9da9d7bc101ae3ec9dace1133332f05b7b82aaee577c06c0d2a8eaa8a96db8b899cb3240cc4dca4f8eab513ad5b3529063b5df3664dde0db1e0ae5c29e69f011076fc7edc4261d043f38f1c68645466c9a5e685a07393b7e2f8f74db86742ba5ac089b45a42df3f943842747674c1653aa2a8ef282f64e7ec2ce1fada994288a5f9b95da4bc083ea008308b91213c74a08868ea0fdad9fbb1b485b793bce6e4fa945668b2351232a7c8a084fb2d87a5c83e7dced6bde3743617a7c4babcbf9381694b64d7e0feeb6615440e927a63293c6b695900b1e7afad1ae612c324a88e6761c3b6fdc41d18f514be1ba3a1ca53fdbcf8c19f95bcd60223abe52d07fd7c4114dad9f347cf122f6241429da7e598959c22692910323a0a699595398f518c58deea7159920d89e3e65702bc2cabea7e9ca0bbb7002fb7be5243bba6a08a12238ead443ff4394510d25eb279885d9112c44529f294c5a2bf493a74ba8f4e38744e632680b3ce055a897d2a5468ef52e6e70dc5af55a9fb83739f6cfc6994871662b8263f2e07e21a6514624909369e0138755165dd2af5a791da63c0604b68ff160fad82a578a06e76f62bb7e951b81d8fde2dade6c3a314eec5913151c16a93a5abd5ceb59ad96197a349721ab123b42f799dbde36d7965e0e5dfcf43d8d1ae13f4a00afd8dde36137d3de87f4e2c0366c18f4b3a449ffd9afc7c742c50456f6e642f7d09e86d5aef224b20ce5d8a2bf164484df8fc87daf69e459fc78c6b974cdb8fb1dccbd5290f560e3114302886e2828ad73ce71b06186254206743076c6af0c3d1facc36695dc28db1d026686b141247e1c7a9323d544b0079023cd2adedc0479ceefc8e0c34782603d0c27d18768eb5485a85bc385ffdfd25f735688a3b9a0c6f532b2a7989c751804de0163582293a17f635fdde14e9067f12929b079f89a53dfc87b986f89f718320ede83cf4086d0d095b24b66d5e3f1bfdb08b79cd5b25657cf2b20faff1d199c16bb7f631b33970b34c12997637447e4127db1bf580b339807637a86e0248cbcf8e1d30ae6fe053e2f9b7b3d0f9e3f4813af908b633560779012f9e06af00e252bb0df9f0caf7d1e82f8deb2ede21d13f406dd9ea69445d50844c95c921d8d1cbc8afbc5ddcd4157e65cbfbbafe2670e9146a5643db049a8d696f0eae07c3d4099447ef78bdb90fc05d7cc97bf9b9dee8719464ec6b9e6de866f73914a80396dea3900a9f7b43a47e648e20a9504da92c47ac65368813e5453e82020f8861aba2534346e6137e71adb28a5ff080365d6ea26dfc30ef5500d0760749d6e4e0f93aaebed544832308b19f72e92ebb8eaec2492c6ea7972fd359a8b67a1f4053bfb1a3c6fb720b5925a7a827e59b3bd0651b8014c77b25d61db17eb169cc2fa2442c82f68fb42200c59baa468a9fc92f13273ff071124f8b31e2b4b2517ee622d29489997ecb5676fb52e3002371c01004c214757b1f510091c2377a08d058209d18feb9b524a41712b6df4b92f2b14c583d3196749f367b3bbc8ab5e9e2615c511f23ba5fb1bac2ee9436dd8d162bd96f1fb663d2b520ba7e8ddfc2a4d549b63714654cfbb37ee1dca5f723139187ada8f8d5b42ad09ff196b70720d2527b4466d44f33cce486ef2e86311c75ead31a17b16989dc63bacf0d465379d9138df7ea2ebc71f4cc3b6662e24895050e2553dbc160a567d6722964a904d43bf2684206cee3562256e98addf3038e968cf6c09c921e2c89c9c249f6ba7afd20dd27587b4143f704f2738315a91c2d40c467111b4f3bae4f77bae402145e742ba83a527aeffca13ee2290988df882feaf5a3c24b416d59e06cf4f8832a016ce55419b7bd2028545557528a0af23f17942433e13fad089fdb79449bd9d99b0324b1828791249b6789a09cdfb6ec40c0fbaf8b28ea4f72d3df5159bea7a7965b94beb1bb01d87d76ae7ce47fc333fc152038ab4e7ca64a802f96f2e92bcc53ad9cae0242c622c99b2daf005e554cd6ba127991d84841ffe3ba0674eb7930509045dd00ab91a7c6acd2f4a40e7ffc9959929851e40d417f488a29f7bb5af3847a8caa5daa0682aea870ac8b866ccfdc435971e3d862c2f651cc6eb8a33fca313a56ab8228ee9ac7dce14ea3c3fba4f58c70888ae558d8cd632a2723ba54a3d538f4e20936a2ee543e9b2141e06095c72d4ee19908febf7c248c03a78655420da644746e2d508c31ceb0b648800d95dceec72f7576502046e5dce54b5a097f625001bfc92d6e4633b293cdfa63b1fca5de9e26d03ba2f1cf3647dbdad5359ed76bf702f0621c057dea3617af678016aa13360ebb02c6cb2fa0d3f137a1a3c639c989e12383841ab7ca5a84f84c08af4b85416ce7ec3ed91636a79add207bedf9dfb2ff626387f20cb3315502b2b06f361cbf6a51fb507598af41c5a5b9cd95ba1894ca372c5e1851e62a0d3d78dab6f92bd43ba6fcd71230b6cfd843d89268872b75e3c5b471db530b7ab5451dbe63fa0bdaa7d74907cb376643e129febbe6ce10b5dffbf323dc973f097d2081e06aad65e674c5a41bb81b80556fd78691fe6b5bfad47fd1b64db577f27f22f17973cbff3a7c4aa43569bbe6843d773a2f933f472650e88e0ec6643f87dfd37e7fba915c7386a130b8d4f0ff4d0e99a633d1f863f3e8ce4e1ac5e31438d89c3b6d5ace3aa6e14e7073164ea01e853958bece389316023127f9916297a47c5d6ab5513bab874c1ae3bf2850cfab9018cbf50a7febe03ff3e8e4e55ae5632812b6a147edf051b461bfe56f01a6ab571e0553e37a57a3a9811f4fda2e189d79b74215d6fe199595d18c6543c747572f8cdc61a53ce09d9ca96b43a5af5b56b53148dd4fdfc1e22c9958caa783f2d112d8d5fd39e6955df75d35c59a1967fc0d8d3293e39a6cdf82d6846b39a74b1a538372c266b3f12d7ccf464ff7e32fe54342994f51d344302b3b2e11eed2187a741eec99ef0a79a19a854c03d8bd3fcd557b9d8bfb35f0976da327fc7e8d95fb43db8e66be5b373385fc1b68099566c7e88aefe92c7c521d084c15c8d403d87bbc975e8d687e2a51e5ce53191e3db5bdc50f475853cda7cc5a7365c41035aecb61444c2a48492a600b58300b2805be97b4e9e30526e9e62bb3248a17c3809219307ca85351495c943a865359c783cf615a809c739cce0786c6045d9c8071797001434cbae571d42cef415e28ed6adab09ed10e0713dc1412ed80b8d26d549964321559137483c81b19203080b36abcd68e841f4c78b5302da79fd6e555f390322ae67e54c55749491889d79eb2982fc4428086bd1060c4113137ddb4dd7c9b690b802e805999d4f5127f66f6b1d397dc3509504e2196513b5787407b45b928cfc3c437523daa4f876dfe061e351cb3bad99ea205ab276c4f2a5ccee1027104f09adaf55cd282d4e9e44ac2b65f7e423da1cebb0ac70691347e7a7bd0de8bc9fb2e7a08afc0075a0e85902316cd6ec9a5802c51a6d65bf3251ae712ae0f66de6cba1e51efbad53ad7e769f851799caf5fb81ef35b4da814915dcfa67553f1c67158154707d16804be27af2115559e4758b313b9da4a1131718b29a75970b3f0a5e2f2c11a0a1ed47f238c145dc4fe9e8e963d8395c67dfa94a232b8133a0d953b05455f79e0bdff0bc3de9c04d93d97084ab99229622cfe3958ac5fda6757de1696b575f6250b441e6368386751b1d2f6007d254d152fe76578fbbe164af49cda805b9325f7ea47f5e18f3de1ce38006ae1bf027d3e354d6f923d8bc6286aaf9b9a7b9e7a7fbd36a31db0d88166dc68e7eb567d8164bed1e279a8810fc21656621ff7cb42a21ee04e6086924bb62dddd16c3343db69250f7ed95aba953202640bef18dfb6c00f1ee03c670a5cc6c0f3cd7cb006590dddffa6f19d450860e289f85edb4fb0dbbd2f992eebba09cddc1b20a3c98d8739ad1875a514b09b1f23cf406c4c55cc4266e0b8b283fa445849316c30bd19254e9d035756d2773cab7f5fd56d6d3a094a717ccca43251201cfddf80ba1aa0dad34f5a3acf8476b784fd53a1aff1307a7838705112650bd25dfea21b991d801f018a5dae26edb9dd5a0ab940a94b7bbb90fd1f30f9d1dd2ea3aad6d0a2a3c42fd2641233c7d624314c3a54ce616d2ca5683d04f6fc0924f0b667be32f4de8820f9cfab963a287a1c708857ebabed9b5bcc35d539ef9bc170636cd528ba86a620195134cacbc2b8e742376124b67ed8155ab53979e281f97b184c60355b008f15f45c8b7a506b1c1f511e4aaf0bc32fee27b656b01ed6afaa4053ed674a60175b6c89a77d42963111d0940730db02ff67534fe6a296e0e01e2db6b3f0fe9648286a0f3420cd4393163662751deed6457abbb370f83ed92e9da86a0181df13b8ef33e5718ce524a700ba5f2b40f3f973a67c1c412dc251c19e6b7ceb279dc1dfc36a3567e3a98a9d96ef52b0d0734f57bd9edebedd925167f230b1c81ca938e94ceebe43d2573735873a436331a8b76c1169c6a869889cb74e5d33721bbb99ec87f160c025f570f1d11c2e3ae6a52580785d854790139510179b003418dbcee1f4fd4fa39fc134521ffd7f29cee650472638dd04d8331ee439eaa32c57b56c4fd9c9ba87516a8236dc99b8d6e4c2a48e53a6779d5e13bbd73cc7917f0cfb8e231218bf33bc3c213599eb76476558f0e38a3979cdaad6ac6b03bd0ef0aefec634fbe0e1e87bd78123a19b7352326b9def856ecfc02b06622f94e8cb2a1cb6cf10d020f789a7db775063030f15b463f08878219636f2bb94ed11a3ed9689d797a3253809c7f2e0c60672e8476a9e272075c7f808258901e611c4d535a11bfe01daccaec3a26a187ab45a9fd0bb9a7ecf2e9c4aa3177ddaca1449f19f78ebe26be2e25bca012a10649b56899339f5418925648f3253bd716336dcf65e6b4f16d2ae51fed1acbc8335c103f721f46023cc2043f568ddb033aa5f2157e52b89eed4571cb523fcc66ef5cddc90679633c2a46f45f1a86c975db4f6f37f9fcfe54809ccf75305bc9f242f26f30a0ad5f3cd71cbd31ac45ceed2dc8571142a09b7d3091a4838727b9a067927e17b7559076649b405dfd480627881489d52339d4a8943ca396e92b92066e45d525acf7785a944345d25d721d6a354b1a9f3e2afd379d1c341badd0dd913a3471a5b78a81c0b338a2984e115d003b1deec1b44fd19824279d742017248fb4434cf47ad07fc87df86e634b2d8f6e0aa572088678b9a9f767404f06c84ea8cbf65d46effbde7de1f090d3d4b9e7c7c3b2b1dfa9e591efe12ffe0fc82c9eeb7fcd9f25fe438b39c46614438d0be7e1dad11bce8b91396f867531e8c45d8c01119abc2b20be253779b5e651bd80536854e2aabccddc5f4fbfb3497111fe9a8f8a417ab4dd806745c82126524ec325c931ac1f31a3cea19e159e1dbfbfcff761cccabefad38062872fe8a45a14781ba12551befb31c21150a56ccacf9815d8f458b1f591c71ba7b0459e7c09a4eac5c9e5b2984314ecd2f7054ed055ba082204f7ed62b1d513cd0992bc10c28bc745e30b27f6ca28ac84dec6cf0ef73c971ce12b2ddcc0d6264d8f7dfbba0a20f8ff1d7387cd9d9872f4b345b409950d66ababa9852f7f5ee634dad6085666956b97e4c9142dbdce96bf42d1334c61d04ffed5ac8f12a5075ac87a7416fd52579a876c89e22008759a93ebc57279215e178662a064bca65670089ec688532468c07161f56bbafbfa5655768123e713c7aff52852978e9d6004ab3a434d9b5c73f0d90dd1fe742a169a84f0e96a189bfc5265d8c5e2d9e42f5503d04ce01f9a912bf8b9bd8c282a4d40bbeca55d14971d1d305a16eb85d02b4edd8d35baea56156ba12f4e344dc4cb34509fc780ee97d24173a75e49960ec32055710bf8119d005447c6c391365737a0cff68d9f44868b97b2357dc051ed7fcf590b32292624545935e87f25e56b3e4a2b9c39c4936b5be9030b4711f246623264e0370291b675e75e1ce9cb425e5fabcfb55e25f084ea8a1b84870135ad997f7b700876691939cf268204669790a10ddd3d38cd22252226a09fddd395482deb561ee834ba452750d5b8e0de63c77c85a7446dd5bb29df2620f98e07bdac4cb59af8b9dc64d427dab780257e252e8d6793fd1b99f7c3162b4233a418526ab227d40b9deadc943d0f108a38d7a6b075465a44c920c0146338504eadf826cae345e864452e94706c8dceac5cca87469f2183a9c918295c09eef65f747b7a3d7fb3d259c4f531ffe48a5c338717ceb45efb557a47a593fac85cfaa4c263c109d385c01a3193a6ad1be5923d6a53e6c369a2b5e704cd6ac3ac255954c3fca1079895c596596873c1309fdcc5f36fe039d06806dd16cb00bd028edd6b44fb1e9ce4a020362824bef6a59502cce4e1d3d3884d7d865823deb092916a215ee73bdae1d4baf7f294caac7f63a36c2a15a40517438b8cecb93a5da3e11c25ff228ef3e7281360a2ce3ac66e69a2f136a83fbdbc44dd1737e9a31bdce16df9e118345ec1d9a9c47bfa60502722c9813d31c9f1b0364e2e25d77a0816db52f7e86bade9aff644df50b1cea9a339e76e869fa1fa50101f8182a2a6aee2e90d242d4b4d6b999d1c358a8d9297b6e0e2ec141c2b3692d70b141a213d477e87c52a2c87a5c6d1f0fb091f35f50915878ac70000000000000000000000000000000009111b212a32363b", + "hash": "0xe37a3c437aacfb3f7abe9bd9da80fb8a50398a56e6b60e6fd29f08abd049d9d7", + "intrinsicGasEstimate": "236504" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-1.json b/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-1.json new file mode 100755 index 000000000..2ad914461 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-1.json @@ -0,0 +1,6 @@ +{ + "id": "wrong-chain-ml-dsa-1", + "expect": "WRONG_CHAIN_ID (when validated on 28001)", + "alg": 1, + "raw": "0x50f90ec5820af080843b9aca0084773594008302d5709400000000000000000000000000000000000000010180c001b90520372c0f4874450fb92ace74d41bc0326c7f739589f9b86a97afa87ef65d5939e608c81a44909e41f41931349f744b7aedff8d5270b91c4a2f61192e2bb6e3e6d12231deab235359e78ccada386becb6a6a1105afc0999243ab8b363f7cd2c19b2b741c9969dcf20252f20d130dc05d9244f58d6de9b4fb4b6f0125c43b60ebe3c7272b6ae7578f1abb4bb5e2dcb31eebf4aa7089aa2bf40a0ba5eb73aaa90e45472168738cb0e866547e079075d0341c4728ed794cd449d0cdeceaf64d09173a2677e3f2621b56014df58ee8de2bbcf8cb2bf369e57a28e40b24df6d0b15d3417b7b7fce3c49230b3bb7c7080c4f1344380db37299d8c0c29a7c9e95bfc4f3ec70b767895be6ad798449f94c92f320696f8f9ec844fc9451f5ab30874e6c78673b932e24a918d5bc03f4fa647c8679631ad8b30ba4f9a1a790a535104f5079f781fa4c4aad807777327e08bd6e14b957e527650d39e2de7d30da7b2b27457d3539c2f99903054bd1a6d6301b2f83249db80dedc911059b047b5552407ed32b79b57ea4968198decf978fed532277fb189841d0c17f261f1a7c4618c33b258a71cb6b2b921c48735c1fbc375a80fe2d702e9f70db34547147f6d65153f1c508ff90aaf57dfde59ce6e56c5c52049b10fbc2640cd937bf5027d755444cd5e84aad66be4ccf04f710f0b970cbe7fc5e4e7a44f5d8fc2af94ec6df87862dabe0d85dd17e43728800d5dc8ff9e9e1fd349b9d6431f264836a447646a1ee2d73e6a4d1803d71b98510d94d53b5d07764400f413b7837f463e273980296ad5e78a62c83fb91354c25c2e28bfa19480ca41b0ca2d8beed456029eabc0ba69cf3504cf1207ab21bed0e3a60795f5b066019132212a9bd20e98b43bb32484454b7693bc63764d0ba8768da4336ad16a979b1d3e8b06e89afc4caafaddead83ad861a4596814062468d8cb2e131e71cf38c4e335bb3d1d9629251fd50a4273999a20e11d9a881fa2465c2ef32301fa8805ccb38b4656e3c815b54ef42f292d05847c0e5149b0a2ffd1719fcad10730b763406e9e453d2e4a556c397a984a7d8622466522e79f715f980279cb2d1d74d5fd15f8beb8df9c0a1fb93f0d5494ab701cd60cf2b613b484a191d873449c4815f44eebb62658ef90f7033a5e48d40c8f4ec9a25d4f1b73a150e5b03a4feec9142362e77d74d364bb8a40f9873efa2d9f458d84277fdb0063642d9ebc794356368a0b4e53f6ab0d9acf4418fa42d05c11db12cb67d6c4cbbfde4d85358abaf8042510db53c1540fcb40045b334bc54a17608e82433d1e9e53c99769b86b69b8cf1914584cdef479061718a2cc5bec5c31272e0463139721c0c3523a6ea31832b5c15aa59819304c217fbc51a2636bfff331e6dc1037e89be15c17d6708762976329353612f312b828e525c09b81afafa5ae5c25d82b70b6e55f892429a93e5eb4048ade675583e828da988f9d253123a06c0ed047adf4d93d20cc6c865f5a761fec27811305165cd4bda05f563215d0612944b88ade9d64477ae8fb441978720e70b0d77e2edafd3a2c571cd28a42cca2f289d157cec813c24e7f56051b4f28c153adfbb2c1ff90ea1fbc03cb89603387169072442f5d3081140e2256ebadcd775d2f1da92c15a9ff1ce6e980b3b1e91a7e379081ed46a4259fada21536af318eb2043ea16cece60b73acd415d239389cad9212e15bad1b1ae38f93c756635a9b87417faa844e4f43bae1f1ae68641a04f0ff1d55f9045cf7e3ed59fde5c07219b9113329356d4300885ee19c9955c5757db33c6ae75b49d035003171d02ccbd7321d6a14db0bd011d4877f04070dbda3b67bf22d083eb90974dbb3fe4443f9160a432bb4e436b97eb1dddeb445ac5e99b3ecb7573e7d8306ca2c9ca81e4c0b9cb4bc8a19222f0f45910a0982bd3c78abccf395a5d87c9ee78cfd7d902808c21483a0e99137edc77073a35ad680dfe59c284e489272a85481bbbdd14158024750fb2762a931e06a16079056458fe2bb97ed55419da0798f94ec35767c7511ce7ccc0e626152f8b566bd71377dace697520cfa5aff622276c0e5cb0a970cc3795c889258daa614042dbe34dcf258b8aa52423035182399130f3b140164baf8caef8e9767f31db5beac2872907bce2550f448ebd74184f8bd28fc2ef9aa9e2e6625895fca23bc190983377c16b98ffb338e78ca6d64bc95fa90258a375240d11fc8cbbd8ea8f18ea28567ac02184342e61d6c6dcb3fe04cdb8ce967cec1c9e205114304839c81d5af6895401ba809bb81cac66062bb5159cdbb36b644927d99bd2ad337ef7fde1850b6b4776b7f484f4aa0b9a2a3bc69b4ae541bb6adc3cd5d8f9de83a5543941a97b2e0ff61700f834e90a74c2de3a0e02066685c94e3e08964b9f876772aa3e04be45979dc7e1df55e8c81d45bd07379d3f672509fd5faec33122e17f08c158948dc23a1bce964f6f665e7cb41e8994ddd2f01e8d5552227925c85985517e703dd10c79f4d77721bc28872048f7feda6197ccbfb0560be1e013953c76b9262a178642b0be5628880950fdb8bea2ed6b301b2751a8fe1876b8ab4d5f34dec3bc95b3d01dd1c53897c8cca238b7b7ce99175e3bb8547daef19d7399db5029106cb37b67d70dd131d6cbf97ccadff5fd2bdf83b0210d94ec7b1ee8c1efdc5646d704fc79544026b62c176259f3bb3de1d0a0be8ccd9d95370083a78fe4a0269484907e88051f16ed1e9da53180f28980e0951b897e3ab2694412ef3fab73ecf4ccaa14b236d4aac95b1d943d563c0194b6fdbccef0c92bded1d856684b98e76ee8832c64921f999f1908c5d8ebb9d5895ac48f976e60d636b99f327532932b44170e94db91b268e5e1024e2e15ed126800e7cef347cc58743fd57a9b7511e4e95d422a8e6b1022cd6ab7816a6afe1fcdedba4915ebf5a459e8b26d3c848276ee3b0a8202a3140e968a2686506d34960d96e86b309864754fcbfd128b816346fdcc04b8d14faff7cf5ea31c7422ebea74a7a524548bc57cb38bcc8d8689c90a469d8f0105a6f0cf2e7c24933a7993988389f5066bb7385e1ed75992c75c3df24c0a08c3f2162f5bab574b13dae648904d6754f92e1354190e706f1bc45ac71473c465fa73d784c09fe7fcab408e1d808dc5c318a0a6db8219121958f35046abcfed9d874f60dd18376fcd844c333ae7dc13353449082c79f46e9d7a2eaf71a7c54867b04dccef0e3593ce939e12e395e5b69a9a133e4a2f3140f17f89894b70bb7f21082621742249f544464f1995693f37ade71ead1de00701beade7e60d857c7c00c5431a4129c42803d00cce4f3765a9dff1ca90fbd27ee23f3a75baa049fe6205a24aa0a621ac5126649644c4b0cd3cb78d5db9460dff55761e5ffbae250c6365e632d953291efb1f891a614d52c8f882a7c867725c427eeeea2229c424bfc00ee7f4b186c8c68daff492d317733795f6674a44e3bc276e013f28c75fd176c53d8f6fe39675562bf7e0957a631587c0e76112da49f057786a976110ec3fa93e589117f1346180af06f2954b49ac60b4369e49b53b8ac068aac4e107294791eec204ac6ad869342cd55e90257893f92e3ae3c598be9cce120d674a8c128e46951a6b8817033aeebf46c55a1c9aa23d48c03b24ce63786fd7946c4be1f1dde7e6beb733f8f3a8ac8363ed03e1434669e7aa048ae77176b393c9ee6dc5febb7b8ca0b343e78601ca958f87600561c3bc4d32cbc0a31c0c026ab7b5f7659c15ea8d71709b9c5d3d377702097345ef51efc9c9384cddadae853e0d889cb835cbac3ac59370fa6395f9ca44a4a6250fb55181c83d14c1e4b5ec25ba3211abe634fac46163998739787b76a9f253eb83d0e9a9955859748cc42503b95624516bc41bdc12fce27d495c7326cce0e25d831261ebb157954913fefefc24021d90dfb342749507a899441028a24c5a678b636b26c8389737dd40c10f37c0d07ec8655247f149cc9dbb3567b2c81507c07f17944cf617477d692b6024d2000416fd75de3463eab6752130eef9d3400362c82c44fdc950ea47ac75ae25bc133b8c48f8bb9bdc6d0c7c109aadd7965b87a122544a14e72e219d58d237e7795cd3132e7802b8c370e8c14c170ec3026b5572e393e62cedb243a376d302e6573d75397c72b507a0e39a4b9c87c8fd6f49330e35248724217cc9782bcb408f5ec6f1510d334e31978c6ef5baac79444fb7ed56bd6eaf034d0dc32a66e3827886aa3c10327cb9bb7c9fab27bcd9a97c4d4181d06b7fe82204a369a079c6bbe454de03b87daee2b76390c701a26372cead63e99513d354dedea2a0b5f1788302ace68679fb52d6f11a17ea658616d4f625c1d3da587949e048acf37c4980125ea1e8666f85e37ef13af70c2a4219d9cc12fc0855713ec9c139f1bf41f34f0b787a08afc33814ff0e7530c22946d0b33ecba6d7be579e0a5644f6a4ee5a4088bbec8ab100faba7edbee3238a8fe55f4a19b45babb17d10cad5919a01839e67c256b66c84571a460f2ef287c367562be9e02bcf5e2a2bf1036b4a61e0393d58acc5554691847f8d972f48cedd46902b7c4711841bcd9d6186cfa462df62a78cb924429994a56f8edc2466fe9de98bb87c75d771cf41528174d7e0858b00b3398e59a7cd32a64ab4958b03724dd05f00915d08ae5356d605494a2728bd06fdbabbcb6b1bedbb83239a91a5ea9132f1aff725414898b5a848279c0f789900ad0c57b9a8c8aa3f10a19095b77e14f08389423411c59651ccf228fc0c0e94d0a057a894acdf7280c05fd56c7171659686383ebc6b19a93c47139f3ed455c0e642a49bea837a451cb0c6ab2073ce13f6b72eb71cb138ffaf668d41b8a6e94f1a9c216a33bf0532f9e9b4ed22944599f90ccc7162a0132113359dacb2793aa80c1077dfda1799414bf3dd0d2ebf84663c0f5762429c9ac94755562a7c62d90eb6b99233531d3bb7115b346c4644e94e78ea0a11ec4b1d18ee61891aa47bcf3988bae06fc01428dc32d5012ff32d1d2c17e1a7e23bfba427ac10a5462d6fecd35161296da85d00e3a59d5e6a68a38dd0e3f3f03b157321ab52d551bdadf30223f81df4d9a477bbf25c8ba80bf835f3e1012783270bbabc02b4f29ddb269784ae6d1323416f8a9799a1a9afc8e2e3e7f5fe0d1d2e4b4f5a858d9c9fa9b6bdbfd0d405091112383b44a3acb5bdcbccdef2f6475867838bb2c6e5eef4f9fa00000000000000000000000000000000000000001020303c" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-2.json b/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-2.json new file mode 100755 index 000000000..cf1ebcd49 --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-2.json @@ -0,0 +1,6 @@ +{ + "id": "wrong-chain-ml-dsa-2", + "expect": "WRONG_CHAIN_ID (when validated on 28001)", + "alg": 2, + "raw": "0x50f914be820af080843b9aca008477359400830383209400000000000000000000000000000000000000010180c002b907a05424000ae9a496294dd6b99046cfdbb235ae71031b379ce274c13b0c96411740cb61021a5390fbe8fb56b642b4e5e5abb7aeab143e0037f8db283b9f2febd650265ed6b05f1b867c124aef245c1811422f92414447fd0b20844e0f1b1cb4eec052400aad52b9d773aae0015c0c390bfdde3d367bd8ef9c3c73bca3164b9d418ecbb2d25303bbd12739a858c5fac4cbfa0203b9f3c319e9bc89d17a7a244b57d6613b5caabdb528f077eff9727015b9c266d777c0ba11920118c7ec4dd59b380c40e361a5b23ce04be4c61e12a1c21e091fa0d890687cbf588944db3e34253c75cdf797378de79162e0b4ca309f550365a289f652dd6d559478912cff70a5417589f73f14640970694d7b5a6bd8f000a65c632f0326ed3d128fda96dbea68cb812634dd75e9f63813a5645336681378b6a63220c066550aba43a5b937131d41f08752d13949a115a74bf96fa1925ff4338e10df0301abe40aaa49e14a1a1d58eef005a0f1d0299267002cebeda20cadcea7419cd0c365c53aede1aa36efaf764d3d36169747cdc8ee9a09e0a0ac6bcaeaeded0cd303c965d705d1b91a8b35f408ad8a033b02ff57610bddbfa60e2114e53f20f8fcad15dffac6a494c3f4f631590f2be3422af14cba7c900c9c38796952e20c3069bea2ab54bf0edf9315903aa5cf68549f878eafcc77561b36f8b78d950871ed4914417316f868a2bc54c72d3c9929f0138a2f0cbccb7c4141e94bb8a7ae11f660861cbbe498697d7327709271460a75bd4e024de3d4d6fe5af066944c96ba87459fa948a95eeb61abbaf643190ccaa9cd18591eb6f249a6eb92db89fc95616d21b41d7d15424b80a750938a12cd57d50ef95aaf222025dc4d81df320d9bc32c608b1c5a1aac8bd14c0f7a4c4380cdd65c793a6287050ff4d609102fd91e47e7365fb55513aeca273618528c199f7bb151e9c11a0bf202147734d1be9d5d0e9318096fa567317ed9fa6a8efe201b915b9aa05ca0d19e15c9a80449cc130b398ebbac3d938f55eea8f74e024b0e33dfecdbea02b920ddc5b277146685916194bfa1f8ac7784c7ed76923d4ff9ed97d3ceac283f9b26977df0133c5fa4fb5fcec577bc152e926529f06ff50c204c083c0b4d6b8d474cf5cf7cfcf7acf76921225443eb0abf5e4c76d0a3f524243ee4e372e80ff0f76dd9d135f240114a2ebe6d69609b6c60d275f251d7dceadc600d18e0cf8bc8fa8392e61fa32b8f7481c4883e19d820b51af0f87d3f7faae44e3b908fc759c6de59361487d8e424ffbd662d57a68801110e9cb099214143253949cc479eaae0e321fecab90c63b06819ce3cf56fc2fc1419408075c658024a28950aa47d549bcdb8b5bc9aeab463466c7834ca7d73058c206a95a023f0c8ac95badd383e63041e1f0ef69f51634f5ce2f48d80f8f2e92f4a1fb5322930141fc50e1e20bd235a8b8d768d473b46711257d028e710f82f0b6bd923da05ca64ae805f708577e125b3fca2feb5656f61ded034eaae481a195628801c82db85345f9ffdc72c860cffe2264ba4be2a08fdb37a4f5f80276baba4ea637847335c89dbd35504389f68b2d61ea66d4eac5fd0057d9e757d929214a7d83daf2fc2b3f840e083792d20d772584b252ba955ae8ae8c36af648c59ae0b25d3bca19413fbd749077b6969db5847409d13e4a67387e59116fe3836a733f3253d47f9919f49618fac8edf5fd711a4239447655d6c40f479f86ef3c9d4dc1a6f9683a3f1bc5c9730025e76ea1588d43494f59823f42c207e34412f73c7e2a126501b8fb810f12995c213063d909a5a9c2653d3511ceb809efa69c638f4c977d46a2a305cc831ecc0feebf5d9356ede6c780da78fe2ad683b3312282d5142612c0d1f85108de04de5c3d5414b62826d5b75f8887dc2d932c40f306c08e5d4f69ef4d344fe4317552df9890d0961e3d857bd9b2c5b44536d8606f62f66d14ddd43b0e5d3379cf66d664616df12b1c62385a57f6a562c34e120b79d64ca39d8b23e1e07b2c03910d711f09df5b54cb0e133dd751bea7832fdb38de2f1dafae69fbdf82b6887ff0a92940299020a835b958bb01b25b8699a0846614cb256a6621ef92e4a0947df9141ed4f91eca527aef25862158a8fa712dd60dda947f6a16e077810e29542a56f9244c34a73454b9ad0d8e8c40bd503efe12c4e5bf7d0ff8e6ab642a039f4e8b575d33c0c3de77a1abfa60b0252d7a549dd791d9630c8b848988157608448d77938bfb27beaea8f9b4a259263797c5b2fbdc7f469b2769f7dcb7b9478cdf5f109322eb2f0a83163469b72d8121fe8e01df227563cbd941a1f63961e2a010c6322a812a014279583a0066492a17d1a15c07024f6b8b1561041b3db608ec1c7475ce4d086e60523e85d7a955841558a35535d6e52cb166669a69049646b94d2fdb901ffbb1446a2d7f58696bce000ccbbb6942b0ad6480d006602c228218d3a2f0bc6a5d5c73acda9fc4b0b496a7d527050f8d77b71641f030368e9494bfe8e9dbf6dd4040426da1b0423739b40450273f4a8d551637e5fe3ca8d54fc476e6278e75cebf4a4ac3ac8ef3807041c4b274568797c8caaffae7df08c6c158d92411db981ea02cc212064c3ad6a9cd1cc02087acce5ceb8d7cddaec429d199c3d90670288be6e88e6826d1f6c417df5f35139c71a62c0267adfce7cb3aa49e827165b28c8cc157a691cb52ef103d8d7ca0ebfc628904d0b2d365dd3401b620d6d93cef670e2fb90ced0f4116f56457e97077c6728c16d27e9876b13275f1e5fdaacdf89ed7d20f7d53cc974910a84cdc1aa3c1289de7ce0a80dd983de4463d77f3390e4a9c64baa94cd0f8e31cb21844698ec396abb704d0886c9ef5239451d5a9c328564fdcf5203a0f6cca322d20e25a21a6d96246cd64ac993e175af68aa3ed24b210cb1822e8526257427552a8a896fc3ad77ac0a87bb1d574405d7ced0467b62c49470365adf9e16c492eb671ccfc637e4b9dd0a32f9de2a51a8970d431d8ad92e0cc265d8c6d165469da63fca1f189d70c51e911f624c3786b42e3b3a8c372842cbae99d6afdd2281251c28adeefde311b8bfd0c45e67ce6a6ec16193fd9bbeaff975331eb112c326b303748bd0d28535b73bb1a179b4ef4eba08f42c2dda78366631dfcd78944bdc9058169461baf34386bfd505b119ab6b2c9b84b9b130bb7723e601ce99257925bf06fa80f5ac9f0bd3d00044f71451e72354c0e20408548cbf68de3efdcf93b4383820d93c5fcbae49ecf9fa027660bd9f91613be07d7eb3cf2153588094db67c578447d1302b402283a05e03265d33c0f0a7bd7fffc77c2092a67a4a0983d0a6539bed110abca2a292c7c8f5eec9ad3cfc085708394705bd63d386eea1aa4b22daae2ed1685f17161b7df3ede14455504195692c683908273d73f0503ed4cc7c1c61288a17193923780fb50f9b020e08977c6d25ef33373ba13ebda30c38fc1a2d87d79b846f2ec4511e2fe77eb60fdc46811f055a646bd93de0b342177919f009be73913e21a9171584a1b5051f258fcf079fd474bcdb731b003a37403826cdee0e8ed0dbc9ca9b56cdc7e6d47c653561b47f3b3542a2c8c28777c13c72f4290e832452decb15cc5dd8c06283750af8c67694b40a8902e8f631d7b9447c84ff2122bf310f86cae68147e2357f8af55bbeff3d80b74f55c3e097681e593d0aa6a11ef2c3f55832f21f21bcefda9ebd539e4a11960ee8af8c609b7cdbda9580b278094058a30c5047f7a90b5b87aafb222afb7b80570cec0e3dac70d56592cce38ff1c4ae0b588f6cccd46ca44c77381a529aa712c8e4a806b1938ac1f1363912762be173e7d3f9e1c2dc2ca36ce29038463fa8697c268e68bb614e40ab18084c27746eb8b6b4a71ff53d509b877ac2532807d57694c7cbb1bc095092728374272e29dfb865393b9fedfb9ff0e67fec861da566318a65937254e65889cfe4c506e72e05db17c6094c7ee6ba48af6882582f5928d885daa934ceeedb494fcb8012f10253368df32f5951d8c6f319dd7800ac3fa437234265efb3fae1559aac30295de2d0c3e191551adea1d5da29bdb0fb81d8e1f6ff0e4579c31c8d5d958b06b2c9be37de43fe83317e079c18805836d72eda19cf86a97912187b39c0350bc790e0b760361c3b1558bae5fe841932dea5b84ac413661da37af425631c5f68ff4040d3c3f7b4bae3c74b0764d776d39cbde0b3c5d75f142ba111d4f604227900c3fa913b6d78d5fcd20df306b8b8f6dcf2321b1f90f55f81cec1b2599bbad1adabec95a2c4b0cfe0d429e056878af68871308cd2e21f94f6d6fef8b29fc9273aa97e6150d20c916e68710baa9b3de541b1022135151b61ce965d87d850eeccd4d74e201312d9ddf6952cb11f756f96558947f31adbf036179029c62dbc27815ddfee70b6652f257702a449381e1a7b66b5f550bf83cf23baac996f0b66fb405f5ed1400b5937d89e897dd40d70973bf716c97c81c1f9e36f83273e63cf489b26772a6d582fe3675137b934d1251cbb3d5bd4ab78ba886103ebe9864367a3048c3c0995e2bd2b76c97bb2e5c1d9e9c51244c202d33cd6a706f6958eff96bb47996a36f19e95350a4b2cd5a5d9a3e4c5240b5c6daa2bea47d43b4a10c767767ef81cab30be74d4891c6b64f0528d82a1e3053ea34231a2d10efa129d8d42ac32f9d8d0cdb559043cfcbc38968c8b031e40da7bc4add0f003c7e50216ad414ca3badb380de9c45713eb46965f8ccf77eae0beeb62529f21431597682605f4e07210a9ab9790b4614917c7b8f4db754cd57a031d03365317d6126de0a89ebe6ef2f877a64a9ec824ca8e6d0017c5249fcad3df09bdf09ced66cd6f840f151ec8a4db239bba62385779742ade58fbe56c4c79c0e8b271f77880953b8a39be239e729bc5fcc831993ae3fe8eb687527956a451dc7031428ebc64c9c426f77827adadd46b9384028a12bbbc4ec7cf7280f2d3fb2dffed142f13aa17f7d42405049d80dbb6ac9762ef56b947baff7012cf08c416935629de0ca1bd8a6f637d7416b780e898413284b16da24bf585eb288c85cac3520927bbcd07a1dfb8373b12ac7ab31f894074a15db8b033659c8e6160e743dc42228594e1db9f8b69f7d8334e75ec6288ab0da7cff63435ca2405f3d1e94b235dea4d61865f5e5ef73b3e86e28e624cab6fee2dd09d01f62d72d18a9fed6f77e660ac1cb3049a6cf0856d5373cda997bff223b10f59d76d6707fa7afc8c2dffe7a5a967f1340a18abfe9b64e3fc0822651a6c52c28b342842b830630c65c5e8cc82e8d06cba10b394207e72a4711d991e5851b3b5ca8e479c445b8c951d759b731b88ed7646f742a276cb4aedb8916c298a22c46103924f0b785febbc0d67acc5a869ba1fa1afda456fdd1a7bed9b29bcb5982fa0ee7eb2da5682f62e16b3a9754ac227df6b703e1b929d3b1142c6c616329d8a564e4a525a0e84194b365d1bd011c5bcac9812195ae3f60f6ec946f46cc2ad0ec7adade8ec2e5f70f1d6e65b20de2714f118ddd25dfa24c1b9c821af013cd54d363c0881a0295cf7129feead0336e2ff7df676665a392f57faf8bf1581715f3634049b2431c077709b3edba503de7a238eafc0c616f29ca4ed0b526ce819a6372f8e25e3f902e1fd7f7387b341948bd79bf3a1f81559138cdd455a098e49a68e64869b15806d363e7a5cd10c8e04ef7c7c28a2281e29daa999bf2aafcfdadf5d55b97c0dbf1b8e77a5351b26069b2eece2515fc08799a6f30896360b3eed3ca9056d5f2c1d8f761458fcc6d9e82091f6f0b3e954f73b9dc682c1b2e2be3d86c6da5b586ecb6d5ec9a57210e1c69467be07c9ebd1e363359274b27fdee6896043272af11e89ca047c388aa35d594d004c580fa87a46744f4f8be181ff374a362e753c8a48a9cf1060d176c08f01cef66e49b2ffc9b2280041ca8bd9cfcd10bc8e0058798ad72a45ed4566a9eed14aa4d03b6f691090515522b9466ee017f38cfdea83c92476f6640f7506862004d1a29c78575b8960cc50aac4092764ea5694dc21d84d65902f5c89384b687b9021ef3e66ed6d45a2f13c198ca722845f1d24b8729a766d2d1383573888b3405a30952c17e90cc6d4a9174bee6f1b0cbc8b449a36dea4593005938735ab45992733414e1bef4ec12368e575f5edd51a7b414fe67ad2c4fbdedb93bd350242fd4e285684e75ab4710982193459f779f7bd5ac12804098b53205bdfef7ae96f7615a52e35227ff29b8a1bd3ca54bfa1eaeaf2e84324119864ed4483fd9ca40fbc00fd5f72d7ca00ff9abfcbade3a8085392e70425691f8158c1ef9e173c10666843f3e14ba2fd5c78bd516e4a6503a11e06f39f6a5bbd657765317b1163f2ed9cbc687ec95515ec56ae75b64cc743c02442d02915e47b8c706ac70b0b5901fb61a5aa8bdc9057eaa42d43b37a5381266ecddd7510dd2a18138805758c2d41e896934cab73c61370ac959447e43bf5b629b904e7bba5ae8f959f923aa7844a898d150df35672635f304f8c55177e9185de1ef8ba82516d56bd27c7e7ba2b139a570f44f4085b275fa05d8f8e65b87a6e30570fa6846d227584ab63ae6293c0d0b8299fb53979a6e796eae7fe8f3439aa3a51889a8a5b1a4514ce597365a27cf5bec9e91558393ebfeeccc6462b7c25f6c03e251546d9fb603b1c25ab756044e042e2f325af8fc2cbb79fcf6f414bad1217cf96f21bb0d48c95c35abee171486d8bd0fa0b485b32f0e73dcf6f05a5475f95f3359634c4de53f44d1c53e4ec3264a82f635258c5b4d8bc912ba3b5503c53b1b239d44d3799a62dd3913871b0ed6fc87f186db1a40b2fe81ed197ab0df57c63de250f72ad592da936177e9f154b90625f76e86cbc2cd2f310d427330559b8b26f685a0a81d652562a3e3c70dd17e31b10b1c55208a551daec05aad5c5dfb32eb37a9dbfb4e43afdeb2d2dd27528c8dac2d043b0548ea7c2b0ca74ebf7dc4da83a8205d227e813d21808b11dec1ed78cc9fb489a0149eccc352e5d22f69b0c65993ec5de6f0ad0c20c936d35c26eb0f4cc61a0f64a376bd91ef980392fe99ef9e1845f1ccffd52b13679d164c7e917816daaee828a733ce4baeb1763ad59e9309ad1f6569dc7882b947032ce67ff0bb1f80362779455ce5741708931b8972ad67943161f6d2a9e4b376b07e3f5cdaff63b769b463be0c2e0a848211071e38709ce089d0413bf7bf9464fcccd03f16ae31c3a607716ff8f52eedabfc4f645c2ed293dee63f3434fb12b5024bb5cc16b0c03ebb2e8c2af1ef088e863cb75ecdcfbbb61ccd394954357e3baf7f7f2a137416073d0dbec002a60a5cadb5d678cbfe91d84bcd31b2144454c5677e64f9ff400000000000000000000000000000000000000000000070d12161e21" +} diff --git a/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-3.json b/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-3.json new file mode 100755 index 000000000..85f6fec1b --- /dev/null +++ b/ethereum/core/src/test/resources/aere/pqtx/wrong-chain-ml-dsa-3.json @@ -0,0 +1,6 @@ +{ + "id": "wrong-chain-ml-dsa-3", + "expect": "WRONG_CHAIN_ID (when validated on 28001)", + "alg": 3, + "raw": "0x50f91c64820af080843b9aca00847735940083045f289400000000000000000000000000000000000000010180c003b90a20fd3c43f5fc7807747a73e1d8e78cd9e611ad6bbba9b264534594174b49082aeab827927b335526cc50c2f0368fc666efb79c34af8ee90427d1718736acaad47f5959b9b26457619c07c2dda553d55a7498e30a37c92909f6b37c246dca4e8fd24d4cccd811396d276e5d11f1e8d14bb9eb4d5ec49798202422edd57ea4d8c0e8c6388e9c93a0ff2e52f7ca2303e40300c50c926a7da22919be462e2dcbdb3ec235b14290a282ee76a04f4bf7c5e2ec5c8fc0aaac72ce4f8fcf0d42b9fc3c4049ab6dfdfa12623d89c0d96434a8e13cb6f79ad6f4a8102f9a0bfe582d967372d8928ff9d7d7393b22ec1386ee91dd196eb9c349a6a12f7504e66a096eec0a8ae98e62275f6b84fb40a81a390c6ef0102c8fd2c11d303745b8fc49e638e6f3004961724a977a18d81efc67e37d0d44558e28cf9015dfa08eff82004c4a53dfa40c2451fa03a987f70c855dbee37e36480863044165e6d46d4c43278091317beab6f301d61c8f54f94ee88fa358c9aed6e55b80b4196e79a3d7251ede25c4baef8129882a69789df3a8262941199ded7bd381de00c257199c18e9086d9ce3f72c6d95c0a4d109a3a15474805f0dc06649a16a7805e8d74bd1af7658f5f9ef726d560595ff9f072d4cfaaf61283087843b904b0f5670ca551079c759d4a2839a71505e007cb5d49b0437b87a080fab5e2efdedd1d01f0f1ab72f0e6129a2525fc6e9829b56ce9d9f287a5bd80be8b1556e4ca82eafc60ec22315448768a72e45d4d956c16ee48a0658e307f81ee0f695f1b1b747d1d533d8da720f088b64608b1edb2d4d27247b2cd35e3d94e1256a3c5c944bbafe07b55ca74df4ec0b869733ddb466717a16e98af4ec310d046c90046c024fb33fbb2ffbb105d41bdd0e0af27b1239aa4d92b6ef8d727e51372fefc3b5c8bc6eb585a0ae2dd9970009555c2c2ced5e5a1e97c659565b6139dc4f3bae788e21f9658affa8fdb6f4733f7fa83fefab91a030f8ec976b8263c17abcef46dc22456d5347eea7c30dd25bdc3caad7cb2010f06573d56b6e5d28e6e847d8df8f18d6a2655ea66fe3c8e7e4ef192b5a8aeb35f8469277657b77155142c7b1653d5eb9cf9c4d69bbc5746e0c1876e330f9016a2f5343ec60b2f35ea380169a2bdf102888e6aae7e797d0bce73834f418018e8e55492da8236a542a999d9eea55bd52ee2e59feb0329d716c78c0bfcd79dc27cd9639399d2fd99d2fc9c4900ad60bdb8221501038ec4baadd2ac4830b2bfe1e20804c818c8e089661e7d842bc4e566fa0bc2d7968a44f8df0d4e88e494fc7bebdb695d3a8edf6a2703817b0f8c1a55569ac4a8ff0931137f075797e9744135a3fec6c767af26d4592a9022271a4052b1f1f24f072bd5ceb1d19e02b0bbf31251a7bb8b723bd3da02f59ca1c0c91bc10896970a1e0f8e0fd5b755da58d70be8935f65661629a9f833b35810113ce80125f8ed7a031cfd5eb1475b597856b4ce7629a9429d840a3457bbd70c05c73c6ce84dd59f917a24d06ca8743225ab8c266e209fbadf57cdb587df96eedf54c04fb3f83ec0dddd1d8bf9051c6de4db3aa099f1779f3f30f61f432e5c8f6b7ac4ee6c6dd6fce667556df155ddb2002735fb7addd8acf74863ccfe04a3088317634eb47e56b18c79f31318ac5e448a9094b5c2c70b44dbbbff7c235cef4701d504723b032726d009c6d7f527e645a23fc1ab478e6e2699211694d575bd436d778e7ae53868c63dfb78f591d82b979585cec8bbcde61f375e783e97e8f787fb392fa4f0bc3e9010aa9ec3cf6471bb16355c3ed3fdf2ee5b95ade86371d60fb0699a851770a212d0e0eeb3f20df78ab180343fd79a9d04d8dc56d9fe3d820b27d98d12275a40d270f4181aa1a18305c8d3469a954b2e85405a394684cc234702a6cb01c04ccc941a4392cf64ba31bea700d339152fce6abb0dbe84823b8d3b18258a29414fd52c91ccbc198e101287b79d8bd0e5f4b05a14a07055e66ea37d781934840a204638bffda400113bb1344126fe1c2ac1e57bb861c3d35349b1fba0c11e12921262ae52fb2e0bee444f8197e2817b9356e10af67e794a7967055936bfcb51f4be6fc5602a8df97ddcd73afe83c02f00d4f1d8302bd2e826d4c50fd3ded9a74debd0e807b694e912a8a3a800f5b983e171898874b77ea305ede4abdf0db5ca84a8a60b184374c08066537b08d42a609b97039ff8905bccc4454188b051c5d1e574e1e8b74cc5cbded064a5374c55f17002ee9b17447fdc324a12e3f2f414b491cccf20c9f98820461f4c7d61355a30f1a6cbb2fe7403b90587298fcc9500519451e44225c750b8b32a649ea288eda389e596390a5386652dea5d0e096ee270bcab9da0c3c4ba464f44172732a748e339cbfc8f0c1ee3187225e2fb29e67ffbd84df8acf759c817d628e03a245e9ae0cf00939fa12964e8dc124659eea8798b097ba52480532fa11194e4623ff63f6cc1d17c7080bb2c1459fe8cc9b197b89ba91986b7bfa61e514bf5c60f981e63baffd9fce44af87ad73fba197e46790fc03f8a46aa6d7590f47e08daedd7f564685208ee87da84b04b11cdc0c020bb26b0abdad3c1340649130e26af9c7651533313301e8b517a84c807d86a4c0cff68566d34da4111d67bdc77ef5f49ec7d83af24a143bceaee020acce02499c725ebc341a86d91c7f63dd962ffcc09fc0b5673873ee55cea4bba69b5058e4b364fb3802832d5118774790dd12eed78330412dc877cc034309a7e292ebee955a431fd46faf7884cf3bd5ab03d02b8784af2a84bb907ba5f021fc332f638a2d4b6451ea0a2cdee6ff1621d698eadfc99d6f405003f300e321a9e80ed3b577a899fa7dd891b53cab8acaa9fd3ce02640eaa75646f134c190817675b9e4a688d0668528fa3b378749bb6b1a0bd16873e89dfc927dcf568fc3cf94ac49d289ba1fb9c58a74574c8fbac321db256bf919e9432d6a8ae9a0dae900901f436b13d0c2b753a5eb6fcef03301d7faa15ff32ec0730335b13394bff66ea83a7043f9e1df5962671ff2d2759db234a4a4fa47fd3a9359bb14ef5b5fc398836d42afcc5d5f252b1b061afc6a0815b3a7586d25eed5ee52c56d2389b8f2438649ee652b431d3cc4262c6e5ea1c0ccec21aa6123e88b4bc933098576bd78cf5bcbbc278ee682029e05e91aac2043ad3ec1d3d97f6ebc6bd5faffa5bc71328cd4351bcb9a0d8d1ea9253b97b08c8c53b20e29703568d5d7dfa2bfa6aeb3a93043e4123116a125311695a11c8538658210971d7763ed7870c1309893909e306df22fe968612531e58a91d19dfe2c658ade19c8e0900c779af8ec333d19552e42cdedbe13ff85d99b10baf8daf70951290db56bc7ea049e6b468b6546a7f3ae77c2e14770eed1ea345f0d139336af4eee686ac2e73bd4262cb802e0173fb872a77cd2c0f3421c497b0260be79ae29d04d9a9da9d7bc101ae3ec9dace1133332f05b7b82aaee577c06c0d2a8eaa8a96db8b899cb3240cc4dca4f8eab513ad5b3529063b5df3664dde0db1e0ae5c29e69f011076fc7edc4261d043f38f1c68645466c9a5e685a07393b7e2f8f74db86742ba5ac089b45a42df3f943842747674c1653aa2a8ef282f64e7ec2ce1fada994288a5f9b95da4bc083ea008308b91213821ea6fa73a5016d6bbd3227853ecb797d9d49be7e4f6fa69ba1f84c4f509491e1a07ad0af5fad203717c10931dbc67c1c1a9d90591f8951f595dc96357d91e202ebae7955f0e45245936c750840ffd8df89e0f2789e427c79ac48d58982a6e087bf4235920efc666854459d6e4979a308594b7284181a9cdc011b48e1520454c48443228ba54f286952331533db7bcfb04df5e4cde37ff417dc4444adf86a4c4cb15be04b0fc9cf292ff313ff1ab5d1ecbffd14fe67526d4b6bc29c838ccbb2a442d08df1f8686da94e80867f9cef8b96b62656778cbad55c43f24b0915e6ace48353025c135a5c33bce233363ded2753716e61f213b04f2c429a797460e1e4166fed83575632b70540218afe616cd89fb77a981f60952c58a2246bbecf6606c005fe50caa3c3669c5b019e3ba52773aecf0fdf06d570d4ebe10241fd5694127365088a8045523fa639f6df29c6ed9ecb839c27582b133867f2f4b9395cae52c2606176d8ef04d32ce7bd563fbd3f2f3b9f7fc0468bbb8c770a563c278e22acb2d8a59e5e37538f07b98fbcadee17f23e625e93e76188bd1ea77152cf39cf05e568b95a3f5188920c0e8ab46e4ad9d9e6533de563334cf5ed7cd4e62b43a8e9455d4d232903dda4774c7dd9bcd39b01c2744ad47b361469c54aa589a35c798365bf8e6748465c7fffa0b688007f5f814953f87c03c6b3bf682ba6e70adc817596410d1e581e8c0f237e889bb4d4a09be8514707573b6299414845ef8ba7c9fade369afd8b1d7078031ad82bea47e516a2e5827a67591e85e628930bc81f20a5733270b8285922eb6fdd1f23cbc47f34563578db8433eeb007c428e5815e15bf6232d1801a39deabbb77a1a2bef02d16cc88b975e1835c105bdc813f7faaf6eecf601a4a67e30053c7fc92aae3cfc52900e471c3e8b70da92395c6f46cb6930f1ca80fcbffe73d5c02208b62d5f5368d0c7fb25ee9229284e10ac2278556f7026ba0d3bd5fcd1e04120b728a2f308366757fe15d176f72df5e566a31aaa809a97745a20352d4d698d945da8476defb6052414fe086e326b558b64447e3c9dac0b1f4ce5a06e678426d48f3436597cba43cf8af80b94c3813832bacbcd5d7c167fdaa1ad13afdc0ced8c3da011c695a33724bcdd9902eb545ec9aaf7038cf39600b9dad3091adc79a8b0e6b2fb457260f7ff789dbf78431ac839802a8f435e0b29b3c236a4cf8c7c138896b6724ae5b3690503ca21977bc6c5e29506702292a120e59ef8269682389ecbd41fb5aae0f6f04d0bd1942a527bb5152eb57843c6f64944996972eee48cce5d8a69ced00b240345dea932b5e32e4056f959b77051f10da85b06e6b6b6e4e191463e5105f55f1772d8117448f4b5511a2423475130ce26bdec44150b872116667791aea4c083f3b0abe44f19f841019911236179d280653dab71efc7fcd82bbeb56e5ede3bd7958a94b9a1ff082d82586ea876f6f3f059dec352b6c69ea86043137e547b62937e7a806a445528fa15b71e8cc987c587d3382ac00bd307b2c2ae5ff99f30bd1d1deb08976f9214788735d772b2ef04d827280e6dd836de156d1ac3a4eb530cb4c701ca69d51de13a6681de8d57dda2787a14bb5ebd934993596f6a98fcbd50339f0222da1df81247c5a0d620f6cb4f5ef311bdc66546bd3a5e2a5af0efa3c6158d7a6bb493ea89d8eaca4c07ec56189283118b7cadf32abbe1f65293973a1a55bae933f09feaaa3c6058083bec065f15fc795dc8e824f1ce941fa09f4d3512f4edd6fcc4c5b2f10d059087638d2bfcdd3f9e24383fd7466a1982226f8696abc5df1e51648fc165c46a0012c49e33a0de4ed6ba6215889cc923c8746407d38d856eee5c6f81ddd1b12d0511c79c0c6d0e88d09fc5f2f16e3f09b4c1754e26aa554840e707836cf3cedce57e463e0aa1a7be552d07594f3dd77cb0e76d9412faa917abdd50b3ce779d8c81019ec9d947f5717cee5a4e98c3e30e60fd4f34c66b29be5dd96d0ec235f6340464948976334d47a0e49198e77980acb97bcf77243f5c9eafdb8e742120065b8eb4348027a7dd251e9244ff3a2776d1783a449bcfb4dc4b3370362bb68ae3a61f842def75fcdb248634441092e25530db3b7bc2ce203231387d34c8195dbf293a2e680a2dff9b74e30f2f00ce4e84a309f1255ab55af3b2ce5b7a50712cd1d13ebcbb48dfa08b5edda1621ad30eb3e72562a2d3baeeb741514ddba8234d365e67ee35adc7a7902df9ac3f3f885da7a9fc4b6580d97f2dfbfd110b2fe313dd2b023ae1e98488742cad89bf33303ea235ce1bfb87577a04dfd3c1e1f952422bec2c5ef6a90aef6c39777d2c1fc283261b734fe19ff85777a63ddf6da7b6434e2ea8a2f6d0db84fff632a1d8e596fdb92b8d93a7a9a9d2a113032f96b1ba8ccc804c797f9ea6f65453c0ac308d10113abdab820817805547c0f1c392eacdf950a1bb88a85679461d2e2dff041037822062476311fd328173a9718934c3f2eeb8e6cff5316d44d5a870bb90407936c8188b9f8d4a26e92124a220f64dba55fd4ca34c39fc575899f8bba24d846fdd53ea0c0be00a9a5079406fbee0e83cdf8f360238e2e2c36b1c61b525c42a60d86bb79240bffc2fe6e0f5d46b09bc745ca7919a872461409298c61deb8648ed88774eb701ef565a0e1fa69bbefb87157441546e21371b98925e06d51124161b7ae678b84ce504360206a84f388557b99ee7774fdd0f411f300198c9abf5dc20a4f97d675dfa194e77266b7d8d47b101a8cac292d8b9945d1ad42d1878e8f5f35b0ec80281f02d7bfeb65226ad77704d7f6bc30fbcc6a4be54c8d162fe9529af1370f44ceb0da10ea36d389b6936fc9957f04a19ea796d2c5face0c8ee7bb23ff2db8a0b77a1cff4b169ece8d636663a3bcfd2d35bf44c251b8689338b76914d17f968ceff5e8de1719631729429371e5faf9cbb2067e891c658d0cb98276b16851b432b885d94d8efaa43e40ce4d09a97c1b7dca5d94d595629c44b41e75d2cda9bbcfef02adee54b5367a687428f005a1324eb8411f4468b0565ffc6b17953fc42a015e9acd9ae1e078a54ddd3b7355109c0eb56ab28263a02ec012993ebefa4060e1dd6347414681e634843baf9ee268fdbe7d00f22d05356231488042d08658f350b47c525d468bf63517758bad63c83821375d1c9f1165d7a3c829ac39a41200aabfbf03e8bde55c379e0f8ea8f81f59784212ec997612fa1aaed3f3ab82035cb761365982d4acb7e4713b9850511c3ad88b0844910e0968333ea3dba07068ad671208d1f4704e8d4d5b55b6b3ea7a4a70d2cffea0e8927bb215c1c628fbdaa6ea2d62d9fbcf274b56d7ffd5639ff2626b37ebba7f7add88dd978a5743d673e4ec7c82836de153d84ead5d378d290b2fffb2e5095496e7ca773d2db364896700ca09f0148df30d7c9ad70448503849831a428f602182eef6353db3c68f3100501e2575e31f658ad8fbe6f6f21f6d7dd369ecd1aab3f944d25ccb12c5fb2cecc39d32587b479f787482e38d60da3b15757816c4d0de0ac1dbfa4f6feab2e15be5b343227dbcc11fda877e9231d0d4cce4fdb0e9b73d0946fb60241613d51b658a2fd828d0931b1d2b7cdd50ee00c6aa454b0483747647b33d3eb9a4ce5f46755ea957202286a0e414940c570f7b8da652f3c7a0ebb28dcdfbc0a922f9f19bde6101563f898877ae298a51264cf5c692d97c62efab162d6265ea36aa59ffc86ba42d9f17979df28eb2f77045dbbd99d53e3d4553a9b8d4c7cec4d74f4f3d6a24129f7d48ef74dabd2804acaceb715fae1462446a06da637d196f19d02830a3f7ba8f0de5df1d080dfca719d6992317284a5d250c644e9dfd86930fd7224f199c4f52b7dfffc9767c003d066c43e980516a1bb2fcc92a3d5de9787b5f34e3bfee0ae38b97f84bc9f521b2f4e5c34787a8ea0a4c4daae98753a15af3481c41caa45b78cf98452cb7ec13ece08355d16be12f2c5cfc6aab958cb6273117bcff01a34940ef94ee8afa76360afac39aaeed3f54e7de726c3dc224de85cd92f57f3b105db6ad3e5f194fa33646984de36299958effd36bb1f9510b79f975bfdada10b334ab6a7f0f8337f084a7bc3db1e7af1b8d6b6a2e7061a80efb4ff5d7198175eba1c12e6acbf5092f0de03789a7de9b0cb0b385ed38f8db4c65628f674768ae91d256faa8152595d1270ca3d54249a3b1df84097f81d618297bb042750aca4f20d5a056689a5e8cebca0c3e36cc6333a16b9c7052517b5793552c1f625f8ec14a860cfdda306fafad0b77c47b47136f61ed8b9baf08ae974012c43bc00501f8044109125d5ebb450063fc6a954ab1bdee806882f8e04404ba28b6136c94f8f0a9fed264f5943e90d0c0edec69c668813d34d54bb6e43d90a9509d9dd7761431cf02109cefe77ff28cbd8915c116023f38e8457638dc11e9fef20ff2a6fb5623760981c8d267a18a64e19b1b58bf038a54dc90ea235346bd44ec79f37a20c6171ddbaab5276ca4dac6ebd79e5683727ed773ed29993b07de6905a295fb90d01f2f275d6a4cbcb1b6856593451083b988d1a0fb1bfd316e94e9f006a8011809413d695316d7477ee7dc327451aa7abfd1b91984ee887708153ffe1a4294aa561692db5d097dc9df1136c2bf29758760a422afb7e562d8be5769dd192c46aa95e3c8f9b6ec7d618b365137908987a75be43e511bb99f94936f1ab5fd6f5c93dcbaf8d0c017f6a24740b9cd49a1cb38a4e34397ce65265ed7276706d875a98adc60a7267a30e7fb39ee43fc930e697bc23972aecbe8c4c9059b8a43a26d4214d5162de2b80e8317b2877d2396164bd7240b411517ca0f57eed764e3319aee03e3e13570e75292ae6fb8c09a70f270325add11b3c7b0095ec721a35adf071b8db007d7b9a2408b62c1b17f0388250bfbee0dd7b9aef7eb8ce50df5bb18c441154a9da18773c57731a4345354ae6e03d4e863504e2adaffd618aa7aa44789269f83af69fb32a9cfc7fbdd6b316d03e2a9ce31509e05a07cb6c6ee6e127dd3b1c13d89e50f7407fc2e9ab99c1f6c7129589a1c77242392e1e08724fe2f6de96e87b4c4506a963e84eb3461bc9e0cab6094b7dd291e8e421823a6bc48d0d1a242fb8b0ca0a7b1f4124e4c262d5294b465eeaba288047cf6f24b26bf17dfdb70b09082384bad7c357a9ba33e7b97f290b540906b944240a88efbf89bc909a917f533d2bd3881847458dd8c58032949b43e21323af420a7d90c23977162d68627fa8f8f28659cbf497876b9dba0f2916b89f447d76167acf7ae5fa9769847feeef93deaa892e1e3ba4fbd3be85c9fad2ac7f403614c2a67d06ce3417529a8a866a22c5c10aa5bf07e195ad79556cc366ed3ab2d2f713d60e7e62a1af637aa9bec3ed96ff952fcd7162da28cbcc5999a38b926cee893a7704e325f0724ac383bb2d6e48e3c35d0bae557963a675674d3bcb058531b8b12d1c692b61078dd9bf9b2eeec94ce172b434941eafffb982dcc73e22812cabace33b2516fa45ec3eb82d2ce5b0204340f7f153d4ec65b2f42ce29e3dc5bb38531b666e4fed6485d2c3fecd536719bf758eade6c96086b258947dc694be765b3b9d8286852b18c25f15eca74ab745ac106bb91e2275b69b129cbd14b1c07348d0d157c90bbbfc11af6b4960fbc666cb3c9e4a3c408e6f595a67179e4ca2349c270ffa3d1581d8b9ebf6e9684067d358b6de326c0e6b890bc05e3175662f4c6f44e09ed3305ed04cb16d0635ee07377a106c24e42abeae5efa977446f88b7bb5def5aca2dbbf51e519521d018b5c668622e2b55e66b9b8fdfcde3b8491852907848ca86732810216ea19a9964842c6a3811078e6d1e73ac0d876d14272bd649dc6502816d2e20f7bbbc3026cbef63c6ae6ce07af82a832a06e634c59ca060b9b385a23a8c8bb2651a98f94ba138bf84e5f5a2e60c51962597df442438d9ff5447595d4919ccb4eb362fef3ba49fd94ab48a47f88e2ff009aa09f83ceb512524ea34ccbaf392492aa19ba75a480c16ea43beb1bfe8e1077f2735543aa1131daaf325e1895da07dd555f5a03d9387ee8d0ecdaa134950b7cb1a006587d3121060f97d3ca36e72dc9934a49f6fda29d7dd7fa6755379a0db48f97cd8bdf6ff252b08534b7d377a55bb91e616263467fd381ab0a12947c590cda2d43febbb45ba5fdd9a90d306c20e1b661e62c76232003ba0cde7da5e40e40b6b10cc9b9cca21e4f13daa7a05572e808b2205c37e0628566aef675caf08fa26ac299e866bb58c9fbc420acb2f02bfa6802da6fe81a065de34185dc38a6ec1ddd4b6aa188faa7f5c515614dd1c8bf6870eadf7d2595ddd56185b073be9f18f21285999c6c64a928572d7859e76520132b42398596d7f808392a2da2640546b6ea4c21d24520d59748ea4b2bdc10887a4cc15161acdd462639ab2cde2040e333543525f6c82dce50000000000000000000000000000000000000000000000080f121a1e232934" +} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java index 4c7a60bdc..077f2be57 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java @@ -1,33 +1,39 @@ /* * Copyright contributors to Hyperledger Besu. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.eth.transactions; import static org.hyperledger.besu.ethereum.core.kzg.CKZG4844Helper.CELL_PROOFS_PER_BLOB; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.ACCESS_LIST_ENTRY_SHALLOW_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.ACCESS_LIST_STORAGE_KEY_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.BLOBS_WITH_COMMITMENTS_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.BLOB_PROOF_BUNDLE_SIZE_V0; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.BLOB_PROOF_BUNDLE_SIZE_V1; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.CODE_DELEGATION_ENTRY_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.EIP1559_AND_EIP4844_SHALLOW_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.KZG_PROOF_CONTAINER_SHALLOW_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.KZG_PROOF_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_ACCESS_LIST_SHALLOW_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_CHAIN_ID_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_CODE_DELEGATION_LIST_SHALLOW_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_SHALLOW_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_TO_SIZE; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.PAYLOAD_SHALLOW_SIZE; @@ -143,77 +149,91 @@ public abstract class PendingTransaction public void decrementScore() { // use temp var to avoid non-atomic update of volatile var final byte newScore = (byte) (score - 1); // check to avoid underflow if (newScore < score) { score = newScore; } } public abstract PendingTransaction detachedCopy(); private int computeMemorySize() { return switch (transaction.getType()) { case FRONTIER -> computeFrontierMemorySize(); case ACCESS_LIST -> computeAccessListMemorySize(); case EIP1559 -> computeEIP1559MemorySize(); case BLOB -> computeBlobMemorySize(); case DELEGATE_CODE -> computeDelegateCodeMemorySize(); + case AERE_PQ -> computeAerePqMemorySize(); } + PENDING_TRANSACTION_SHALLOW_SIZE; } private int computeFrontierMemorySize() { return FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE + computePayloadMemorySize() + computeToMemorySize() + computeChainIdMemorySize(); } private int computeAccessListMemorySize() { return FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE + computePayloadMemorySize() + computeToMemorySize() + computeChainIdMemorySize() + computeAccessListEntriesMemorySize(); } private int computeEIP1559MemorySize() { return EIP1559_AND_EIP4844_SHALLOW_SIZE + computePayloadMemorySize() + computeToMemorySize() + computeChainIdMemorySize() + computeAccessListEntriesMemorySize(); } private int computeBlobMemorySize() { return computeEIP1559MemorySize() + OPTIONAL_SHALLOW_SIZE // for the versionedHashes field + computeBlobWithCommitmentsMemorySize(); } private int computeDelegateCodeMemorySize() { return computeEIP1559MemorySize() + computeCodeDelegationListMemorySize(); } + // AIP-20: an EIP-1559 shape plus the post-quantum authorization (record + two Bytes wrappers + the + // raw key and signature bytes, up to 7,219 of them for ML-DSA-87). + private static final int AERE_PQ_AUTHORIZATION_SHALLOW_SIZE = 64; + + private int computeAerePqMemorySize() { + return computeEIP1559MemorySize() + + OPTIONAL_SHALLOW_SIZE + + transaction + .getPqAuthorization() + .map(a -> AERE_PQ_AUTHORIZATION_SHALLOW_SIZE + a.authorizationByteCount()) + .orElse(0); + } + private int computeBlobWithCommitmentsMemorySize() { final int blobCount = transaction.getBlobCount(); return switch (transaction.getBlobsWithCommitments().get().getBlobType()) { case KZG_PROOF -> OPTIONAL_SHALLOW_SIZE + BLOBS_WITH_COMMITMENTS_SIZE + calculateListShallowSize(blobCount) // list of KZGProofBundle + BLOB_PROOF_BUNDLE_SIZE_V0 * blobCount; case KZG_CELL_PROOFS -> OPTIONAL_SHALLOW_SIZE + BLOBS_WITH_COMMITMENTS_SIZE + calculateListShallowSize(blobCount) // list of KZGProofBundle + (BLOB_PROOF_BUNDLE_SIZE_V1 + KZG_PROOF_CONTAINER_SHALLOW_SIZE + KZG_PROOF_SIZE * CELL_PROOFS_PER_BLOB) * blobCount; }; } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java index fe525c431..1ad11b019 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java @@ -1,33 +1,39 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.eth.transactions; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolStructuredLogUtils.logInvalid; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolStructuredLogUtils.logStart; import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolStructuredLogUtils.logStop; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.CHAIN_HEAD_NOT_AVAILABLE; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.INTERNAL_ERROR; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.TRANSACTION_ALREADY_KNOWN; import static org.hyperledger.besu.ethereum.trie.pathbased.common.provider.WorldStateQueryParams.withBlockHeaderAndNoUpdateNodeHead; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.BlockAddedEvent; @@ -432,40 +438,49 @@ public class TransactionPool implements BlockAddedObserver { // Strict replay protection is enabled but the tx is not replay-protected return ValidationResultAndAccount.invalid( TransactionInvalidReason.REPLAY_PROTECTED_SIGNATURE_REQUIRED); } if (transaction.getGasLimit() > chainHeadBlockHeader.getGasLimit()) { return ValidationResultAndAccount.invalid( TransactionInvalidReason.EXCEEDS_BLOCK_GAS_LIMIT, String.format( "Transaction gas limit of %s exceeds block gas limit of %s", transaction.getGasLimit(), chainHeadBlockHeader.getGasLimit())); } if (transaction.getType().equals(TransactionType.EIP1559) && !feeMarket.implementsBaseFee()) { return ValidationResultAndAccount.invalid( TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, "EIP-1559 transaction are not allowed yet"); } else if (transaction.getType().equals(TransactionType.BLOB) && transaction.getBlobsWithCommitments().isEmpty()) { return ValidationResultAndAccount.invalid( TransactionInvalidReason.INVALID_BLOBS, "Blob transaction must have at least one blob"); } + // AIP-20: not admitted to the pool before the activation height (the next block is judged). + if (transaction.getType().supportsPqAuthorization() + && !org.hyperledger.besu.ethereum.mainnet.AerePqTransactionSupport.isActiveAt( + chainHeadBlockHeader.getNumber() + 1)) { + return ValidationResultAndAccount.invalid( + TransactionInvalidReason.INVALID_TRANSACTION_FORMAT, + org.hyperledger.besu.ethereum.mainnet.AerePqTransactionSupport.inactiveMessage( + chainHeadBlockHeader.getNumber() + 1)); + } // Call the transaction validator plugin final Optional maybePluginInvalid = configuration .getTransactionPoolValidatorService() .createTransactionValidator() .validateTransaction(transaction, isLocal, hasPriority); if (maybePluginInvalid.isPresent()) { return ValidationResultAndAccount.invalid( TransactionInvalidReason.PLUGIN_TX_POOL_VALIDATOR, maybePluginInvalid.get()); } try (final var worldState = protocolContext .getWorldStateArchive() .getWorldState(withBlockHeaderAndNoUpdateNodeHead(chainHeadBlockHeader)) .orElseThrow()) { if (worldState instanceof BonsaiWorldState bonsaiWorldState) { bonsaiWorldState.disableCacheMerkleTrieLoader(); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java index 86592933a..f3b958463 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/BaseTransactionPoolTest.java @@ -1,33 +1,39 @@ /* * Copyright contributors to Hyperledger Besu. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.eth.transactions.layered; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.core.TransactionTestFixture.createSignedCodeDelegation; import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SignatureAlgorithm; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobType; import org.hyperledger.besu.datatypes.CodeDelegation; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlobTestFixture; import org.hyperledger.besu.ethereum.core.Transaction; @@ -173,40 +179,43 @@ public class BaseTransactionPoolTest extends TrustedSetupClassLoaderExtension { final TransactionType txType = TransactionType.values()[randomizeTxType.nextInt(4)]; return switch (txType) { case FRONTIER, ACCESS_LIST, EIP1559 -> createTransaction(txType, nonce, maxGasPrice, payloadSize, null, keys); case BLOB -> createTransaction( txType, nonce, maxGasPrice, maxGasPrice.divide(10), payloadSize, 1, BlobType.KZG_PROOF, null, keys); case DELEGATE_CODE -> createTransaction( txType, nonce, maxGasPrice, payloadSize, List.of(CODE_DELEGATION_SENDER_1), keys); + case AERE_PQ -> + throw new IllegalArgumentException( + "AIP-20 transactions need ML-DSA keys and are not generated by this test"); }; } protected Transaction createTransaction( final TransactionType type, final long nonce, final Wei maxGasPrice, final int payloadSize, final List codeDelegations, final KeyPair keys) { return createTransaction( type, nonce, maxGasPrice, maxGasPrice.divide(10), payloadSize, 0, BlobType.KZG_PROOF, codeDelegations, keys); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java index 1b48609ac..ccbf03c38 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/layered/LayersTest.java @@ -1,33 +1,39 @@ /* * Copyright contributors to Hyperledger Besu. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.ethereum.eth.transactions.layered; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.awaitility.Awaitility.await; import static org.hyperledger.besu.datatypes.TransactionType.ACCESS_LIST; import static org.hyperledger.besu.datatypes.TransactionType.BLOB; import static org.hyperledger.besu.datatypes.TransactionType.DELEGATE_CODE; import static org.hyperledger.besu.datatypes.TransactionType.EIP1559; import static org.hyperledger.besu.datatypes.TransactionType.FRONTIER; import static org.hyperledger.besu.ethereum.core.TransactionTestFixture.createSignedCodeDelegation; import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayeredRemovalReason.PoolRemovalReason.INVALIDATED; import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayersTest.AuthorityAndNonce.NO_DELEGATIONS; import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayersTest.AuthorityAndNonce.delegation; import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayersTest.AuthorityAndNonce.toCodeDelegations; import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayersTest.Sender.S1; import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayersTest.Sender.S2; import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayersTest.Sender.S3; import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayersTest.Sender.S4; @@ -1789,40 +1795,43 @@ public class LayersTest extends BaseTransactionPoolTest { return this; } private PendingTransaction create( final Sender sender, final TransactionType type, final AuthorityAndNonce[] authorityAndNonces, final long nonce) { if (liveTxsBySender.get(sender).containsKey(nonce)) { fail( "Transaction for sender " + sender.name() + " with nonce " + nonce + " already exists"); } final var newPendingTx = switch (type) { case FRONTIER -> createFrontierPendingTransaction(sender, nonce); case ACCESS_LIST -> createAccessListPendingTransaction(sender, nonce); case EIP1559 -> createEIP1559PendingTransaction(sender, nonce); case BLOB -> createBlobPendingTransaction(sender, nonce); case DELEGATE_CODE -> createEIP7702PendingTransaction(sender, nonce, authorityAndNonces); + case AERE_PQ -> + throw new IllegalArgumentException( + "AIP-20 transactions need ML-DSA keys and are not generated by this test"); }; liveTxsBySender.get(sender).put(nonce, newPendingTx); return newPendingTx; } private PendingTransaction replace(final Sender sender, final PendingTransaction pendingTx) { final var replaceTx = createRemotePendingTransaction( createTransactionReplacement(pendingTx.getTransaction(), sender.key), sender.hasPriority); liveTxsBySender.get(sender).replace(pendingTx.getNonce(), replaceTx); return replaceTx; } private Optional getMaybe(final Sender sender, final long nonce) { return Optional.ofNullable(liveTxsBySender.get(sender).get(nonce)); } private PendingTransaction get(final Sender sender, final long nonce) { return getMaybe(sender, nonce).get(); diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java index 52771a088..4dd3f52d5 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java @@ -1,33 +1,39 @@ /* * Copyright ConsenSys AG. * * 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 + * + * Modifications Copyright contributors to the Aere Network. + * + * This file was modified by contributors to the Aere Network, as required by section 4(b) of the + * Apache License 2.0. The copyright header above is the upstream one and is left exactly as it was + * found, as section 4(c) requires. The change itself is in patches/0006-aere-pq-transactions.patch. */ package org.hyperledger.besu.evm.gascalculator; import static org.hyperledger.besu.evm.internal.Words.clampedAdd; import static org.hyperledger.besu.evm.internal.Words.clampedMultiply; import static org.hyperledger.besu.evm.internal.Words.clampedToInt; import static org.hyperledger.besu.evm.internal.Words.numWords; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.operation.ExpOperation; import java.util.function.Supplier; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; @@ -139,40 +145,53 @@ public class FrontierGasCalculator implements GasCalculator { return clampedAdd(getMinimumTransactionCost(), dynamicIntrinsicGasCost); } /** * Calculates the dynamic part of the intrinsic gas cost * * @param transaction the transaction * @param baselineGas how much gas is used by access lists and code delegations * @return the dynamic part of the intrinsic gas cost */ protected long dynamicIntrinsicGasCost(final Transaction transaction, final long baselineGas) { final int payloadSize = transaction.getPayload().size(); long cost = clampedAdd(callDataCost(payloadSize, transaction.getPayloadZeroBytes()), baselineGas); if (cost == Long.MIN_VALUE || cost == Long.MAX_VALUE) { return cost; } + // AIP-20: the post-quantum authorization bytes are charged like non-zero calldata (16 per byte) + // and the verification itself at the algorithm's flat cost. Zero for every other type. + final long pqCost = + transaction + .getPqAuthorization() + .map(a -> clampedAdd(16L * a.authorizationByteCount(), a.algorithm().verifyGas())) + .orElse(0L); + cost = clampedAdd(cost, pqCost); + + if (cost == Long.MIN_VALUE || cost == Long.MAX_VALUE) { + return cost; + } + if (transaction.isContractCreation()) { cost = clampedAdd(cost, contractCreationCost(payloadSize)); if (cost == Long.MIN_VALUE || cost == Long.MAX_VALUE) { return cost; } } return cost; } /** * Calculates the cost of the call data * * @param payloadSize the total size of the payload * @param zeroBytes the number of zero bytes in the payload * @return the cost of the call data */ protected long callDataCost(final long payloadSize, final long zeroBytes) { return clampedAdd(