Commit 8c28b149 authored by luxq's avatar luxq

fix compile error

parent ac83284e
jar { enabled = false }
dependencies {
implementation project(':infrastructure:async')
implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'org.apache.tuweni:tuweni-bytes'
testImplementation project(':infrastructure:test-support')
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testImplementation 'org.junit.jupiter:junit-jupiter-engine'
}
description = 'Teku Attacker Client'
\ No newline at end of file
package tech.pegasys.teku.attacker;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.HexFormat;
public class Attacker {
private static final AtomicBoolean initOnce = new AtomicBoolean(false);
private static String serviceUrl;
private static AttackClient client;
public static byte[] fromHex(String s) throws IllegalArgumentException {
String hex = s.startsWith("0x") ? s.substring(2) : s;
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException("Invalid hex string");
}
return HexFormat.of().parseHex(hex);
}
private static void initAttacker() {
serviceUrl = System.getenv("ATTACKER_SERVICE_URL");
}
public static AttackClient getAttacker() {
if (initOnce.compareAndSet(false, true)) {
initAttacker();
}
if (client != null) {
return client;
}
if (serviceUrl == null || serviceUrl.isEmpty()) {
return null;
}
try {
client = AttackClient.dial(serviceUrl, 0);
return client;
} catch (Exception e) {
return null;
}
}
}
\ No newline at end of file
package tech.pegasys.teku.attacker.client;
import java.net.URI;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.apache.tuweni.bytes.Bytes;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
/**
* AttackerClient defines typed wrappers for the Attacker RPC API.
*/
public class AttackerClient {
private final RpcConnection rpcConnection;
private final int validatorIndex;
private static final String BLOCK_MODULE = "block";
private static final String ATTEST_MODULE = "attest";
/**
* Dial connects a client to the given URL.
*
* @param rawUrl The URL to connect to
* @param validatorIndex The validator index
* @return A new AttackerClient
* @throws Exception If connection fails
*/
public static AttackerClient dial(String rawUrl, int validatorIndex) throws Exception {
return new AttackerClient(new HttpRpcConnection(URI.create(rawUrl)), validatorIndex);
}
/**
* Creates a client that uses the given RPC connection.
*
* @param rpcConnection The RPC connection
* @param validatorIndex The validator index
*/
public AttackerClient(RpcConnection rpcConnection, int validatorIndex) {
this.rpcConnection = rpcConnection;
this.validatorIndex = validatorIndex;
}
/**
* Close closes the underlying RPC connection.
*/
public void close() {
rpcConnection.close();
}
/**
* Get new parent root for block.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param parentRoot The parent root
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> blockGetNewParentRoot(long slot, String pubkey, String parentRoot) {
return rpcConnection.call(
BLOCK_MODULE + "_getNewParentRoot",
AttackerResponse.class,
slot,
pubkey,
parentRoot);
}
/**
* Delay for receive block.
*
* @param slot The slot number
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> delayForReceiveBlock(long slot) {
return rpcConnection.call(
BLOCK_MODULE + "_delayForReceiveBlock",
AttackerResponse.class,
slot);
}
/**
* Before block broadcast.
*
* @param slot The slot number
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> blockBeforeBroadcast(long slot) {
return rpcConnection.call(
BLOCK_MODULE + "_beforeBroadCast",
AttackerResponse.class,
slot);
}
/**
* After block broadcast.
*
* @param slot The slot number
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> blockAfterBroadcast(long slot) {
return rpcConnection.call(
BLOCK_MODULE + "_afterBroadCast",
AttackerResponse.class,
slot);
}
/**
* Before sign block.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param blockDataBase64 The block data in base64 encoding
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> blockBeforeSign(long slot, String pubkey, String blockDataBase64) {
return rpcConnection.call(
BLOCK_MODULE + "_beforeSign",
AttackerResponse.class,
slot,
pubkey,
blockDataBase64);
}
/**
* After sign block.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param signedBlockDataBase64 The signed block data in base64 encoding
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> blockAfterSign(long slot, String pubkey, String signedBlockDataBase64) {
return rpcConnection.call(
BLOCK_MODULE + "_afterSign",
AttackerResponse.class,
slot,
pubkey,
signedBlockDataBase64);
}
/**
* Before propose block.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param signedBlockDataBase64 The signed block data in base64 encoding
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> blockBeforePropose(long slot, String pubkey, String signedBlockDataBase64) {
return rpcConnection.call(
BLOCK_MODULE + "_beforePropose",
AttackerResponse.class,
slot,
pubkey,
signedBlockDataBase64);
}
/**
* After propose block.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param signedBlockDataBase64 The signed block data in base64 encoding
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> blockAfterPropose(long slot, String pubkey, String signedBlockDataBase64) {
return rpcConnection.call(
BLOCK_MODULE + "_afterPropose",
AttackerResponse.class,
slot,
pubkey,
signedBlockDataBase64);
}
/**
* Before attestation broadcast.
*
* @param slot The slot number
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> attestBeforeBroadcast(long slot) {
return rpcConnection.call(
ATTEST_MODULE + "_beforeBroadCast",
AttackerResponse.class,
slot);
}
/**
* After attestation broadcast.
*
* @param slot The slot number
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> attestAfterBroadcast(long slot) {
return rpcConnection.call(
ATTEST_MODULE + "_afterBroadCast",
AttackerResponse.class,
slot);
}
/**
* Before signing attestation.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param attestDataBase64 The attestation data in base64 encoding
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> attestBeforeSign(
long slot,
String pubkey,
String attestDataBase64) {
return rpcConnection.call(
ATTEST_MODULE + "_beforeSign",
AttackerResponse.class,
slot,
pubkey,
attestDataBase64);
}
/**
* After signing attestation.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param signedAttestDataBase64 The signed attestation data in base64 encoding
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> attestAfterSign(
long slot,
String pubkey,
String signedAttestDataBase64) {
return rpcConnection.call(
ATTEST_MODULE + "_afterSign",
AttackerResponse.class,
slot,
pubkey,
signedAttestDataBase64);
}
/**
* Before proposing attestation.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param signedAttestDataBase64 The signed attestation data in base64 encoding
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> attestBeforePropose(
long slot,
String pubkey,
String signedAttestDataBase64) {
return rpcConnection.call(
ATTEST_MODULE + "_beforePropose",
AttackerResponse.class,
slot,
pubkey,
signedAttestDataBase64);
}
/**
* After proposing attestation.
*
* @param slot The slot number
* @param pubkey The validator public key
* @param signedAttestDataBase64 The signed attestation data in base64 encoding
* @return A future that completes with the response
*/
public SafeFuture<AttackerResponse> attestAfterPropose(
long slot,
String pubkey,
String signedAttestDataBase64) {
return rpcConnection.call(
ATTEST_MODULE + "_afterPropose",
AttackerResponse.class,
slot,
pubkey,
signedAttestDataBase64);
}
}
\ No newline at end of file
package tech.pegasys.teku.attacker.client;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* AttackerCommand defines the command types that can be returned by the attacker client API.
* This matches the Go implementation in tsinghua-cel/attacker-client-go/client/type.go.
*/
public enum AttackerCommand {
CMD_NULL(0),
CMD_CONTINUE(1),
CMD_RETURN(2),
CMD_ABORT(3),
CMD_SKIP(4),
CMD_ROLE_TO_NORMAL(5), // Role changes to normal node
CMD_ROLE_TO_ATTACKER(6), // Role changes to attacker
CMD_EXIT(7),
CMD_UPDATE_STATE(8),
CMP_DELAY_BROAD_CAST(9);
private final int value;
AttackerCommand(int value) {
this.value = value;
}
@JsonValue
public int getValue() {
return value;
}
@JsonCreator
public static AttackerCommand fromValue(int value) {
for (AttackerCommand command : AttackerCommand.values()) {
if (command.value == value) {
return command;
}
}
throw new IllegalArgumentException("Unknown AttackerCommand value: " + value);
}
}
\ No newline at end of file
package tech.pegasys.teku.attacker.client;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* AttackerResponse defines the response from the attacker client API.
* This matches the Go implementation in tsinghua-cel/attacker-client-go/client/type.go.
*/
public class AttackerResponse {
@JsonProperty("cmd")
private AttackerCommand cmd;
@JsonProperty("result")
private String result;
public AttackerResponse() {
// Default constructor for Jackson deserialization
}
public AttackerResponse(AttackerCommand cmd, String result) {
this.cmd = cmd;
this.result = result;
}
public AttackerCommand getCmd() {
return cmd;
}
public String getResult() {
return result;
}
/**
* Convenience method to check if the command is CMD_CONTINUE.
*
* @return true if the command is CMD_CONTINUE, false otherwise
*/
public boolean shouldContinue() {
return cmd == AttackerCommand.CMD_CONTINUE;
}
/**
* Convenience method to check if the command is CMD_ABORT.
*
* @return true if the command is CMD_ABORT, false otherwise
*/
public boolean shouldAbort() {
return cmd == AttackerCommand.CMD_ABORT;
}
@Override
public String toString() {
return "AttackerResponse{" +
"cmd=" + cmd +
", result='" + result + '\'' +
'}';
}
}
\ No newline at end of file
package tech.pegasys.teku.attacker.client;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.atomic.AtomicLong;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
public class HttpRpcConnection implements RpcConnection {
private static final ObjectMapper MAPPER = new ObjectMapper();
private final HttpClient httpClient;
private final URI endpoint;
private final AtomicLong idCounter = new AtomicLong(0);
public HttpRpcConnection(URI endpoint) {
this.endpoint = endpoint;
this.httpClient = HttpClient.newHttpClient();
}
@Override
public <T> SafeFuture<T> call(String method, Class<T> responseType, Object... params) {
SafeFuture<T> future = new SafeFuture<>();
try {
ObjectNode requestNode = MAPPER.createObjectNode();
requestNode.put("jsonrpc", "2.0");
requestNode.put("id", idCounter.incrementAndGet());
requestNode.put("method", method);
ArrayNode paramsNode = MAPPER.createArrayNode();
for (Object param : params) {
paramsNode.addPOJO(param);
}
requestNode.set("params", paramsNode);
String requestBody = MAPPER.writeValueAsString(requestNode);
HttpRequest request = HttpRequest.newBuilder()
.uri(endpoint)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(response -> {
try {
ObjectNode responseNode = (ObjectNode) MAPPER.readTree(response.body());
if (responseNode.has("error")) {
throw new RuntimeException("RPC error: " + responseNode.get("error").toString());
}
return MAPPER.treeToValue(responseNode.get("result"), responseType);
} catch (Exception e) {
throw new RuntimeException("Failed to parse RPC response", e);
}
})
.thenAccept(future::complete)
.exceptionally(e -> {
future.completeExceptionally(e);
return null;
});
} catch (Exception e) {
future.completeExceptionally(e);
}
return future;
}
@Override
public void close() {
// HttpClient doesn't need explicit closing
}
}
\ No newline at end of file
package tech.pegasys.teku.attacker.client;
import java.net.URI;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.apache.tuweni.bytes.Bytes;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
/**
* AttackerClient defines typed wrappers for the Attacker RPC API.
*/
public class AttackerClient {
private final RpcConnection rpcConnection;
private final int validatorIndex;
/**
* Dial connects a client to the given URL.
*
* @param rawUrl The URL to connect to
* @param validatorIndex The validator index
* @return A new AttackerClient
* @throws Exception If connection fails
*/
public static AttackerClient dial(String rawUrl, int validatorIndex) throws Exception {
return new AttackerClient(new HttpRpcConnection(URI.create(rawUrl)), validatorIndex);
}
/**
* Creates a client that uses the given RPC connection.
*
* @param rpcConnection The RPC connection
* @param validatorIndex The validator index
*/
public AttackerClient(RpcConnection rpcConnection, int validatorIndex) {
this.rpcConnection = rpcConnection;
this.validatorIndex = validatorIndex;
}
/**
* Close closes the underlying RPC connection.
*/
public void close() {
rpcConnection.close();
}
}
\ No newline at end of file
......@@ -51,5 +51,5 @@ dependencies {
jmhImplementation testFixtures(project(':ethereum:spec'))
jmhImplementation 'org.mockito:mockito-core'
jmhImplementation testFixtures(project(':eth-benchmark-tests'))
// jmhImplementation testFixtures(project(':eth-benchmark-tests'))
}
......@@ -22,7 +22,6 @@ import static tech.pegasys.teku.infrastructure.json.types.CoreTypes.UINT64_TYPE;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
......@@ -34,18 +33,13 @@ import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import tech.pegasys.teku.benchmarks.gen.KeyFileGenerator;
import tech.pegasys.teku.bls.BLSConstants;
import tech.pegasys.teku.bls.BLSKeyPair;
import tech.pegasys.teku.ethereum.json.types.validator.AttesterDuties;
import tech.pegasys.teku.ethereum.json.types.validator.AttesterDuty;
import tech.pegasys.teku.infrastructure.json.types.SerializableTypeDefinition;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.TestSpecFactory;
import tech.pegasys.teku.spec.datastructures.interop.GenesisStateBuilder;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.bellatrix.BeaconStateBellatrix;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.versions.bellatrix.MutableBeaconStateBellatrix;
@Fork(1)
@State(Scope.Thread)
......@@ -88,32 +82,32 @@ public class AttesterDutiesGeneraterBenchmark {
@Setup(Level.Trial)
public void init() {
BLSConstants.disableBLSVerification();
List<BLSKeyPair> validatorKeys = KeyFileGenerator.readValidatorKeys(validatorsCount);
state =
BeaconStateBellatrix.required(
new GenesisStateBuilder()
.spec(spec)
.signDeposits(true)
.addValidators(validatorKeys)
.build());
final MutableBeaconStateBellatrix mutableState = state.createWritableCopy();
mutableState.setSlot(UInt64.ONE);
state = mutableState.commitChanges();
System.out.println("active validators: " + state.getValidators().size());
for (int i = 0; i < querySize; i++) {
validatorIndices.add(i);
}
attesterDutiesGenerator = new AttesterDutiesGenerator(spec);
epoch = spec.computeEpochAtSlot(state.getSlot()).increment();
int generatedDuties = computeAttesterDuties().getDuties().size();
if (generatedDuties == 0) {
throw new IllegalStateException("No duties generated, check the state");
}
// BLSConstants.disableBLSVerification();
// List<BLSKeyPair> validatorKeys = KeyFileGenerator.readValidatorKeys(validatorsCount);
// state =
// BeaconStateBellatrix.required(
// new GenesisStateBuilder()
// .spec(spec)
// .signDeposits(true)
// .addValidators(validatorKeys)
// .build());
// final MutableBeaconStateBellatrix mutableState = state.createWritableCopy();
// mutableState.setSlot(UInt64.ONE);
// state = mutableState.commitChanges();
//
// System.out.println("active validators: " + state.getValidators().size());
//
// for (int i = 0; i < querySize; i++) {
// validatorIndices.add(i);
// }
//
// attesterDutiesGenerator = new AttesterDutiesGenerator(spec);
// epoch = spec.computeEpochAtSlot(state.getSlot()).increment();
//
// int generatedDuties = computeAttesterDuties().getDuties().size();
// if (generatedDuties == 0) {
// throw new IllegalStateException("No duties generated, check the state");
// }
System.out.println("computed duties: " + computeAttesterDuties().getDuties().size());
System.out.println("Done!");
......
......@@ -94,11 +94,12 @@ public abstract class AbstractBlockPublisher implements BlockPublisher {
// when broadcast validation is disabled, we can publish the block (and blob sidecars)
// immediately and then import
// todo: luxq add bf inject point, for receiveBlock.
// todo: luxq add bf inject point, for receiveBlock.
importBlobSidecars(blobSidecars.get(), blockPublishingPerformance);
SafeFuture<BlockImportAndBroadcastValidationResults> future = importBlock(block, broadcastValidationLevel, blockPublishingPerformance);
SafeFuture<BlockImportAndBroadcastValidationResults> future =
importBlock(block, broadcastValidationLevel, blockPublishingPerformance);
// todo: luxq add bf inject point, for broadcastBlock.
// todo: luxq add bf inject point, for broadcastBlock.
publishBlockAndBlobs(block, blobSidecars, blockPublishingPerformance);
return future;
......
rootProject.name='teku'
include 'acceptance-tests'
include 'attacker'
include 'attacker:client'
include 'beacon:pow'
include 'beacon:sync'
include 'beacon:validator'
......@@ -68,7 +68,7 @@ include 'validator:eventadapter'
include 'validator:remote'
include 'eth-tests'
include 'eth-reference-tests'
include 'eth-benchmark-tests'
//include 'eth-benchmark-tests'
include 'fork-choice-tests'
include 'ethereum:performance-trackers'
......@@ -111,7 +111,7 @@ public class AttestationProductionDuty implements Duty {
.getForkInfo(slot)
.thenCompose(
forkInfo ->
// todo: luxq add bf inject point, before/after attest broadcast.
// todo: luxq add bf inject point, before/after attest broadcast.
sendingStrategy.send(
produceAllAttestations(slot, forkInfo, validatorsByCommitteeIndex)));
}
......@@ -236,7 +236,7 @@ public class AttestationProductionDuty implements Duty {
.signAttestationData(attestationData, forkInfo)
.thenApply(
signature ->
// todo: luxq add bf jnject point, after attest sign.
// todo: luxq add bf jnject point, after attest sign.
signedAttestationProducer.createSignedAttestation(
attestationData, validator, signature))
.thenApply(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment