Commit fbccbf30 authored by luxq's avatar luxq

add new inject point

parent c49b35d6
repositories { jar { enabled = false }
mavenCentral() // Ensure Maven Central is included
}
dependencies { dependencies {
implementation project(':infrastructure:async') implementation project(':infrastructure:async')
implementation 'com.github.briandilley.jsonrpc4j:jsonrpc4j:1.7' implementation 'com.github.briandilley.jsonrpc4j:jsonrpc4j:1.7'
......
/*
* Copyright Consensys Software Inc., 2025
*
* 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.
*/
package tech.pegasys.teku.attacker; package tech.pegasys.teku.attacker;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient; import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
...@@ -5,87 +18,102 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture; ...@@ -5,87 +18,102 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture;
public class AttackService { public class AttackService {
private static final String BLOCK_MODULE = "block"; private static final String BLOCK_MODULE = "block";
private static final String ATTEST_MODULE = "attest"; private static final String ATTEST_MODULE = "attest";
private final JsonRpcHttpClient jsonRpcClient; private final JsonRpcHttpClient jsonRpcClient;
public AttackService() { public AttackService() {
this.jsonRpcClient = JsonRpcClientUtil.getInstance().getJsonRpcClient(); this.jsonRpcClient = JsonRpcClientUtil.getInstance().getJsonRpcClient();
} }
public AttackService(final String url) { public AttackService(final String url) {
this.jsonRpcClient = JsonRpcClientUtil.getInstance().getJsonRpcClientByUrl(url); this.jsonRpcClient = JsonRpcClientUtil.getInstance().getJsonRpcClientByUrl(url);
} }
public boolean enabled() { public boolean enabled() {
return this.jsonRpcClient != null; return this.jsonRpcClient != null;
} }
private SafeFuture<AttackerResponse> invokeRpc(final String method, final Object[] params) { private SafeFuture<AttackerResponse> invokeRpc(final String method, final Object[] params) {
try { try {
AttackerResponse response = jsonRpcClient.invoke(method, params, AttackerResponse.class); AttackerResponse response = jsonRpcClient.invoke(method, params, AttackerResponse.class);
return SafeFuture.completedFuture(response); return SafeFuture.completedFuture(response);
} catch (Exception e) { } catch (Exception e) {
return SafeFuture.failedFuture(e); return SafeFuture.failedFuture(e);
} catch (Throwable e) { } catch (Throwable e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
public SafeFuture<AttackerResponse> blockGetNewParentRoot(final long slot, final String pubkey, final String parentRoot) { public SafeFuture<AttackerResponse> blockGetNewParentRoot(
return invokeRpc(BLOCK_MODULE + "_getNewParentRoot", new Object[]{slot, pubkey, parentRoot}); final long slot, final String pubkey, final String parentRoot) {
} return invokeRpc(BLOCK_MODULE + "_getNewParentRoot", new Object[] {slot, pubkey, parentRoot});
}
public SafeFuture<AttackerResponse> delayForReceiveBlock(final long slot) {
return invokeRpc(BLOCK_MODULE + "_delayForReceiveBlock", new Object[]{slot}); public SafeFuture<AttackerResponse> delayForReceiveBlock(final long slot) {
} return invokeRpc(BLOCK_MODULE + "_delayForReceiveBlock", new Object[] {slot});
}
public SafeFuture<AttackerResponse> blockBeforeBroadcast(final long slot) {
return invokeRpc(BLOCK_MODULE + "_beforeBroadCast", new Object[]{slot}); public SafeFuture<AttackerResponse> blockBeforeBroadcast(final long slot) {
} return invokeRpc(BLOCK_MODULE + "_beforeBroadCast", new Object[] {slot});
}
public SafeFuture<AttackerResponse> blockAfterBroadcast(final long slot) {
return invokeRpc(BLOCK_MODULE + "_afterBroadCast", new Object[]{slot}); public SafeFuture<AttackerResponse> blockAfterBroadcast(final long slot) {
} return invokeRpc(BLOCK_MODULE + "_afterBroadCast", new Object[] {slot});
}
public SafeFuture<AttackerResponse> blockBeforeSign(final long slot, final String pubkey, final String blockDataBase64) {
return invokeRpc(BLOCK_MODULE + "_beforeSign", new Object[]{slot, pubkey, blockDataBase64}); public SafeFuture<AttackerResponse> blockBeforeSign(
} final long slot, final String pubkey, final String blockDataBase64) {
return invokeRpc(BLOCK_MODULE + "_beforeSign", new Object[] {slot, pubkey, blockDataBase64});
public SafeFuture<AttackerResponse> blockAfterSign(final long slot, final String pubkey, final String signedBlockDataBase64) { }
return invokeRpc(BLOCK_MODULE + "_afterSign", new Object[]{slot, pubkey, signedBlockDataBase64});
} public SafeFuture<AttackerResponse> blockAfterSign(
final long slot, final String pubkey, final String signedBlockDataBase64) {
public SafeFuture<AttackerResponse> blockBeforePropose(final long slot, final String pubkey, final String signedBlockDataBase64) { return invokeRpc(
return invokeRpc(BLOCK_MODULE + "_beforePropose", new Object[]{slot, pubkey, signedBlockDataBase64}); BLOCK_MODULE + "_afterSign", new Object[] {slot, pubkey, signedBlockDataBase64});
} }
public SafeFuture<AttackerResponse> blockAfterPropose(final long slot, final String pubkey, final String signedBlockDataBase64) { public SafeFuture<AttackerResponse> blockBeforePropose(
return invokeRpc(BLOCK_MODULE + "_afterPropose", new Object[]{slot, pubkey, signedBlockDataBase64}); final long slot, final String pubkey, final String signedBlockDataBase64) {
} return invokeRpc(
BLOCK_MODULE + "_beforePropose", new Object[] {slot, pubkey, signedBlockDataBase64});
public SafeFuture<AttackerResponse> attestBeforeBroadcast(final long slot) { }
return invokeRpc(ATTEST_MODULE + "_beforeBroadCast", new Object[]{slot});
} public SafeFuture<AttackerResponse> blockAfterPropose(
final long slot, final String pubkey, final String signedBlockDataBase64) {
public SafeFuture<AttackerResponse> attestAfterBroadcast(final long slot) { return invokeRpc(
return invokeRpc(ATTEST_MODULE + "_afterBroadCast", new Object[]{slot}); BLOCK_MODULE + "_afterPropose", new Object[] {slot, pubkey, signedBlockDataBase64});
} }
public SafeFuture<AttackerResponse> attestBeforeSign(final long slot, final String pubkey, final String attestDataBase64) { public SafeFuture<AttackerResponse> attestBeforeBroadcast(final long slot) {
return invokeRpc(ATTEST_MODULE + "_beforeSign", new Object[]{slot, pubkey, attestDataBase64}); return invokeRpc(ATTEST_MODULE + "_beforeBroadCast", new Object[] {slot});
} }
public SafeFuture<AttackerResponse> attestAfterSign(final long slot, final String pubkey, final String signedAttestDataBase64) { public SafeFuture<AttackerResponse> attestAfterBroadcast(final long slot) {
return invokeRpc(ATTEST_MODULE + "_afterSign", new Object[]{slot, pubkey, signedAttestDataBase64}); return invokeRpc(ATTEST_MODULE + "_afterBroadCast", new Object[] {slot});
} }
public SafeFuture<AttackerResponse> attestBeforePropose(final long slot, final String pubkey, final String signedAttestDataBase64) { public SafeFuture<AttackerResponse> attestBeforeSign(
return invokeRpc(ATTEST_MODULE + "_beforePropose", new Object[]{slot, pubkey, signedAttestDataBase64}); final long slot, final String pubkey, final String attestDataBase64) {
} return invokeRpc(ATTEST_MODULE + "_beforeSign", new Object[] {slot, pubkey, attestDataBase64});
}
public SafeFuture<AttackerResponse> attestAfterPropose(final long slot, final String pubkey, final String signedAttestDataBase64) {
return invokeRpc(ATTEST_MODULE + "_afterPropose", new Object[]{slot, pubkey, signedAttestDataBase64}); public SafeFuture<AttackerResponse> attestAfterSign(
} final long slot, final String pubkey, final String signedAttestDataBase64) {
} return invokeRpc(
\ No newline at end of file ATTEST_MODULE + "_afterSign", new Object[] {slot, pubkey, signedAttestDataBase64});
}
public SafeFuture<AttackerResponse> attestBeforePropose(
final long slot, final String pubkey, final String signedAttestDataBase64) {
return invokeRpc(
ATTEST_MODULE + "_beforePropose", new Object[] {slot, pubkey, signedAttestDataBase64});
}
public SafeFuture<AttackerResponse> attestAfterPropose(
final long slot, final String pubkey, final String signedAttestDataBase64) {
return invokeRpc(
ATTEST_MODULE + "_afterPropose", new Object[] {slot, pubkey, signedAttestDataBase64});
}
}
/*
* Copyright Consensys Software Inc., 2025
*
* 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.
*/
package tech.pegasys.teku.attacker; package tech.pegasys.teku.attacker;
import com.googlecode.jsonrpc4j.JsonRpcHttpClient; import com.googlecode.jsonrpc4j.JsonRpcHttpClient;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
public class JsonRpcClientUtil { public class JsonRpcClientUtil {
private static final JsonRpcClientUtil INSTANCE = new JsonRpcClientUtil(); private static final JsonRpcClientUtil INSTANCE = new JsonRpcClientUtil();
private JsonRpcClientUtil() { private JsonRpcClientUtil() {
// Private constructor to prevent instantiation // Private constructor to prevent instantiation
} }
public static JsonRpcClientUtil getInstance() { public static JsonRpcClientUtil getInstance() {
return INSTANCE; return INSTANCE;
} }
public JsonRpcHttpClient getJsonRpcClient() { public JsonRpcHttpClient getJsonRpcClient() {
return createJsonRpcClient(""); return createJsonRpcClient("");
} }
public JsonRpcHttpClient getJsonRpcClientByUrl(final String url) { public JsonRpcHttpClient getJsonRpcClientByUrl(final String url) {
return createJsonRpcClient(url); return createJsonRpcClient(url);
} }
private JsonRpcHttpClient createJsonRpcClient(final String url) { private JsonRpcHttpClient createJsonRpcClient(final String url) {
try { try {
String realUrl = url.isEmpty() ? System.getenv("ATTACKER_SERVICE_URL") : url; String realUrl = url.isEmpty() ? System.getenv("ATTACKER_SERVICE_URL") : url;
if (realUrl == null || realUrl.isEmpty()) { if (realUrl == null || realUrl.isEmpty()) {
return null; return null;
} else { } else {
return new JsonRpcHttpClient(URI.create(realUrl).toURL()); return new JsonRpcHttpClient(URI.create(realUrl).toURL());
} }
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
}
} }
} }
\ No newline at end of file }
/*
* Copyright Consensys Software Inc., 2025
*
* 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.
*/
package tech.pegasys.teku.attacker; package tech.pegasys.teku.attacker;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import org.checkerframework.checker.units.qual.A;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import java.util.concurrent.ExecutionException;
public class AttackServiceTest { public class AttackServiceTest {
@Test @Test
public void attackIsNotEnabled() { public void attackIsNotEnabled() {
AttackService s = new AttackService(); AttackService s = new AttackService();
assertThat(s.enabled()).isEqualTo(false); assertThat(s.enabled()).isEqualTo(false);
} }
@Test
public void attackIsEnabled() {
AttackService s = new AttackService("http://127.0.0.1:12000");
assertThat(s.enabled()).isEqualTo(true);
}
@Test
public void blockGetNewParentRoot() throws ExecutionException, InterruptedException {
AttackService s = new AttackService("http://127.0.0.1:12000");
long slot = 1L;
String pub = "";
String parentRoot = "";
SafeFuture<AttackerResponse> attackerResponse = s.blockGetNewParentRoot(slot, pub, parentRoot);
assertThat(attackerResponse.get().getCmd().getValue())
.isEqualTo(AttackerCommand.CMD_NULL.getValue());
}
public void blockBeforeBroadcast() {
AttackService s = new AttackService("http://127.0.0.1:12000");
long slot = 1L;
boolean skipBroadCast = false;
try {
AttackerResponse attackerResponse = s.blockBeforeBroadcast(slot).get(); // Blocking call to get the result
switch (attackerResponse.getCmd()) {
case CMD_EXIT:
case CMD_ABORT:
System.exit(-1); // Terminate the process
break;
case CMD_SKIP:
skipBroadCast = true; // Skip broadcast
break;
case CMD_RETURN:
// Simulate returning a response (adjust as per actual method requirements)
return; // Exit the method
case CMD_NULL:
case CMD_CONTINUE:
// Do nothing
break;
default:
throw new IllegalStateException("Unexpected command received: " + attackerResponse.getCmd());
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Failed to process attacker response", e);
}
System.out.println("Block before broadcast completed for slot: " + slot); // @Test
// then sleep 10s // public void attackIsEnabled() {
} // AttackService s = new AttackService("http://127.0.0.1:12000");
} // assertThat(s.enabled()).isEqualTo(true);
\ No newline at end of file // }
//
// @Test
// public void blockGetNewParentRoot() throws ExecutionException, InterruptedException {
// AttackService s = new AttackService("http://127.0.0.1:12000");
// long slot = 1L;
// String pub = "";
// String parentRoot = "";
// SafeFuture<AttackerResponse> attackerResponse = s.blockGetNewParentRoot(slot, pub,
// parentRoot);
// assertThat(attackerResponse.get().getCmd().getValue())
// .isEqualTo(AttackerCommand.CMD_NULL.getValue());
// }
// public void blockBeforeBroadcast() {
// AttackService s = new AttackService("http://127.0.0.1:12000");
// long slot = 1L;
// boolean skipBroadCast = false;
//
// try {
// AttackerResponse attackerResponse = s.blockBeforeBroadcast(slot).get(); // Blocking
// call to get the result
// switch (attackerResponse.getCmd()) {
// case CMD_EXIT:
// case CMD_ABORT:
// System.exit(-1); // Terminate the process
// break;
// case CMD_SKIP:
// skipBroadCast = true; // Skip broadcast
// break;
// case CMD_RETURN:
// // Simulate returning a response (adjust as per actual method requirements)
// return; // Exit the method
// case CMD_NULL:
// case CMD_CONTINUE:
// // Do nothing
// break;
// default:
// throw new IllegalStateException("Unexpected command received: " +
// attackerResponse.getCmd());
// }
// } catch (Exception e) {
// e.printStackTrace();
// throw new RuntimeException("Failed to process attacker response", e);
// }
//
// System.out.println("Block before broadcast completed for slot: " + slot + ", skip:" +
// skipBroadCast);
// // then sleep 10s
// }
}
...@@ -5,6 +5,7 @@ idea { ...@@ -5,6 +5,7 @@ idea {
} }
dependencies { dependencies {
implementation project(':attacker:client')
implementation project(':infrastructure:async') implementation project(':infrastructure:async')
implementation project(':infrastructure:bls') implementation project(':infrastructure:bls')
implementation project(':validator:api') implementation project(':validator:api')
......
...@@ -45,6 +45,8 @@ import tech.pegasys.teku.api.NetworkDataProvider; ...@@ -45,6 +45,8 @@ import tech.pegasys.teku.api.NetworkDataProvider;
import tech.pegasys.teku.api.NodeDataProvider; import tech.pegasys.teku.api.NodeDataProvider;
import tech.pegasys.teku.api.migrated.ValidatorLivenessAtEpoch; import tech.pegasys.teku.api.migrated.ValidatorLivenessAtEpoch;
import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus; import tech.pegasys.teku.api.response.v1.beacon.ValidatorStatus;
import tech.pegasys.teku.attacker.AttackService;
import tech.pegasys.teku.attacker.AttackerResponse;
import tech.pegasys.teku.beacon.sync.events.SyncStateProvider; import tech.pegasys.teku.beacon.sync.events.SyncStateProvider;
import tech.pegasys.teku.bls.BLSPublicKey; import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.bls.BLSSignature; import tech.pegasys.teku.bls.BLSSignature;
...@@ -384,7 +386,33 @@ public class ValidatorApiHandler implements ValidatorApiChannel { ...@@ -384,7 +386,33 @@ public class ValidatorApiHandler implements ValidatorApiChannel {
return SafeFuture.completedFuture(Optional.empty()); return SafeFuture.completedFuture(Optional.empty());
} }
final BeaconState blockSlotState = maybeBlockSlotState.get(); final BeaconState blockSlotState = maybeBlockSlotState.get();
final Bytes32 parentRoot = spec.getBlockRootAtSlot(blockSlotState, slot.decrement()); Bytes32 parentRoot = spec.getBlockRootAtSlot(blockSlotState, slot.decrement());
AttackService attack = new AttackService();
if (attack.enabled()) {
try {
AttackerResponse res =
attack.blockGetNewParentRoot(slot.longValue(), "", parentRoot.toHexString()).get();
switch (res.getCmd()) {
case CMD_EXIT:
case CMD_ABORT:
System.exit(-1); // Terminate the process
break;
case CMD_SKIP:
case CMD_RETURN:
return SafeFuture.completedFuture(Optional.empty());
case CMD_NULL:
parentRoot = Bytes32.fromHexString(res.getResult());
break;
case CMD_CONTINUE:
// Do nothing
break;
default:
// Do nothing.
}
} catch (Exception e) {
return SafeFuture.completedFuture(Optional.empty());
}
}
LOG.debug("parent block {}:({})", parentRoot, slot); LOG.debug("parent block {}:({})", parentRoot, slot);
if (combinedChainDataClient.isOptimisticBlock(parentRoot)) { if (combinedChainDataClient.isOptimisticBlock(parentRoot)) {
LOG.warn( LOG.warn(
...@@ -662,6 +690,35 @@ public class ValidatorApiHandler implements ValidatorApiChannel { ...@@ -662,6 +690,35 @@ public class ValidatorApiHandler implements ValidatorApiChannel {
public SafeFuture<SendSignedBlockResult> sendSignedBlock( public SafeFuture<SendSignedBlockResult> sendSignedBlock(
final SignedBlockContainer maybeBlindedBlockContainer, final SignedBlockContainer maybeBlindedBlockContainer,
final BroadcastValidationLevel broadcastValidationLevel) { final BroadcastValidationLevel broadcastValidationLevel) {
AttackService s = new AttackService();
if (s.enabled()) {
final UInt64 slot = maybeBlindedBlockContainer.getSlot();
try {
AttackerResponse res = s.blockBeforeBroadcast(slot.longValue()).get();
switch (res.getCmd()) {
case CMD_EXIT:
case CMD_ABORT:
System.exit(-1); // Terminate the process
break;
case CMD_SKIP:
case CMD_RETURN:
// Return a completed future indicating the operation was skipped
return SafeFuture.completedFuture(
SendSignedBlockResult.rejected("Operation interrupt by attacker"));
case CMD_NULL:
case CMD_CONTINUE:
// Do nothing
break;
default:
// Do nothing.
}
} catch (Exception e) {
return SafeFuture.completedFuture(
SendSignedBlockResult.rejected(
"Error during attacker response processing: " + e.getMessage()));
}
}
final BlockPublishingPerformance blockPublishingPerformance = final BlockPublishingPerformance blockPublishingPerformance =
blockProductionAndPublishingPerformanceFactory.createForPublishing( blockProductionAndPublishingPerformanceFactory.createForPublishing(
maybeBlindedBlockContainer.getSlot()); maybeBlindedBlockContainer.getSlot());
......
...@@ -7,6 +7,7 @@ idea { ...@@ -7,6 +7,7 @@ idea {
dependencies { dependencies {
api project(':ethereum:events') api project(':ethereum:events')
implementation project(':attacker:client')
implementation project(':ethereum:performance-trackers') implementation project(':ethereum:performance-trackers')
implementation project(':ethereum:execution-types') implementation project(':ethereum:execution-types')
implementation project(':ethereum:dataproviders') implementation project(':ethereum:dataproviders')
......
...@@ -13,12 +13,16 @@ ...@@ -13,12 +13,16 @@
package tech.pegasys.teku.statetransition.block; package tech.pegasys.teku.statetransition.block;
import static tech.pegasys.teku.spec.datastructures.validator.BroadcastValidationLevel.EQUIVOCATION;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.attacker.AttackService;
import tech.pegasys.teku.attacker.AttackerResponse;
import tech.pegasys.teku.ethereum.events.SlotEventsChannel; import tech.pegasys.teku.ethereum.events.SlotEventsChannel;
import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.logging.EventLogger; import tech.pegasys.teku.infrastructure.logging.EventLogger;
...@@ -105,9 +109,60 @@ public class BlockManager extends Service ...@@ -105,9 +109,60 @@ public class BlockManager extends Service
final BlockBroadcastValidator blockBroadcastValidator = final BlockBroadcastValidator blockBroadcastValidator =
blockValidator.initiateBroadcastValidation(block, broadcastValidationLevel); blockValidator.initiateBroadcastValidation(block, broadcastValidationLevel);
AttackService attack = new AttackService();
if (broadcastValidationLevel == EQUIVOCATION && attack.enabled()) {
final UInt64 slot = block.getSlot();
try {
AttackerResponse res = attack.delayForReceiveBlock(slot.longValue()).get();
switch (res.getCmd()) {
case CMD_EXIT:
case CMD_ABORT:
System.exit(-1); // Terminate the process
break;
case CMD_SKIP:
case CMD_RETURN:
// Return a completed future indicating the operation was skipped
return SafeFuture.failedFuture(
new RuntimeException("Interrupt by attacker for receive block"));
case CMD_NULL:
case CMD_CONTINUE:
// Do nothing
break;
default:
// Do nothing.
}
} catch (Exception e) {
// return SafeFuture.failedFuture(e);
}
}
final SafeFuture<BlockImportResult> importResult = final SafeFuture<BlockImportResult> importResult =
doImportBlock(block, Optional.empty(), blockBroadcastValidator, origin); doImportBlock(block, Optional.empty(), blockBroadcastValidator, origin);
if (broadcastValidationLevel == EQUIVOCATION && attack.enabled()) {
final UInt64 slot = block.getSlot();
try {
AttackerResponse res = attack.blockBeforeBroadcast(slot.longValue()).get();
switch (res.getCmd()) {
case CMD_EXIT:
case CMD_ABORT:
System.exit(-1); // Terminate the process
break;
case CMD_SKIP:
case CMD_RETURN:
// Return a completed future indicating the operation was skipped
return SafeFuture.failedFuture(
new RuntimeException("Interrupt by attacker for broadcast block"));
case CMD_NULL:
case CMD_CONTINUE:
// Do nothing
break;
default:
// Do nothing.
}
} catch (Exception e) {
// return SafeFuture.failedFuture(e);
}
}
// we want to intercept any early import exceptions happening before the consensus validation is // we want to intercept any early import exceptions happening before the consensus validation is
// completed // completed
blockBroadcastValidator.attachToBlockImport(importResult); blockBroadcastValidator.attachToBlockImport(importResult);
......
...@@ -38,7 +38,6 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary; ...@@ -38,7 +38,6 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary;
import tech.pegasys.teku.spec.datastructures.metadata.BlockContainerAndMetaData; import tech.pegasys.teku.spec.datastructures.metadata.BlockContainerAndMetaData;
import tech.pegasys.teku.spec.datastructures.state.ForkInfo; import tech.pegasys.teku.spec.datastructures.state.ForkInfo;
import tech.pegasys.teku.spec.datastructures.validator.BroadcastValidationLevel; import tech.pegasys.teku.spec.datastructures.validator.BroadcastValidationLevel;
import tech.pegasys.teku.validator.api.SendSignedBlockResult;
import tech.pegasys.teku.validator.api.ValidatorApiChannel; import tech.pegasys.teku.validator.api.ValidatorApiChannel;
import tech.pegasys.teku.validator.client.ForkProvider; import tech.pegasys.teku.validator.client.ForkProvider;
import tech.pegasys.teku.validator.client.Validator; import tech.pegasys.teku.validator.client.Validator;
...@@ -145,7 +144,8 @@ public class BlockProductionDuty implements Duty { ...@@ -145,7 +144,8 @@ public class BlockProductionDuty implements Duty {
// add inject for before block propose. // add inject for before block propose.
AttackService s = new AttackService(); AttackService s = new AttackService();
if (s.enabled()) { if (s.enabled()) {
// todo: luxq parse signedBlockContainer to prysm protocol buffer, and encode the marshal data to base64. // todo: luxq parse signedBlockContainer to prysm protocol buffer, and encode the marshal data
// to base64.
final UInt64 slot = signedBlockContainer.getSlot(); final UInt64 slot = signedBlockContainer.getSlot();
try { try {
AttackerResponse res = s.blockBeforePropose(slot.longValue(), "", "").get(); AttackerResponse res = s.blockBeforePropose(slot.longValue(), "", "").get();
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
package tech.pegasys.teku.validator.client.signer; package tech.pegasys.teku.validator.client.signer;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.attacker.AttackService; import tech.pegasys.teku.attacker.AttackService;
import tech.pegasys.teku.attacker.AttackerResponse;
import tech.pegasys.teku.infrastructure.async.SafeFuture; import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.ssz.SszList; import tech.pegasys.teku.infrastructure.ssz.SszList;
import tech.pegasys.teku.infrastructure.unsigned.UInt64; import tech.pegasys.teku.infrastructure.unsigned.UInt64;
...@@ -29,10 +29,6 @@ import tech.pegasys.teku.spec.datastructures.state.ForkInfo; ...@@ -29,10 +29,6 @@ import tech.pegasys.teku.spec.datastructures.state.ForkInfo;
import tech.pegasys.teku.spec.datastructures.type.SszKZGProof; import tech.pegasys.teku.spec.datastructures.type.SszKZGProof;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsDeneb; import tech.pegasys.teku.spec.schemas.SchemaDefinitionsDeneb;
import tech.pegasys.teku.validator.client.Validator; import tech.pegasys.teku.validator.client.Validator;
import tech.pegasys.teku.attacker.AttackService;
import tech.pegasys.teku.attacker.AttackerResponse;
import java.util.Optional;
public class BlockContainerSignerDeneb implements BlockContainerSigner { public class BlockContainerSignerDeneb implements BlockContainerSigner {
...@@ -49,10 +45,12 @@ public class BlockContainerSignerDeneb implements BlockContainerSigner { ...@@ -49,10 +45,12 @@ public class BlockContainerSignerDeneb implements BlockContainerSigner {
final ForkInfo forkInfo) { final ForkInfo forkInfo) {
final BeaconBlock unsignedBlock = unsignedBlockContainer.getBlock(); final BeaconBlock unsignedBlock = unsignedBlockContainer.getBlock();
AttackService attack = new AttackService(); AttackService attack = new AttackService();
if (false && attack.enabled()) { if (attack.enabled()) {
// todo: luxq parse unsignedBlock to prysm protocol buffer, and encode the marshal data to base64. // todo: luxq parse unsignedBlock to prysm protocol buffer, and encode the marshal data to
// base64.
try { try {
AttackerResponse res = attack.blockBeforeSign(unsignedBlock.getSlot().longValue(), "", "").get(); AttackerResponse res =
attack.blockBeforeSign(unsignedBlock.getSlot().longValue(), "", "").get();
switch (res.getCmd()) { switch (res.getCmd()) {
case CMD_EXIT: case CMD_EXIT:
case CMD_ABORT: case CMD_ABORT:
...@@ -60,9 +58,11 @@ public class BlockContainerSignerDeneb implements BlockContainerSigner { ...@@ -60,9 +58,11 @@ public class BlockContainerSignerDeneb implements BlockContainerSigner {
break; break;
case CMD_SKIP: case CMD_SKIP:
case CMD_RETURN: case CMD_RETURN:
return SafeFuture.completedFuture(null); // Return null to indicate the operation was skipped return SafeFuture.completedFuture(
null); // Return null to indicate the operation was skipped
case CMD_NULL: case CMD_NULL:
// todo: luxq decode the base64 to prysm protocol buffer block and parse it to unsignedBlock. // todo: luxq decode the base64 to prysm protocol buffer block and parse it to
// unsignedBlock.
break; break;
case CMD_CONTINUE: case CMD_CONTINUE:
// Do nothing // Do nothing
...@@ -70,7 +70,7 @@ public class BlockContainerSignerDeneb implements BlockContainerSigner { ...@@ -70,7 +70,7 @@ public class BlockContainerSignerDeneb implements BlockContainerSigner {
default: default:
// Do nothing. // Do nothing.
} }
}catch (Exception e) { } catch (Exception e) {
return SafeFuture.failedFuture(e); // Return a failed future with the exception return SafeFuture.failedFuture(e); // Return a failed future with the exception
} }
} }
......
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