mirror of https://github.com/hyperledger/besu
Signed-off-by: Matilda Clerke <matilda.clerke@consensys.net>pull/7638/head
parent
c03bffbc93
commit
b2a45c201e
@ -0,0 +1,89 @@ |
|||||||
|
/* |
||||||
|
* 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 |
||||||
|
*/ |
||||||
|
package org.hyperledger.besu.ethereum.mainnet; |
||||||
|
|
||||||
|
import org.hyperledger.besu.datatypes.Hash; |
||||||
|
import org.hyperledger.besu.ethereum.core.BlockHeader; |
||||||
|
import org.hyperledger.besu.ethereum.core.Request; |
||||||
|
import org.hyperledger.besu.ethereum.core.Transaction; |
||||||
|
import org.hyperledger.besu.ethereum.core.TransactionReceipt; |
||||||
|
import org.hyperledger.besu.ethereum.core.Withdrawal; |
||||||
|
import org.hyperledger.besu.evm.log.LogsBloomFilter; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** A utility class for body validation tasks. Implemented utilising BodyValidation */ |
||||||
|
public class BodyValidator { |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates the transaction root for a list of transactions |
||||||
|
* |
||||||
|
* @param transactions the transactions |
||||||
|
* @return the transaction root |
||||||
|
*/ |
||||||
|
public Hash transactionsRoot(final List<Transaction> transactions) { |
||||||
|
return BodyValidation.transactionsRoot(transactions); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates the withdrawals root for a list of withdrawals |
||||||
|
* |
||||||
|
* @param withdrawals the transactions |
||||||
|
* @return the transaction root |
||||||
|
*/ |
||||||
|
public Hash withdrawalsRoot(final List<Withdrawal> withdrawals) { |
||||||
|
return BodyValidation.withdrawalsRoot(withdrawals); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates the requests root for a list of requests |
||||||
|
* |
||||||
|
* @param requests list of request |
||||||
|
* @return the requests root |
||||||
|
*/ |
||||||
|
public Hash requestsRoot(final List<Request> requests) { |
||||||
|
return BodyValidation.requestsRoot(requests); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates the receipt root for a list of receipts |
||||||
|
* |
||||||
|
* @param receipts the receipts |
||||||
|
* @return the receipt root |
||||||
|
*/ |
||||||
|
public Hash receiptsRoot(final List<TransactionReceipt> receipts) { |
||||||
|
return BodyValidation.receiptsRoot(receipts); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates the ommers hash for a list of ommer block headers |
||||||
|
* |
||||||
|
* @param ommers the ommer block headers |
||||||
|
* @return the ommers hash |
||||||
|
*/ |
||||||
|
public Hash ommersHash(final List<BlockHeader> ommers) { |
||||||
|
return BodyValidation.ommersHash(ommers); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates the logs bloom filter for a list of transaction receipts |
||||||
|
* |
||||||
|
* @param receipts the transaction receipts |
||||||
|
* @return the logs bloom filter |
||||||
|
*/ |
||||||
|
public LogsBloomFilter logsBloom(final List<TransactionReceipt> receipts) { |
||||||
|
return BodyValidation.logsBloom(receipts); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
/* |
||||||
|
* 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 |
||||||
|
*/ |
||||||
|
package org.hyperledger.besu.ethereum.eth.manager.peertask; |
||||||
|
|
||||||
|
import java.lang.reflect.Field; |
||||||
|
|
||||||
|
import org.junit.platform.commons.util.ReflectionUtils; |
||||||
|
|
||||||
|
public class PeerTaskFeatureToggleTestHelper { |
||||||
|
|
||||||
|
public static void setPeerTaskFeatureToggle(final boolean usePeerTaskSystem) |
||||||
|
throws IllegalAccessException { |
||||||
|
Field usePeerTaskSystemField = |
||||||
|
ReflectionUtils.findFields( |
||||||
|
PeerTaskFeatureToggle.class, |
||||||
|
(f) -> f.getName().equals("USE_PEER_TASK_SYSTEM"), |
||||||
|
ReflectionUtils.HierarchyTraversalMode.TOP_DOWN) |
||||||
|
.getFirst(); |
||||||
|
usePeerTaskSystemField.setAccessible(true); |
||||||
|
usePeerTaskSystemField.set(null, usePeerTaskSystem); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,152 @@ |
|||||||
|
/* |
||||||
|
* 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 |
||||||
|
*/ |
||||||
|
package org.hyperledger.besu.ethereum.eth.manager.peertask.task; |
||||||
|
|
||||||
|
import org.hyperledger.besu.datatypes.Hash; |
||||||
|
import org.hyperledger.besu.ethereum.core.BlockHeader; |
||||||
|
import org.hyperledger.besu.ethereum.core.TransactionReceipt; |
||||||
|
import org.hyperledger.besu.ethereum.eth.EthProtocol; |
||||||
|
import org.hyperledger.besu.ethereum.eth.manager.peertask.InvalidPeerTaskResponseException; |
||||||
|
import org.hyperledger.besu.ethereum.eth.messages.EthPV63; |
||||||
|
import org.hyperledger.besu.ethereum.eth.messages.GetReceiptsMessage; |
||||||
|
import org.hyperledger.besu.ethereum.eth.messages.ReceiptsMessage; |
||||||
|
import org.hyperledger.besu.ethereum.mainnet.BodyValidator; |
||||||
|
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.junit.jupiter.api.Assertions; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.mockito.Mockito; |
||||||
|
|
||||||
|
public class GetReceiptsFromPeerTaskTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testGetSubProtocol() { |
||||||
|
GetReceiptsFromPeerTask task = new GetReceiptsFromPeerTask(Collections.emptyList(), null); |
||||||
|
Assertions.assertEquals(EthProtocol.NAME, task.getSubProtocol()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testGetRequiredBlockNumber() { |
||||||
|
GetReceiptsFromPeerTask task = |
||||||
|
new GetReceiptsFromPeerTask( |
||||||
|
List.of(mockBlockHeader(1), mockBlockHeader(2), mockBlockHeader(3)), null); |
||||||
|
Assertions.assertEquals(3, task.getRequiredBlockNumber()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testGetRequestMessage() { |
||||||
|
GetReceiptsFromPeerTask task = |
||||||
|
new GetReceiptsFromPeerTask( |
||||||
|
List.of(mockBlockHeader(1), mockBlockHeader(2), mockBlockHeader(3)), null); |
||||||
|
|
||||||
|
MessageData messageData = task.getRequestMessage(); |
||||||
|
GetReceiptsMessage getReceiptsMessage = GetReceiptsMessage.readFrom(messageData); |
||||||
|
|
||||||
|
Assertions.assertEquals(EthPV63.GET_RECEIPTS, getReceiptsMessage.getCode()); |
||||||
|
Iterable<Hash> hashesInMessage = getReceiptsMessage.hashes(); |
||||||
|
List<Hash> expectedHashes = |
||||||
|
List.of( |
||||||
|
Hash.fromHexString(StringUtils.repeat("00", 31) + "11"), |
||||||
|
Hash.fromHexString(StringUtils.repeat("00", 31) + "21"), |
||||||
|
Hash.fromHexString(StringUtils.repeat("00", 31) + "31")); |
||||||
|
List<Hash> actualHashes = new ArrayList<>(); |
||||||
|
hashesInMessage.forEach(actualHashes::add); |
||||||
|
|
||||||
|
Assertions.assertEquals(3, actualHashes.size()); |
||||||
|
Assertions.assertEquals( |
||||||
|
expectedHashes.stream().sorted().toList(), actualHashes.stream().sorted().toList()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testParseResponseWithNullResponseMessage() { |
||||||
|
GetReceiptsFromPeerTask task = new GetReceiptsFromPeerTask(Collections.emptyList(), null); |
||||||
|
Assertions.assertThrows(InvalidPeerTaskResponseException.class, () -> task.parseResponse(null)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testParseResponseForInvalidResponse() throws InvalidPeerTaskResponseException { |
||||||
|
GetReceiptsFromPeerTask task = |
||||||
|
new GetReceiptsFromPeerTask( |
||||||
|
List.of(mockBlockHeader(1), mockBlockHeader(2), mockBlockHeader(3)), null); |
||||||
|
ReceiptsMessage receiptsMessage = |
||||||
|
ReceiptsMessage.create( |
||||||
|
List.of( |
||||||
|
List.of(new TransactionReceipt(1, 123, Collections.emptyList(), Optional.empty())), |
||||||
|
List.of(new TransactionReceipt(1, 456, Collections.emptyList(), Optional.empty())), |
||||||
|
List.of(new TransactionReceipt(1, 789, Collections.emptyList(), Optional.empty())), |
||||||
|
List.of( |
||||||
|
new TransactionReceipt(1, 101112, Collections.emptyList(), Optional.empty())))); |
||||||
|
|
||||||
|
Assertions.assertThrows( |
||||||
|
InvalidPeerTaskResponseException.class, () -> task.parseResponse(receiptsMessage)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testParseResponse() throws InvalidPeerTaskResponseException { |
||||||
|
BodyValidator bodyValidator = Mockito.mock(BodyValidator.class); |
||||||
|
BlockHeader blockHeader1 = mockBlockHeader(1); |
||||||
|
BlockHeader blockHeader2 = mockBlockHeader(2); |
||||||
|
BlockHeader blockHeader3 = mockBlockHeader(3); |
||||||
|
|
||||||
|
GetReceiptsFromPeerTask task = |
||||||
|
new GetReceiptsFromPeerTask( |
||||||
|
List.of(blockHeader1, blockHeader2, blockHeader3), bodyValidator); |
||||||
|
|
||||||
|
TransactionReceipt receiptForBlock1 = |
||||||
|
new TransactionReceipt(1, 123, Collections.emptyList(), Optional.empty()); |
||||||
|
TransactionReceipt receiptForBlock2 = |
||||||
|
new TransactionReceipt(1, 456, Collections.emptyList(), Optional.empty()); |
||||||
|
TransactionReceipt receiptForBlock3 = |
||||||
|
new TransactionReceipt(1, 789, Collections.emptyList(), Optional.empty()); |
||||||
|
ReceiptsMessage receiptsMessage = |
||||||
|
ReceiptsMessage.create( |
||||||
|
List.of( |
||||||
|
List.of(receiptForBlock1), List.of(receiptForBlock2), List.of(receiptForBlock3))); |
||||||
|
|
||||||
|
Mockito.when(bodyValidator.receiptsRoot(List.of(receiptForBlock1))) |
||||||
|
.thenReturn(Hash.fromHexString(StringUtils.repeat("00", 31) + "12")); |
||||||
|
Mockito.when(bodyValidator.receiptsRoot(List.of(receiptForBlock2))) |
||||||
|
.thenReturn(Hash.fromHexString(StringUtils.repeat("00", 31) + "22")); |
||||||
|
Mockito.when(bodyValidator.receiptsRoot(List.of(receiptForBlock3))) |
||||||
|
.thenReturn(Hash.fromHexString(StringUtils.repeat("00", 31) + "32")); |
||||||
|
|
||||||
|
Map<BlockHeader, List<TransactionReceipt>> resultMap = task.parseResponse(receiptsMessage); |
||||||
|
|
||||||
|
Assertions.assertEquals(3, resultMap.size()); |
||||||
|
Assertions.assertEquals(List.of(receiptForBlock1), resultMap.get(blockHeader1)); |
||||||
|
Assertions.assertEquals(List.of(receiptForBlock2), resultMap.get(blockHeader2)); |
||||||
|
Assertions.assertEquals(List.of(receiptForBlock3), resultMap.get(blockHeader3)); |
||||||
|
} |
||||||
|
|
||||||
|
private BlockHeader mockBlockHeader(final long blockNumber) { |
||||||
|
BlockHeader blockHeader = Mockito.mock(BlockHeader.class); |
||||||
|
Mockito.when(blockHeader.getNumber()).thenReturn(blockNumber); |
||||||
|
// second to last hex digit indicates the blockNumber, last hex digit indicates the usage of the
|
||||||
|
// hash
|
||||||
|
Mockito.when(blockHeader.getHash()) |
||||||
|
.thenReturn(Hash.fromHexString(StringUtils.repeat("00", 31) + blockNumber + "1")); |
||||||
|
Mockito.when(blockHeader.getReceiptsRoot()) |
||||||
|
.thenReturn(Hash.fromHexString(StringUtils.repeat("00", 31) + blockNumber + "2")); |
||||||
|
|
||||||
|
return blockHeader; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue