Skip to content

Commit f4d3760

Browse files
authored
Merge branch 'main' into update-gradle-plugins
2 parents f9ff1a3 + 9f8f121 commit f4d3760

File tree

3 files changed

+201
-0
lines changed

3 files changed

+201
-0
lines changed

besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
import org.hyperledger.besu.cli.subcommands.PasswordSubCommand;
7979
import org.hyperledger.besu.cli.subcommands.PublicKeySubCommand;
8080
import org.hyperledger.besu.cli.subcommands.RetestethSubCommand;
81+
import org.hyperledger.besu.cli.subcommands.TxParseSubCommand;
8182
import org.hyperledger.besu.cli.subcommands.ValidateConfigSubCommand;
8283
import org.hyperledger.besu.cli.subcommands.blocks.BlocksSubCommand;
8384
import org.hyperledger.besu.cli.subcommands.operator.OperatorSubCommand;
@@ -1493,6 +1494,8 @@ private void addSubCommands(final InputStream in) {
14931494
jsonBlockImporterFactory,
14941495
rlpBlockExporterFactory,
14951496
commandLine.getOut()));
1497+
commandLine.addSubcommand(
1498+
TxParseSubCommand.COMMAND_NAME, new TxParseSubCommand(commandLine.getOut()));
14961499
commandLine.addSubcommand(
14971500
PublicKeySubCommand.COMMAND_NAME, new PublicKeySubCommand(commandLine.getOut()));
14981501
commandLine.addSubcommand(
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright Hyperledger Besu Contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.cli.subcommands;
16+
17+
import static java.nio.charset.StandardCharsets.UTF_8;
18+
import static org.hyperledger.besu.cli.subcommands.TxParseSubCommand.COMMAND_NAME;
19+
20+
import org.hyperledger.besu.cli.util.VersionProvider;
21+
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
22+
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
23+
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
24+
25+
import java.io.BufferedReader;
26+
import java.io.InputStreamReader;
27+
import java.io.PrintWriter;
28+
import java.math.BigInteger;
29+
import java.nio.file.Files;
30+
import java.nio.file.Paths;
31+
import java.util.stream.Stream;
32+
33+
import org.apache.tuweni.bytes.Bytes;
34+
import picocli.CommandLine;
35+
36+
/**
37+
* txparse sub command implementing txparse spec from
38+
* https://github.com/holiman/txparse/tree/main/cmd/txparse
39+
*/
40+
@CommandLine.Command(
41+
name = COMMAND_NAME,
42+
description = "Parse input transactions and return the sender, or an error.",
43+
mixinStandardHelpOptions = true,
44+
versionProvider = VersionProvider.class)
45+
public class TxParseSubCommand implements Runnable {
46+
47+
/** The constant COMMAND_NAME. */
48+
public static final String COMMAND_NAME = "txparse";
49+
50+
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
51+
@CommandLine.Option(
52+
names = "--corpus-file",
53+
arity = "1..1",
54+
description = "file to read transaction data lines from, otherwise defaults to stdin")
55+
private String corpusFile = null;
56+
57+
static final BigInteger halfCurveOrder =
58+
SignatureAlgorithmFactory.getInstance().getHalfCurveOrder();
59+
static final BigInteger chainId = new BigInteger("1", 10);
60+
61+
private final PrintWriter out;
62+
63+
/**
64+
* Instantiates a new TxParse sub command.
65+
*
66+
* @param out the PrintWriter where validation results will be reported.
67+
*/
68+
public TxParseSubCommand(final PrintWriter out) {
69+
this.out = out;
70+
}
71+
72+
@SuppressWarnings("StreamResourceLeak")
73+
Stream<String> fileStreamReader(final String filePath) {
74+
try {
75+
return Files.lines(Paths.get(filePath))
76+
// skip comments
77+
.filter(line -> !line.startsWith("#"))
78+
// strip out non-alphanumeric characters
79+
.map(line -> line.replaceAll("[^a-zA-Z0-9]", ""));
80+
} catch (Exception ex) {
81+
throw new RuntimeException(ex);
82+
}
83+
}
84+
85+
@Override
86+
public void run() {
87+
88+
Stream<String> txStream;
89+
if (corpusFile != null) {
90+
txStream = fileStreamReader(corpusFile);
91+
} else {
92+
txStream = new BufferedReader(new InputStreamReader(System.in, UTF_8)).lines();
93+
}
94+
95+
txStream.forEach(
96+
line -> {
97+
try {
98+
Bytes bytes = Bytes.fromHexStringLenient(line);
99+
dump(bytes);
100+
} catch (Exception ex) {
101+
err(ex.getMessage());
102+
}
103+
});
104+
}
105+
106+
void dump(final Bytes tx) {
107+
try {
108+
var transaction = TransactionDecoder.decodeOpaqueBytes(tx, EncodingContext.BLOCK_BODY);
109+
110+
// https://github.com/hyperledger/besu/blob/5fe49c60b30fe2954c7967e8475c3b3e9afecf35/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java#L252
111+
if (transaction.getChainId().isPresent() && !transaction.getChainId().get().equals(chainId)) {
112+
throw new Exception("wrong chain id");
113+
}
114+
115+
// https://github.com/hyperledger/besu/blob/5fe49c60b30fe2954c7967e8475c3b3e9afecf35/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java#L270
116+
if (transaction.getS().compareTo(halfCurveOrder) > 0) {
117+
throw new Exception("signature s out of range");
118+
}
119+
out.println(transaction.getSender());
120+
121+
} catch (Exception ex) {
122+
err(ex.getMessage());
123+
}
124+
}
125+
126+
void err(final String message) {
127+
out.println("err: " + message);
128+
}
129+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright Hyperledger Besu Contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.cli.subcommands;
16+
17+
import static java.nio.charset.StandardCharsets.UTF_8;
18+
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
19+
20+
import java.io.ByteArrayOutputStream;
21+
import java.io.OutputStreamWriter;
22+
import java.io.PrintWriter;
23+
24+
import org.apache.tuweni.bytes.Bytes;
25+
import org.junit.jupiter.api.Test;
26+
27+
public class TxParseSubCommandTest {
28+
29+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
30+
PrintWriter writer = new PrintWriter(new OutputStreamWriter(baos, UTF_8), true);
31+
TxParseSubCommand txParseSubCommand = new TxParseSubCommand(writer);
32+
33+
@Test
34+
public void smokeTest() {
35+
txParseSubCommand.dump(
36+
Bytes.fromHexString(
37+
"0x02f875018363bc5a8477359400850c570bd200825208943893d427c770de9b92065da03a8c825f13498da28702fbf8ccf8530480c080a0dd49141ecf93eeeaed5f3499a6103d6a9778e24a37b1f5c6a336c60c8a078c15a0511b51a3050771f66c1b779210a46a51be521a2446a3f87fc656dcfd1782aa5e"));
38+
String output = baos.toString(UTF_8);
39+
assertThat(output).isEqualTo("0xeb2629a2734e272bcc07bda959863f316f4bd4cf\n");
40+
}
41+
42+
@Test
43+
public void assertInvalidRlp() {
44+
txParseSubCommand.dump(
45+
Bytes.fromHexString(
46+
"0x03f90124f9011e010516058261a89403040500000000000000000000000000000000006383000000f8b6f859940000000000000000000000000000000074657374f842a00100000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940000000000000000000000000000000074657374f842a00100000000000000000000000000000000000000000000000000000000000000a002000000000000000000000000000000000000000000000000000000000000000fc080a082f96cae43a3f2554cad899a6e9168a3cd613454f82e93488f9b4c1a998cc814a06b7519cd0e3159d6ce9bf811ff3ca4e9c5d7ac63fc52142370a0725e4c5273b2c0c0c0"));
47+
String output = baos.toString(UTF_8);
48+
assertThat(output).startsWith("err: ");
49+
assertThat(output).contains("arbitrary precision scalar");
50+
}
51+
52+
@Test
53+
public void assertValidRlp() {
54+
txParseSubCommand.dump(
55+
Bytes.fromHexString(
56+
"0x03f9013f010516058261a89403040500000000000000000000000000000000006383000000f8b6f859940000000000000000000000000000000074657374f842a00100000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940000000000000000000000000000000074657374f842a00100000000000000000000000000000000000000000000000000000000000000a002000000000000000000000000000000000000000000000000000000000000000fe1a0010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c44401401a0d98465c5489a09933e6428657f1fc4461d49febd8556c1c7e7053ed0be49cc4fa02c0d67e40aed75f87ea640cc47064d79f4383e24dec283ac6eb81e19da46cc26"));
57+
String output = baos.toString(UTF_8);
58+
assertThat(output).isEqualTo("0x730aa72228b55236de378f5267dfc77723b1380c\n");
59+
}
60+
61+
@Test
62+
public void assertInvalidChainId() {
63+
txParseSubCommand.dump(
64+
Bytes.fromHexString(
65+
"0xf901fc303083303030803030b901ae30303030303030303030433030303030303030303030303030303030303030303030303030303030203030413030303030303030303000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038390030000000002800380000413159000021000000002b0000000000003800000000003800000000000000000000002b633279315a00633200303041374222610063416200325832325a002543323861795930314130383058435931317a633043304239623900310031254363384361000023433158253041380037000027285839005a007937000000623700002761002b5a003937622e000000006300007863410000002a2e320000000000005a0000000000000037242778002039006120412e6362002138300000002a313030303030303030303030373030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030a03030303030303030303030303030303030303030303030303030303030303030a03030303030303030303030303030303030303030303030303030303030303030"));
66+
String output = baos.toString(UTF_8);
67+
assertThat(output).isEqualTo("err: wrong chain id\n");
68+
}
69+
}

0 commit comments

Comments
 (0)