Skip to content

Commit

Permalink
TrieLogFactory plugin support (hyperledger#5440)
Browse files Browse the repository at this point in the history
* TrieLogs in plugin data
* adds dagger-wired plugincontext and TrieLogService
* add getTrieLogByRange, TrieLogRangeTuple composition
---------

Signed-off-by: garyschulte <garyschulte@gmail.com>
  • Loading branch information
garyschulte authored May 15, 2023
1 parent 3b4f5e1 commit c85841d
Show file tree
Hide file tree
Showing 46 changed files with 1,040 additions and 318 deletions.
10 changes: 5 additions & 5 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -1329,11 +1329,10 @@ static class TxPoolOptionGroup {
private BesuComponent besuComponent;
private final Supplier<ObservableMetricsSystem> metricsSystem =
Suppliers.memoize(
() -> {
return besuComponent == null
? MetricsSystemFactory.create(metricsConfiguration())
: besuComponent.getObservableMetricsSystem();
});
() ->
besuComponent == null || besuComponent.getObservableMetricsSystem() == null
? MetricsSystemFactory.create(metricsConfiguration())
: besuComponent.getObservableMetricsSystem());
private Vertx vertx;
private EnodeDnsConfiguration enodeDnsConfiguration;
private KeyValueStorageProvider keyValueStorageProvider;
Expand Down Expand Up @@ -1412,6 +1411,7 @@ protected BesuCommand(
final PrivacyPluginServiceImpl privacyPluginService,
final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider,
final RpcEndpointServiceImpl rpcEndpointServiceImpl) {
this.besuComponent = besuComponent;
this.logger = besuComponent.getBesuCommandLogger();
this.rlpBlockImporter = rlpBlockImporter;
this.rlpBlockExporterFactory = rlpBlockExporterFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import org.hyperledger.besu.cli.BesuCommand;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.services.BesuPluginContextImpl;

import javax.inject.Named;
import javax.inject.Singleton;
Expand All @@ -50,7 +49,7 @@ BesuCommand provideBesuCommand(final BesuComponent besuComponent) {
RlpBlockExporter::new,
new RunnerBuilder(),
new BesuController.Builder(),
new BesuPluginContextImpl(),
besuComponent.getBesuPluginContext(),
System.getenv());
besuCommand.toCommandLine();
return besuCommand;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoaderModule;
import org.hyperledger.besu.metrics.MetricsSystemModule;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.services.BesuPluginContextImpl;

import javax.inject.Named;
import javax.inject.Singleton;
Expand All @@ -34,7 +35,8 @@
modules = {
BesuCommandModule.class,
MetricsSystemModule.class,
CachedMerkleTrieLoaderModule.class
CachedMerkleTrieLoaderModule.class,
BesuPluginContextModule.class
})
public interface BesuComponent {

Expand Down Expand Up @@ -66,4 +68,12 @@ public interface BesuComponent {
*/
@Named("besuCommandLogger")
Logger getBesuCommandLogger();

/**
* Besu plugin context for doing plugin service discovery.
*
* @return BesuComponent
*/
@Named("besuPluginContext")
BesuPluginContextImpl getBesuPluginContext();
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,29 @@
* SPDX-License-Identifier: Apache-2.0
*
*/
package org.hyperledger.besu.ethereum.bonsai.trielog;
package org.hyperledger.besu.components;

import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.bonsai.worldview.BonsaiWorldStateUpdateAccumulator;
import org.hyperledger.besu.services.BesuPluginContextImpl;

/** Interface for serializing and deserializing {@link TrieLogLayer} objects. */
public interface TrieLogFactory<T extends TrieLogLayer> {
T create(BonsaiWorldStateUpdateAccumulator accumulator, final Hash blockHash);
import javax.inject.Named;
import javax.inject.Singleton;

T deserialize(final byte[] bytes);
import dagger.Module;
import dagger.Provides;

byte[] serialize(final T layer);
/** A dagger module that know how to create the BesuPluginContextImpl singleton. */
@Module
public class BesuPluginContextModule {

/**
* Creates a BesuPluginContextImpl, used for plugin service discovery.
*
* @return the BesuPluginContext
*/
@Provides
@Named("besuPluginContext")
@Singleton
public BesuPluginContextImpl provideBesuPluginContext() {
return new BesuPluginContextImpl();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,8 @@ WorldStateArchive createWorldStateArchive(
blockchain,
Optional.of(dataStorageConfiguration.getBonsaiMaxLayersToLoad()),
cachedMerkleTrieLoader,
metricsSystem);
metricsSystem,
besuComponent.getBesuPluginContext());

case FOREST:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ private enum Lifecycle {
* @param serviceType the service type
* @param service the service
*/
@Override
public <T extends BesuService> void addService(final Class<T> serviceType, final T service) {
checkArgument(serviceType.isInterface(), "Services must be Java interfaces.");
checkArgument(
Expand Down Expand Up @@ -118,7 +119,7 @@ public void registerPlugins(final Path pluginsDir) {
for (final BesuPlugin plugin : serviceLoader) {
try {
plugin.register(this);
LOG.debug("Registered plugin of type {}.", plugin.getClass().getName());
LOG.info("Registered plugin of type {}.", plugin.getClass().getName());
addPluginVersion(plugin);
} catch (final Exception e) {
LOG.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ public void initMocks() throws Exception {
when(mockControllerBuilder.lowerBoundPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxRemotelyInitiatedPeers(anyInt()))
.thenReturn(mockControllerBuilder);
when(mockControllerBuilder.besuComponent(any(BesuComponent.class)))
.thenReturn(mockControllerBuilder);
// doReturn used because of generic BesuController
doReturn(mockController).when(mockControllerBuilder).build();
lenient().when(mockController.getProtocolManager()).thenReturn(mockEthProtocolManager);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.datatypes;

import org.hyperledger.besu.ethereum.rlp.RLPOutput;

/** The values of an account in the world state trie. */
public interface AccountValue {
/**
* The nonce of the account.
*
* @return the nonce of the account.
*/
long getNonce();

/**
* The available balance of that account.
*
* @return the balance, in Wei, of the account.
*/
Wei getBalance();

/**
* The hash of the root of the storage trie associated with this account.
*
* @return the hash of the root node of the storage trie.
*/
Hash getStorageRoot();

/**
* The hash of the EVM bytecode associated with this account.
*
* @return the hash of the account code (which may be {@link Hash#EMPTY}).
*/
Hash getCodeHash();

/**
* Writes the account value to the provided {@link RLPOutput}.
*
* @param out the {@link RLPOutput} to write to.
*/
void writeTo(final RLPOutput out);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* 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.datatypes;

import java.util.Objects;
import java.util.Optional;

import org.apache.tuweni.units.bigints.UInt256;
import org.jetbrains.annotations.NotNull;

/**
* StorageSlotKey represents a key used for storage slots in Ethereum. It contains the hash of the
* slot key and an optional representation of the key itself.
*
* <p>The class provides methods for accessing the hash and key, as well as methods for equality,
* hashcode, and comparison.
*
* <p>StorageSlotKey is used to uniquely identify storage slots within the Ethereum state.
*/
public class StorageSlotKey implements Comparable<StorageSlotKey> {

private final Hash slotHash;
private final Optional<UInt256> slotKey;

/**
* Creates a StorageSlotKey.
*
* @param slotHash Hashed storage slot key.
* @param slotKey Optional UInt256 storage slot key.
*/
public StorageSlotKey(final Hash slotHash, final Optional<UInt256> slotKey) {
this.slotHash = slotHash;
this.slotKey = slotKey;
}

/**
* Creates a StorageSlotKey, hashing the slotKey.
*
* @param slotKey the UInt256 storage slot key.
*/
public StorageSlotKey(final UInt256 slotKey) {
this(Hash.hash(slotKey), Optional.of(slotKey));
}

/**
* Gets the hash representation of the storage slot key.
*
* @return the hash of the storage slot key.
*/
public Hash getSlotHash() {
return slotHash;
}

/**
* Gets the optional UInt256 representation of the storage slot key.
*
* @return an Optional containing the UInt256 storage slot key if present, otherwise an empty
* Optional.
*/
public Optional<UInt256> getSlotKey() {
return slotKey;
}

/**
* Indicates whether some other object is "equal to" this one. Two StorageSlotKey objects are
* considered equal if their slot hash values are equal.
*
* @param o the reference object with which to compare.
* @return true if this object is the same as the obj argument; false otherwise.
*/
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
StorageSlotKey that = (StorageSlotKey) o;
return Objects.equals(slotHash, that.slotHash);
}

@Override
public int hashCode() {
return Objects.hash(slotHash.hashCode());
}

@Override
public String toString() {
return String.format(
"StorageSlotKey{slotHash=%s, slotKey=%s}",
slotHash, slotKey.map(UInt256::toString).orElse("null"));
}

@Override
public int compareTo(@NotNull final StorageSlotKey other) {
return this.slotHash.compareTo(other.slotHash);
}
}
1 change: 1 addition & 0 deletions ethereum/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ dependencies {
annotationProcessor 'com.google.dagger:dagger-compiler'
implementation 'io.opentelemetry:opentelemetry-api'
implementation 'io.vertx:vertx-core'

implementation 'net.java.dev.jna:jna'
implementation 'org.apache.commons:commons-lang3'
implementation 'org.apache.tuweni:tuweni-bytes'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.hyperledger.besu.ethereum.bonsai;

import org.hyperledger.besu.datatypes.AccountValue;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
Expand All @@ -24,7 +25,7 @@
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.hyperledger.besu.evm.ModificationNotAllowedException;
import org.hyperledger.besu.evm.account.AccountStorageEntry;
import org.hyperledger.besu.evm.account.EvmAccount;
Expand All @@ -40,7 +41,7 @@
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;

public class BonsaiAccount implements MutableAccount, EvmAccount {
public class BonsaiAccount implements MutableAccount, EvmAccount, AccountValue {
private final BonsaiWorldView context;
private final boolean mutable;

Expand Down Expand Up @@ -77,7 +78,7 @@ public BonsaiAccount(
public BonsaiAccount(
final BonsaiWorldView context,
final Address address,
final StateTrieAccountValue stateTrieAccount,
final AccountValue stateTrieAccount,
final boolean mutable) {
this(
context,
Expand Down Expand Up @@ -224,6 +225,12 @@ public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(

public Bytes serializeAccount() {
final BytesValueRLPOutput out = new BytesValueRLPOutput();
writeTo(out);
return out.encoded();
}

@Override
public void writeTo(final RLPOutput out) {
out.startList();

out.writeLongScalar(nonce);
Expand All @@ -232,7 +239,6 @@ public Bytes serializeAccount() {
out.writeBytes(codeHash);

out.endList();
return out.encoded();
}

@Override
Expand Down Expand Up @@ -262,6 +268,7 @@ public MutableAccount getMutable() throws ModificationNotAllowedException {
}
}

@Override
public Hash getStorageRoot() {
return storageRoot;
}
Expand Down Expand Up @@ -298,7 +305,7 @@ public String toString() {
* @throws IllegalStateException if the stored values differ
*/
public static void assertCloseEnoughForDiffing(
final BonsaiAccount source, final StateTrieAccountValue account, final String context) {
final BonsaiAccount source, final AccountValue account, final String context) {
if (source == null) {
throw new IllegalStateException(context + ": source is null but target isn't");
} else {
Expand Down
Loading

0 comments on commit c85841d

Please sign in to comment.