use of org.hyperledger.besu.evm.account.Account in project besu by hyperledger.
the class FastWorldStateDownloaderTest method resumesFromNonEmptyQueue.
@Test
public void resumesFromNonEmptyQueue() {
// Setup "remote" state
final WorldStateStorage remoteStorage = new WorldStateKeyValueStorage(new InMemoryKeyValueStorage());
final WorldStateArchive remoteWorldStateArchive = new DefaultWorldStateArchive(remoteStorage, createPreimageStorage());
final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable();
// Generate accounts and save corresponding state root
List<Account> accounts = dataGen.createRandomAccounts(remoteWorldState, 10);
final Hash stateRoot = remoteWorldState.rootHash();
// Sanity check
assertThat(stateRoot).isNotEqualTo(EMPTY_TRIE_ROOT);
final BlockHeader header = dataGen.block(BlockOptions.create().setStateRoot(stateRoot).setBlockNumber(10)).getHeader();
// Add some nodes to the taskCollection
final InMemoryTasksPriorityQueues<NodeDataRequest> taskCollection = spy(new InMemoryTasksPriorityQueues<>());
List<Bytes32> queuedHashes = getFirstSetOfChildNodeRequests(remoteStorage, stateRoot);
// Sanity check
assertThat(queuedHashes.size()).isGreaterThan(0);
for (Bytes32 bytes32 : queuedHashes) {
taskCollection.add(new AccountTrieNodeDataRequest(Hash.wrap(bytes32), Optional.empty()));
}
// Sanity check
for (final Bytes32 bytes32 : queuedHashes) {
final Hash hash = Hash.wrap(bytes32);
verify(taskCollection, times(1)).add(argThat((r) -> r.getHash().equals(hash)));
}
final WorldStateStorage localStorage = new WorldStateKeyValueStorage(new InMemoryKeyValueStorage());
final SynchronizerConfiguration syncConfig = SynchronizerConfiguration.builder().worldStateMaxRequestsWithoutProgress(10).build();
final WorldStateDownloader downloader = createDownloader(syncConfig, ethProtocolManager.ethContext(), localStorage, taskCollection);
// Create a peer that can respond
final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, header.getNumber());
// Respond to node data requests
final List<MessageData> sentMessages = new ArrayList<>();
final RespondingEthPeer.Responder blockChainResponder = RespondingEthPeer.blockchainResponder(mock(Blockchain.class), remoteWorldStateArchive);
final RespondingEthPeer.Responder responder = RespondingEthPeer.wrapResponderWithCollector(blockChainResponder, sentMessages);
CompletableFuture<Void> result = downloader.run(null, new FastSyncState(header));
peer.respondWhileOtherThreadsWork(responder, () -> !result.isDone());
assertThat(localStorage.isWorldStateAvailable(stateRoot, header.getHash())).isTrue();
// Check that already enqueued trie nodes were requested
final List<Bytes32> requestedHashes = sentMessages.stream().filter(m -> m.getCode() == EthPV63.GET_NODE_DATA).map(GetNodeDataMessage::readFrom).flatMap(m -> StreamSupport.stream(m.hashes().spliterator(), true)).collect(Collectors.toList());
assertThat(requestedHashes.size()).isGreaterThan(0);
assertThat(requestedHashes).containsAll(queuedHashes);
// Check that already enqueued requests were not enqueued more than once
for (Bytes32 bytes32 : queuedHashes) {
final Hash hash = Hash.wrap(bytes32);
verify(taskCollection, times(1)).add(argThat((r) -> r.getHash().equals(hash)));
}
// Check that all expected account data was downloaded
assertThat(result).isDone();
final WorldStateArchive localWorldStateArchive = new DefaultWorldStateArchive(localStorage, createPreimageStorage());
final WorldState localWorldState = localWorldStateArchive.get(stateRoot, null).get();
assertAccountsMatch(localWorldState, accounts);
}
use of org.hyperledger.besu.evm.account.Account in project besu by hyperledger.
the class FastWorldStateDownloaderTest method doesNotRequestKnownStorageTrieNodesFromNetwork.
@Test
public void doesNotRequestKnownStorageTrieNodesFromNetwork() {
// Setup "remote" state
final WorldStateStorage remoteStorage = new WorldStateKeyValueStorage(new InMemoryKeyValueStorage());
final WorldStateArchive remoteWorldStateArchive = new DefaultWorldStateArchive(remoteStorage, createPreimageStorage());
final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable();
// Generate accounts and save corresponding state root
final List<Account> accounts = dataGen.createRandomContractAccountsWithNonEmptyStorage(remoteWorldState, 20);
final Hash stateRoot = remoteWorldState.rootHash();
final BlockHeader header = dataGen.block(BlockOptions.create().setStateRoot(stateRoot).setBlockNumber(10)).getHeader();
// Create some peers
final List<RespondingEthPeer> peers = Stream.generate(() -> EthProtocolManagerTestUtil.createPeer(ethProtocolManager, header.getNumber())).limit(5).collect(Collectors.toList());
final InMemoryTasksPriorityQueues<NodeDataRequest> taskCollection = new InMemoryTasksPriorityQueues<>();
final WorldStateStorage localStorage = new WorldStateKeyValueStorage(new InMemoryKeyValueStorage());
// Seed local storage with some trie node values
final List<Bytes32> storageRootHashes = new StoredMerklePatriciaTrie<>(remoteStorage::getNodeData, remoteWorldState.rootHash(), Function.identity(), Function.identity()).entriesFrom(Bytes32.ZERO, 5).values().stream().map(RLP::input).map(StateTrieAccountValue::readFrom).map(StateTrieAccountValue::getStorageRoot).collect(Collectors.toList());
final Map<Bytes32, Bytes> allTrieNodes = new HashMap<>();
final Set<Bytes32> knownNodes = new HashSet<>();
final Set<Bytes32> unknownNodes = new HashSet<>();
for (final Bytes32 storageRootHash : storageRootHashes) {
allTrieNodes.putAll(collectTrieNodesToBeRequestedAfterRoot(remoteStorage, storageRootHash, 5));
}
// Sanity check
assertThat(allTrieNodes.size()).isGreaterThan(0);
final Updater localStorageUpdater = localStorage.updater();
boolean storeNode = true;
for (final Map.Entry<Bytes32, Bytes> entry : allTrieNodes.entrySet()) {
final Bytes32 hash = entry.getKey();
final Bytes data = entry.getValue();
if (storeNode) {
localStorageUpdater.putAccountStorageTrieNode(null, null, hash, data);
knownNodes.add(hash);
} else {
unknownNodes.add(hash);
}
storeNode = !storeNode;
}
localStorageUpdater.commit();
final WorldStateDownloader downloader = createDownloader(ethProtocolManager.ethContext(), localStorage, taskCollection);
final FastSyncState fastSyncState = new FastSyncState(header);
final CompletableFuture<Void> result = downloader.run(null, fastSyncState);
// Respond to node data requests
final List<MessageData> sentMessages = new ArrayList<>();
final RespondingEthPeer.Responder blockChainResponder = RespondingEthPeer.blockchainResponder(mock(Blockchain.class), remoteWorldStateArchive, mock(TransactionPool.class));
final RespondingEthPeer.Responder responder = RespondingEthPeer.wrapResponderWithCollector(blockChainResponder, sentMessages);
respondUntilDone(peers, responder, result);
// World state should be available by the time the result is complete
assertThat(localStorage.isWorldStateAvailable(stateRoot, header.getHash())).isTrue();
// Check that unknown trie nodes were requested
final List<Bytes32> requestedHashes = sentMessages.stream().filter(m -> m.getCode() == EthPV63.GET_NODE_DATA).map(GetNodeDataMessage::readFrom).flatMap(m -> StreamSupport.stream(m.hashes().spliterator(), true)).collect(Collectors.toList());
assertThat(requestedHashes.size()).isGreaterThan(0);
assertThat(requestedHashes).containsAll(unknownNodes);
assertThat(requestedHashes).doesNotContainAnyElementsOf(knownNodes);
// Check that all expected account data was downloaded
final WorldStateArchive localWorldStateArchive = new DefaultWorldStateArchive(localStorage, createPreimageStorage());
final WorldState localWorldState = localWorldStateArchive.get(stateRoot, null).get();
assertThat(result).isDone();
assertAccountsMatch(localWorldState, accounts);
}
use of org.hyperledger.besu.evm.account.Account in project besu by hyperledger.
the class StateDiffGenerator method generateStateDiff.
public Stream<Trace> generateStateDiff(final TransactionTrace transactionTrace) {
final List<TraceFrame> traceFrames = transactionTrace.getTraceFrames();
if (traceFrames.size() < 1) {
return Stream.empty();
}
// This corresponds to the world state after the TX executed
// It is two deep because of the way we addressed Spurious Dragon.
final WorldUpdater transactionUpdater = traceFrames.get(0).getWorldUpdater().parentUpdater().get().parentUpdater().get();
// This corresponds to the world state prior to the TX execution,
// Either the initial block state or the state of the prior TX
final WorldUpdater previousUpdater = transactionUpdater.parentUpdater().get();
final StateDiffTrace stateDiffResult = new StateDiffTrace();
for (final Account updatedAccount : transactionUpdater.getTouchedAccounts()) {
final Address accountAddress = updatedAccount.getAddress();
final Account rootAccount = previousUpdater.get(accountAddress);
// calculate storage diff
final Map<String, DiffNode> storageDiff = new TreeMap<>();
for (final Map.Entry<UInt256, UInt256> entry : ((UpdateTrackingAccount<?>) updatedAccount).getUpdatedStorage().entrySet()) {
// FIXME cast
final UInt256 newValue = entry.getValue();
if (rootAccount == null) {
if (!UInt256.ZERO.equals(newValue)) {
storageDiff.put(entry.getKey().toHexString(), new DiffNode(null, newValue.toHexString()));
}
} else {
final UInt256 originalValue = rootAccount.getStorageValue(entry.getKey());
if (!originalValue.equals(newValue)) {
storageDiff.put(entry.getKey().toHexString(), new DiffNode(originalValue.toHexString(), newValue.toHexString()));
}
}
}
// populate the diff object
final AccountDiff accountDiff = new AccountDiff(createDiffNode(rootAccount, updatedAccount, StateDiffGenerator::balanceAsHex), createDiffNode(rootAccount, updatedAccount, StateDiffGenerator::codeAsHex), createDiffNode(rootAccount, updatedAccount, StateDiffGenerator::nonceAsHex), storageDiff);
if (accountDiff.hasDifference()) {
stateDiffResult.put(accountAddress.toHexString(), accountDiff);
}
}
// Add deleted accounts
for (final Address accountAddress : transactionUpdater.getDeletedAccountAddresses()) {
final Account deletedAccount = previousUpdater.get(accountAddress);
if (deletedAccount == null) {
continue;
}
final AccountDiff accountDiff = new AccountDiff(createDiffNode(deletedAccount, null, StateDiffGenerator::balanceAsHex), createDiffNode(deletedAccount, null, StateDiffGenerator::codeAsHex), createDiffNode(deletedAccount, null, StateDiffGenerator::nonceAsHex), Collections.emptyMap());
stateDiffResult.put(accountAddress.toHexString(), accountDiff);
}
return Stream.of(stateDiffResult);
}
use of org.hyperledger.besu.evm.account.Account in project besu by hyperledger.
the class TraceTransactionIntegrationTest method shouldTraceSStoreOperation.
@Test
public void shouldTraceSStoreOperation() {
final KeyPair keyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
final Transaction createTransaction = Transaction.builder().type(TransactionType.FRONTIER).gasLimit(300_000).gasPrice(Wei.ZERO).nonce(0).payload(Bytes.fromHexString(CONTRACT_CREATION_DATA)).value(Wei.ZERO).signAndBuild(keyPair);
final BlockHeader genesisBlockHeader = genesisBlock.getHeader();
final MutableWorldState worldState = worldStateArchive.getMutable(genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash()).get();
final WorldUpdater createTransactionUpdater = worldState.updater();
TransactionProcessingResult result = transactionProcessor.processTransaction(blockchain, createTransactionUpdater, genesisBlockHeader, createTransaction, genesisBlockHeader.getCoinbase(), blockHashLookup, false, TransactionValidationParams.blockReplay());
assertThat(result.isSuccessful()).isTrue();
final Account createdContract = createTransactionUpdater.getTouchedAccounts().stream().filter(account -> !account.getCode().isEmpty()).findAny().get();
createTransactionUpdater.commit();
// Now call the transaction to execute the SSTORE.
final DebugOperationTracer tracer = new DebugOperationTracer(new TraceOptions(true, true, true));
final Transaction executeTransaction = Transaction.builder().type(TransactionType.FRONTIER).gasLimit(300_000).gasPrice(Wei.ZERO).nonce(1).payload(Bytes.fromHexString(CALL_SET_OTHER)).to(createdContract.getAddress()).value(Wei.ZERO).signAndBuild(keyPair);
final WorldUpdater storeUpdater = worldState.updater();
result = transactionProcessor.processTransaction(blockchain, storeUpdater, genesisBlockHeader, executeTransaction, genesisBlockHeader.getCoinbase(), tracer, blockHashLookup, false);
assertThat(result.isSuccessful()).isTrue();
// No storage changes before the SSTORE call.
TraceFrame frame = tracer.getTraceFrames().get(170);
assertThat(frame.getOpcode()).isEqualTo("DUP6");
assertStorageContainsExactly(frame);
// Storage changes show up in the SSTORE frame.
frame = tracer.getTraceFrames().get(171);
assertThat(frame.getOpcode()).isEqualTo("SSTORE");
assertStorageContainsExactly(frame, entry("0x01", "0x6261720000000000000000000000000000000000000000000000000000000006"));
// And storage changes are still present in future frames.
frame = tracer.getTraceFrames().get(172);
assertThat(frame.getOpcode()).isEqualTo("PUSH2");
assertStorageContainsExactly(frame, entry("0x01", "0x6261720000000000000000000000000000000000000000000000000000000006"));
}
use of org.hyperledger.besu.evm.account.Account in project besu by hyperledger.
the class BlockchainQueriesTest method getAccountBalanceAtBlockNumber.
@Test
public void getAccountBalanceAtBlockNumber() {
final List<Address> addresses = Arrays.asList(gen.address(), gen.address(), gen.address());
final int blockCount = 3;
final BlockchainWithData data = setupBlockchain(blockCount, addresses);
final BlockchainQueries queries = data.blockchainQueries;
for (int i = 0; i < blockCount; i++) {
final long curBlockNumber = i;
final BlockHeader header = data.blockData.get(i).block.getHeader();
final Hash stateRoot = header.getStateRoot();
final WorldState worldState = data.worldStateArchive.get(stateRoot, header.getHash()).get();
assertThat(addresses).isNotEmpty();
addresses.forEach(address -> {
final Account actualAccount = worldState.get(address);
final Optional<Wei> result = queries.accountBalance(address, curBlockNumber);
assertThat(result).contains(actualAccount.getBalance());
});
}
}
Aggregations