mirror of https://github.com/hyperledger/besu
Add debug_getBadBlocks method (#1378)
Signed-off-by: Karim TAAM <karim.t2am@gmail.com>pull/1385/head
parent
714f5fc56c
commit
be89cd93f7
@ -0,0 +1,58 @@ |
||||
/* |
||||
* 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 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; |
||||
|
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BadBlockResult; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory; |
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; |
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; |
||||
|
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
public class DebugGetBadBlocks implements JsonRpcMethod { |
||||
|
||||
private final BlockchainQueries blockchain; |
||||
private final ProtocolSchedule protocolSchedule; |
||||
private final BlockResultFactory blockResultFactory; |
||||
|
||||
public DebugGetBadBlocks( |
||||
final BlockchainQueries blockchain, |
||||
final ProtocolSchedule protocolSchedule, |
||||
final BlockResultFactory blockResultFactory) { |
||||
this.blockchain = blockchain; |
||||
this.protocolSchedule = protocolSchedule; |
||||
this.blockResultFactory = blockResultFactory; |
||||
} |
||||
|
||||
@Override |
||||
public String getName() { |
||||
return RpcMethod.DEBUG_GET_BAD_BLOCKS.getMethodName(); |
||||
} |
||||
|
||||
@Override |
||||
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { |
||||
final List<BadBlockResult> response = |
||||
protocolSchedule.getByBlockNumber(blockchain.headBlockNumber()).getBadBlocksManager() |
||||
.getBadBlocks().stream() |
||||
.map(block -> BadBlockResult.from(blockResultFactory.transactionComplete(block), block)) |
||||
.collect(Collectors.toList()); |
||||
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), response); |
||||
} |
||||
} |
@ -0,0 +1,45 @@ |
||||
/* |
||||
* 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 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results; |
||||
|
||||
import org.hyperledger.besu.ethereum.core.Block; |
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty; |
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder; |
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; |
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
||||
import org.immutables.value.Value; |
||||
|
||||
@Value.Immutable |
||||
@Value.Style(allParameters = true) |
||||
@JsonSerialize(as = ImmutableBadBlockResult.class) |
||||
@JsonDeserialize(as = ImmutableBadBlockResult.class) |
||||
@JsonPropertyOrder({"block", "hash", "rlp"}) |
||||
public interface BadBlockResult { |
||||
|
||||
@JsonProperty("block") |
||||
BlockResult getBlockResult(); |
||||
|
||||
@JsonProperty("hash") |
||||
String getHash(); |
||||
|
||||
@JsonProperty("rlp") |
||||
String getRlp(); |
||||
|
||||
static BadBlockResult from(final BlockResult blockResult, final Block block) { |
||||
return ImmutableBadBlockResult.of( |
||||
blockResult, block.getHash().toHexString(), block.toRlp().toHexString()); |
||||
} |
||||
} |
@ -0,0 +1,137 @@ |
||||
/* |
||||
* 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 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.assertj.core.api.Assertions.fail; |
||||
import static org.mockito.ArgumentMatchers.anyLong; |
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.when; |
||||
|
||||
import org.hyperledger.besu.crypto.SECP256K1; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BadBlockResult; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResultFactory; |
||||
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; |
||||
import org.hyperledger.besu.ethereum.chain.BadBlockManager; |
||||
import org.hyperledger.besu.ethereum.core.Block; |
||||
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; |
||||
import org.hyperledger.besu.ethereum.core.Transaction; |
||||
import org.hyperledger.besu.ethereum.core.TransactionTestFixture; |
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; |
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
public class DebugGetBadBlockTest { |
||||
|
||||
private final TransactionTestFixture transactionTestFixture = new TransactionTestFixture(); |
||||
|
||||
private final ProtocolSchedule protocolSchedule = mock(ProtocolSchedule.class); |
||||
private final BlockchainQueries blockchainQueries = mock(BlockchainQueries.class); |
||||
private final BlockResultFactory blockResult = new BlockResultFactory(); |
||||
private final BadBlockManager badBlockManager = new BadBlockManager(); |
||||
|
||||
private final DebugGetBadBlocks debugGetBadBlocks = |
||||
new DebugGetBadBlocks(blockchainQueries, protocolSchedule, blockResult); |
||||
|
||||
@Test |
||||
public void nameShouldBeDebugTraceBlock() { |
||||
assertThat(debugGetBadBlocks.getName()).isEqualTo("debug_getBadBlocks"); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnCorrectResponse() { |
||||
|
||||
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.generate(); |
||||
final List<Transaction> transactions = new ArrayList<>(); |
||||
for (int i = 0; i < 3; i++) { |
||||
transactions.add(transactionTestFixture.createTransaction(keyPair)); |
||||
} |
||||
|
||||
final Block parentBlock = |
||||
new BlockDataGenerator() |
||||
.block( |
||||
BlockDataGenerator.BlockOptions.create() |
||||
.setBlockHeaderFunctions(new MainnetBlockHeaderFunctions())); |
||||
final Block badBlockWithTransaction = |
||||
new BlockDataGenerator() |
||||
.block( |
||||
BlockDataGenerator.BlockOptions.create() |
||||
.addTransaction(transactions) |
||||
.setBlockNumber(1) |
||||
.setBlockHeaderFunctions(new MainnetBlockHeaderFunctions()) |
||||
.setParentHash(parentBlock.getHash())); |
||||
final Block badBlockWoTransaction = |
||||
new BlockDataGenerator() |
||||
.block( |
||||
BlockDataGenerator.BlockOptions.create() |
||||
.setBlockNumber(2) |
||||
.hasTransactions(false) |
||||
.setBlockHeaderFunctions(new MainnetBlockHeaderFunctions()) |
||||
.setParentHash(parentBlock.getHash())); |
||||
|
||||
badBlockManager.addBadBlock(badBlockWithTransaction); |
||||
badBlockManager.addBadBlock(badBlockWoTransaction); |
||||
|
||||
final ProtocolSpec protocolSpec = mock(ProtocolSpec.class); |
||||
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(protocolSpec); |
||||
when(protocolSpec.getBadBlocksManager()).thenReturn(badBlockManager); |
||||
|
||||
final JsonRpcRequestContext request = |
||||
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "debug_traceBlock", new Object[] {})); |
||||
|
||||
final JsonRpcSuccessResponse response = |
||||
(JsonRpcSuccessResponse) debugGetBadBlocks.response(request); |
||||
final Collection<BadBlockResult> result = (Collection<BadBlockResult>) response.getResult(); |
||||
assertThat(result).hasSize(2); |
||||
|
||||
for (BadBlockResult badBlockResult : result) { |
||||
if (badBlockResult.getBlockResult().getNumber().equals("0x1")) { |
||||
assertThat(badBlockResult.getBlockResult().getTransactions().size()).isEqualTo(3); |
||||
} else if (badBlockResult.getBlockResult().getNumber().equals("0x2")) { |
||||
assertThat(badBlockResult.getBlockResult().getTransactions()).isEmpty(); |
||||
} else { |
||||
fail("Invalid response"); |
||||
} |
||||
assertThat(badBlockResult.getRlp()).isNotEmpty(); |
||||
assertThat(badBlockResult.getHash()).isNotEmpty(); |
||||
assertThat(badBlockResult.getBlockResult().getNonce()).isNotEmpty(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void shouldReturnCorrectResponseWhenNoInvalidBlockFound() { |
||||
final ProtocolSpec protocolSpec = mock(ProtocolSpec.class); |
||||
when(protocolSchedule.getByBlockNumber(anyLong())).thenReturn(protocolSpec); |
||||
when(protocolSpec.getBadBlocksManager()).thenReturn(badBlockManager); |
||||
|
||||
final JsonRpcRequestContext request = |
||||
new JsonRpcRequestContext(new JsonRpcRequest("2.0", "debug_traceBlock", new Object[] {})); |
||||
|
||||
final JsonRpcSuccessResponse response = |
||||
(JsonRpcSuccessResponse) debugGetBadBlocks.response(request); |
||||
final Collection<BadBlockResult> result = (Collection<BadBlockResult>) response.getResult(); |
||||
assertThat(result).hasSize(0); |
||||
} |
||||
} |
@ -0,0 +1,49 @@ |
||||
/* |
||||
* 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 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum.chain; |
||||
|
||||
import org.hyperledger.besu.ethereum.core.Block; |
||||
import org.hyperledger.besu.ethereum.core.Hash; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
import com.google.common.cache.Cache; |
||||
import com.google.common.cache.CacheBuilder; |
||||
|
||||
public class BadBlockManager { |
||||
|
||||
private final Cache<Hash, Block> badBlocks = |
||||
CacheBuilder.newBuilder().maximumSize(100).concurrencyLevel(1).build(); |
||||
|
||||
/** |
||||
* Add a new invalid block. |
||||
* |
||||
* @param badBlock the invalid block |
||||
*/ |
||||
public void addBadBlock(final Block badBlock) { |
||||
if (badBlock != null) { |
||||
this.badBlocks.put(badBlock.getHash(), badBlock); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Return all invalid blocks |
||||
* |
||||
* @return a collection of invalid blocks |
||||
*/ |
||||
public Collection<Block> getBadBlocks() { |
||||
return badBlocks.asMap().values(); |
||||
} |
||||
} |
@ -0,0 +1,240 @@ |
||||
/* |
||||
* 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 |
||||
*/ |
||||
package org.hyperledger.besu.ethereum; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.ArgumentMatchers.any; |
||||
import static org.mockito.ArgumentMatchers.anyLong; |
||||
import static org.mockito.ArgumentMatchers.eq; |
||||
import static org.mockito.Mockito.mock; |
||||
import static org.mockito.Mockito.when; |
||||
|
||||
import org.hyperledger.besu.ethereum.chain.BadBlockManager; |
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain; |
||||
import org.hyperledger.besu.ethereum.core.Block; |
||||
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; |
||||
import org.hyperledger.besu.ethereum.core.BlockHeader; |
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; |
||||
import org.hyperledger.besu.ethereum.core.Hash; |
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState; |
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt; |
||||
import org.hyperledger.besu.ethereum.mainnet.BlockBodyValidator; |
||||
import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; |
||||
import org.hyperledger.besu.ethereum.mainnet.BlockProcessor; |
||||
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; |
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
|
||||
public class MainnetBlockValidatorTest { |
||||
|
||||
private final BlockHeaderValidator blockHeaderValidator = mock(BlockHeaderValidator.class); |
||||
private final BlockBodyValidator blockBodyValidator = mock(BlockBodyValidator.class); |
||||
private final BlockProcessor blockProcessor = mock(BlockProcessor.class); |
||||
private final ProtocolContext protocolContext = mock(ProtocolContext.class); |
||||
protected final MutableBlockchain blockchain = mock(MutableBlockchain.class); |
||||
protected final WorldStateArchive worldStateArchive = mock(WorldStateArchive.class); |
||||
private final BadBlockManager badBlockManager = new BadBlockManager(); |
||||
|
||||
private MainnetBlockValidator mainnetBlockValidator; |
||||
private Block badBlock; |
||||
|
||||
@Before |
||||
public void setup() { |
||||
when(protocolContext.getBlockchain()).thenReturn(blockchain); |
||||
when(protocolContext.getWorldStateArchive()).thenReturn(worldStateArchive); |
||||
mainnetBlockValidator = |
||||
new MainnetBlockValidator( |
||||
blockHeaderValidator, blockBodyValidator, blockProcessor, badBlockManager); |
||||
badBlock = |
||||
new BlockDataGenerator() |
||||
.block( |
||||
BlockDataGenerator.BlockOptions.create() |
||||
.setBlockNumber(2) |
||||
.hasTransactions(false) |
||||
.setBlockHeaderFunctions(new MainnetBlockHeaderFunctions())); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldDetectAndCacheInvalidBlocksWhenParentBlockNotPresent() { |
||||
when(blockchain.getBlockHeader(anyLong())).thenReturn(Optional.empty()); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(0); |
||||
mainnetBlockValidator.validateAndProcessBlock( |
||||
protocolContext, |
||||
badBlock, |
||||
HeaderValidationMode.DETACHED_ONLY, |
||||
HeaderValidationMode.DETACHED_ONLY); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(1); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldDetectAndCacheInvalidBlocksWhenHeaderInvalid() { |
||||
when(blockchain.getBlockHeader(any(Hash.class))) |
||||
.thenReturn(Optional.of(new BlockHeaderTestFixture().buildHeader())); |
||||
when(blockHeaderValidator.validateHeader( |
||||
any(BlockHeader.class), |
||||
any(BlockHeader.class), |
||||
eq(protocolContext), |
||||
eq(HeaderValidationMode.DETACHED_ONLY))) |
||||
.thenReturn(false); |
||||
|
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(0); |
||||
mainnetBlockValidator.validateAndProcessBlock( |
||||
protocolContext, |
||||
badBlock, |
||||
HeaderValidationMode.DETACHED_ONLY, |
||||
HeaderValidationMode.DETACHED_ONLY); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(1); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldDetectAndCacheInvalidBlocksWhenParentWorldStateNotAvailable() { |
||||
when(blockchain.getBlockHeader(any(Hash.class))) |
||||
.thenReturn(Optional.of(new BlockHeaderTestFixture().buildHeader())); |
||||
when(blockHeaderValidator.validateHeader( |
||||
any(BlockHeader.class), |
||||
any(BlockHeader.class), |
||||
eq(protocolContext), |
||||
eq(HeaderValidationMode.DETACHED_ONLY))) |
||||
.thenReturn(true); |
||||
when(worldStateArchive.getMutable(any(Hash.class))).thenReturn(Optional.empty()); |
||||
|
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(0); |
||||
mainnetBlockValidator.validateAndProcessBlock( |
||||
protocolContext, |
||||
badBlock, |
||||
HeaderValidationMode.DETACHED_ONLY, |
||||
HeaderValidationMode.DETACHED_ONLY); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(1); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldDetectAndCacheInvalidBlocksWhenProcessBlockFailed() { |
||||
when(blockchain.getBlockHeader(any(Hash.class))) |
||||
.thenReturn(Optional.of(new BlockHeaderTestFixture().buildHeader())); |
||||
when(blockHeaderValidator.validateHeader( |
||||
any(BlockHeader.class), |
||||
any(BlockHeader.class), |
||||
eq(protocolContext), |
||||
eq(HeaderValidationMode.DETACHED_ONLY))) |
||||
.thenReturn(true); |
||||
when(worldStateArchive.getMutable(any(Hash.class))) |
||||
.thenReturn(Optional.of(mock(MutableWorldState.class))); |
||||
when(blockProcessor.processBlock(eq(blockchain), any(MutableWorldState.class), eq(badBlock))) |
||||
.thenReturn( |
||||
new BlockProcessor.Result() { |
||||
@SuppressWarnings("unchecked") |
||||
@Override |
||||
public List<TransactionReceipt> getReceipts() { |
||||
return Collections.EMPTY_LIST; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isSuccessful() { |
||||
return false; |
||||
} |
||||
}); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(0); |
||||
mainnetBlockValidator.validateAndProcessBlock( |
||||
protocolContext, |
||||
badBlock, |
||||
HeaderValidationMode.DETACHED_ONLY, |
||||
HeaderValidationMode.DETACHED_ONLY); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(1); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldDetectAndCacheInvalidBlocksWhenBodyInvalid() { |
||||
when(blockchain.getBlockHeader(any(Hash.class))) |
||||
.thenReturn(Optional.of(new BlockHeaderTestFixture().buildHeader())); |
||||
when(blockHeaderValidator.validateHeader( |
||||
any(BlockHeader.class), |
||||
any(BlockHeader.class), |
||||
eq(protocolContext), |
||||
eq(HeaderValidationMode.DETACHED_ONLY))) |
||||
.thenReturn(true); |
||||
when(worldStateArchive.getMutable(any(Hash.class))) |
||||
.thenReturn(Optional.of(mock(MutableWorldState.class))); |
||||
when(blockProcessor.processBlock(eq(blockchain), any(MutableWorldState.class), eq(badBlock))) |
||||
.thenReturn( |
||||
new BlockProcessor.Result() { |
||||
@SuppressWarnings("unchecked") |
||||
@Override |
||||
public List<TransactionReceipt> getReceipts() { |
||||
return Collections.EMPTY_LIST; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isSuccessful() { |
||||
return true; |
||||
} |
||||
}); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(0); |
||||
mainnetBlockValidator.validateAndProcessBlock( |
||||
protocolContext, |
||||
badBlock, |
||||
HeaderValidationMode.DETACHED_ONLY, |
||||
HeaderValidationMode.DETACHED_ONLY); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(1); |
||||
} |
||||
|
||||
@Test |
||||
public void shouldNotCacheWhenValidBlocks() { |
||||
when(blockchain.getBlockHeader(any(Hash.class))) |
||||
.thenReturn(Optional.of(new BlockHeaderTestFixture().buildHeader())); |
||||
when(blockHeaderValidator.validateHeader( |
||||
any(BlockHeader.class), |
||||
any(BlockHeader.class), |
||||
eq(protocolContext), |
||||
eq(HeaderValidationMode.DETACHED_ONLY))) |
||||
.thenReturn(true); |
||||
when(worldStateArchive.getMutable(any(Hash.class))) |
||||
.thenReturn(Optional.of(mock(MutableWorldState.class))); |
||||
when(blockProcessor.processBlock(eq(blockchain), any(MutableWorldState.class), eq(badBlock))) |
||||
.thenReturn( |
||||
new BlockProcessor.Result() { |
||||
@SuppressWarnings("unchecked") |
||||
@Override |
||||
public List<TransactionReceipt> getReceipts() { |
||||
return Collections.EMPTY_LIST; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isSuccessful() { |
||||
return true; |
||||
} |
||||
}); |
||||
when(blockBodyValidator.validateBody( |
||||
eq(protocolContext), |
||||
eq(badBlock), |
||||
any(), |
||||
any(), |
||||
eq(HeaderValidationMode.DETACHED_ONLY))) |
||||
.thenReturn(true); |
||||
assertThat(badBlockManager.getBadBlocks().size()).isEqualTo(0); |
||||
mainnetBlockValidator.validateAndProcessBlock( |
||||
protocolContext, |
||||
badBlock, |
||||
HeaderValidationMode.DETACHED_ONLY, |
||||
HeaderValidationMode.DETACHED_ONLY); |
||||
assertThat(badBlockManager.getBadBlocks()).isEmpty(); |
||||
} |
||||
} |
Loading…
Reference in new issue