Skip to content

Commit

Permalink
[WIP] abstractions and API for querying to storages
Browse files Browse the repository at this point in the history
  • Loading branch information
vnabiev committed Apr 6, 2022
1 parent 329a556 commit 67065db
Show file tree
Hide file tree
Showing 49 changed files with 2,681 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
import static com.strategyobject.substrateclient.rpc.codegen.sections.Constants.CLASS_NAME_TEMPLATE;

public class RpcGeneratedSectionFactory {
public <T> T create(@NonNull Class<T> interfaceClass,
private RpcGeneratedSectionFactory() {
}

public static <T> T create(@NonNull Class<T> interfaceClass,
@NonNull ProviderInterface provider) throws RpcInterfaceInitializationException {
if (interfaceClass.getDeclaredAnnotationsByType(RpcInterface.class).length == 0) {
throw new IllegalArgumentException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ void createsRpcSectionAndCallsMethod() throws ExecutionException, InterruptedExc
when(provider.send(anyString(), anyList()))
.thenReturn(sendFuture);

val factory = new RpcGeneratedSectionFactory();
val rpcSection = factory.create(TestSection.class, provider);
val rpcSection = RpcGeneratedSectionFactory.create(TestSection.class, provider);

val actual = rpcSection.doNothing("some").get();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import com.strategyobject.substrateclient.rpc.core.annotations.RpcCall;
import com.strategyobject.substrateclient.rpc.core.annotations.RpcInterface;
import com.strategyobject.substrateclient.rpc.core.annotations.RpcSubscription;
import com.strategyobject.substrateclient.rpc.types.*;
import com.strategyobject.substrateclient.scale.annotations.Scale;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Supplier;

@RpcInterface(section = "state")
public interface State {
Expand All @@ -20,9 +23,56 @@ public interface State {
@RpcCall(method = "getKeys")
CompletableFuture<List<StorageKey>> getKeys(StorageKey key);

@RpcCall(method = "getKeys")
CompletableFuture<List<StorageKey>> getKeys(StorageKey key, @Scale BlockHash at);

@RpcCall(method = "getKeysPaged")
CompletableFuture<List<StorageKey>> getKeysPaged(StorageKey key, int count);

@RpcCall(method = "getKeysPaged")
CompletableFuture<List<StorageKey>> getKeysPaged(StorageKey key, int count, StorageKey startKey);

@RpcCall(method = "getKeysPaged")
CompletableFuture<List<StorageKey>> getKeysPaged(StorageKey key,
int count,
StorageKey startKey,
@Scale BlockHash at);

@RpcCall(method = "getStorage")
CompletableFuture<StorageData> getStorage(StorageKey key);

@RpcCall(method = "getStorage")
CompletableFuture<StorageData> getStorage(StorageKey key, @Scale BlockHash at);

@RpcCall(method = "getStorageHash")
@Scale
CompletableFuture<Hash> getStorageHash(StorageKey key);

@RpcCall(method = "getStorageHash")
@Scale
CompletableFuture<Hash> getStorageHash(StorageKey key, @Scale BlockHash at);

@RpcCall(method = "getStorageSize")
CompletableFuture<Long> getStorageSize(StorageKey key);

@RpcCall(method = "getStorageSize")
CompletableFuture<Long> getStorageSize(StorageKey key, @Scale BlockHash at);

@RpcCall(method = "queryStorage")
CompletableFuture<List<StorageChangeSet>> queryStorage(List<StorageKey> keys, @Scale BlockHash fromBlock);

@RpcCall(method = "queryStorage")
CompletableFuture<List<StorageChangeSet>> queryStorage(List<StorageKey> keys,
@Scale BlockHash fromBlock,
@Scale BlockHash toBlock);

@RpcCall(method = "queryStorageAt")
CompletableFuture<List<StorageChangeSet>> queryStorageAt(List<StorageKey> keys);

@RpcCall(method = "queryStorageAt")
CompletableFuture<List<StorageChangeSet>> queryStorageAt(List<StorageKey> keys, @Scale BlockHash at);

@RpcSubscription(type = "storage", subscribeMethod = "subscribeStorage", unsubscribeMethod = "unsubscribeStorage")
CompletableFuture<Supplier<CompletableFuture<Boolean>>> subscribeStorage(List<StorageKey> keys,
BiConsumer<Exception, StorageChangeSet> callback);
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ void hasKey() throws ExecutionException, InterruptedException, TimeoutException,
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
Author rpcSection = sectionFactory.create(Author.class, wsProvider);
Author rpcSection = RpcGeneratedSectionFactory.create(Author.class, wsProvider);

val publicKey = PublicKey.fromBytes(
HexConverter.toBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"));
Expand All @@ -83,8 +82,7 @@ void insertKey() throws ExecutionException, InterruptedException, TimeoutExcepti
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
Author rpcSection = sectionFactory.create(Author.class, wsProvider);
Author rpcSection = RpcGeneratedSectionFactory.create(Author.class, wsProvider);

assertDoesNotThrow(() -> rpcSection.insertKey("aura",
"alice",
Expand All @@ -102,11 +100,10 @@ void submitExtrinsic() throws ExecutionException, InterruptedException, TimeoutE
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
Chain chainSection = sectionFactory.create(Chain.class, wsProvider);
Chain chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);

val genesis = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS);
Author authorSection = sectionFactory.create(Author.class, wsProvider);
Author authorSection = RpcGeneratedSectionFactory.create(Author.class, wsProvider);

assertDoesNotThrow(() -> authorSection.submitExtrinsic(createBalanceTransferExtrinsic(genesis, NONCE.getAndIncrement()))
.get(WAIT_TIMEOUT, TimeUnit.SECONDS));
Expand All @@ -121,11 +118,10 @@ void submitAndWatchExtrinsic() throws ExecutionException, InterruptedException,
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
Chain chainSection = sectionFactory.create(Chain.class, wsProvider);
Chain chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);

val genesis = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS);
Author authorSection = sectionFactory.create(Author.class, wsProvider);
Author authorSection = RpcGeneratedSectionFactory.create(Author.class, wsProvider);

val updateCount = new AtomicInteger(0);
val status = new AtomicReference<ExtrinsicStatus>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ void getFinalizedHead() throws ExecutionException, InterruptedException, Timeout
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
val rpcSection = sectionFactory.create(Chain.class, wsProvider);
val rpcSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);

val result = rpcSection.getFinalizedHead().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

Expand All @@ -57,8 +56,7 @@ void subscribeNewHeads() throws ExecutionException, InterruptedException, Timeou
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
val rpcSection = sectionFactory.create(Chain.class, wsProvider);
val rpcSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);

val blockCount = new AtomicInteger(0);
val blockHash = new AtomicReference<BlockHash>(null);
Expand Down Expand Up @@ -91,8 +89,7 @@ void getBlockHash() throws ExecutionException, InterruptedException, TimeoutExce
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
val rpcSection = sectionFactory.create(Chain.class, wsProvider);
val rpcSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);

val result = rpcSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS);

Expand All @@ -108,8 +105,7 @@ void getBlock() throws ExecutionException, InterruptedException, TimeoutExceptio
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
Chain rpcSection = sectionFactory.create(Chain.class, wsProvider);
Chain rpcSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);

val height = new AtomicInteger(0);
rpcSection.subscribeNewHeads((e, header) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ void getRuntimeVersion() throws ExecutionException, InterruptedException, Timeou
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
State rpcSection = sectionFactory.create(State.class, wsProvider);
State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

assertDoesNotThrow(() -> {
rpcSection.getRuntimeVersion().get(WAIT_TIMEOUT, TimeUnit.SECONDS);
Expand All @@ -54,8 +53,7 @@ void getMetadata() throws ExecutionException, InterruptedException, TimeoutExcep
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
State rpcSection = sectionFactory.create(State.class, wsProvider);
State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

assertDoesNotThrow(() -> {
rpcSection.getMetadata().get(WAIT_TIMEOUT * 10, TimeUnit.SECONDS);
Expand All @@ -71,8 +69,7 @@ void getKeys() throws ExecutionException, InterruptedException, TimeoutException
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
State rpcSection = sectionFactory.create(State.class, wsProvider);
State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

// xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f
// xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1
Expand All @@ -91,8 +88,7 @@ void getStorage() throws ExecutionException, InterruptedException, TimeoutExcept
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
State rpcSection = sectionFactory.create(State.class, wsProvider);
State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

// xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f
// xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1
Expand All @@ -112,8 +108,7 @@ void getStorageHandlesNullResponse() throws ExecutionException, InterruptedExcep
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
State rpcSection = sectionFactory.create(State.class, wsProvider);
State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

val emptyKey = new byte[32];
val storageData = rpcSection.getStorage(StorageKey.valueOf(emptyKey)).get(WAIT_TIMEOUT, TimeUnit.SECONDS);
Expand All @@ -123,15 +118,124 @@ void getStorageHandlesNullResponse() throws ExecutionException, InterruptedExcep
}

@Test
void getStorageAt() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException {
void getStorageAtBlock() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException {
try (WsProvider wsProvider = WsProvider.builder()
.setEndpoint(substrate.getWsAddress())
.disableAutoConnect()
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
State rpcSection = sectionFactory.create(State.class, wsProvider);
val chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);
val blockHash = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS);
State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

// xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f
// xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1
val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash`
val storageData = rpcSection.getStorage(
StorageKey.valueOf(HexConverter.toBytes(key)),
blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS);

assertNotNull(storageData);
assertTrue(storageData.getData().length > 0);
}
}

@Test
void getStorageHash() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException {
try (WsProvider wsProvider = WsProvider.builder()
.setEndpoint(substrate.getWsAddress())
.disableAutoConnect()
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

// xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f
// xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1
val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash`
val hash = rpcSection.getStorageHash(StorageKey.valueOf(HexConverter.toBytes(key))).get(WAIT_TIMEOUT, TimeUnit.SECONDS);

assertNotNull(hash);
assertTrue(hash.getData().length > 0);
}
}

@Test
void getStorageHashAt() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException {
try (WsProvider wsProvider = WsProvider.builder()
.setEndpoint(substrate.getWsAddress())
.disableAutoConnect()
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);
val blockHash = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS);
State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

// xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f
// xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1
val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash`
val hash = rpcSection.getStorageHash(
StorageKey.valueOf(HexConverter.toBytes(key)),
blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS);

assertNotNull(hash);
assertTrue(hash.getData().length > 0);
}
}

@Test
void getStorageSize() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException {
try (WsProvider wsProvider = WsProvider.builder()
.setEndpoint(substrate.getWsAddress())
.disableAutoConnect()
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

// xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f
// xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1
val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash`
val size = rpcSection.getStorageSize(StorageKey.valueOf(HexConverter.toBytes(key))).get(WAIT_TIMEOUT, TimeUnit.SECONDS);

assertEquals(1, size);
}
}

@Test
void getStorageSizeAt() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException {
try (WsProvider wsProvider = WsProvider.builder()
.setEndpoint(substrate.getWsAddress())
.disableAutoConnect()
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val chainSection = RpcGeneratedSectionFactory.create(Chain.class, wsProvider);
val blockHash = chainSection.getBlockHash(0).get(WAIT_TIMEOUT, TimeUnit.SECONDS);
State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

// xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f
// xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1
val key = "0xc2261276cc9d1f8598ea4b6a74b15c2f308ce9615de0775a82f8a94dc3d285a1"; // TODO implement and use `xxhash`
val size = rpcSection.getStorageSize(
StorageKey.valueOf(HexConverter.toBytes(key)),
blockHash).get(WAIT_TIMEOUT, TimeUnit.SECONDS);

assertEquals(1, size);
}
}

@Test
void queryStorageAt() throws ExecutionException, InterruptedException, TimeoutException, RpcInterfaceInitializationException {
try (WsProvider wsProvider = WsProvider.builder()
.setEndpoint(substrate.getWsAddress())
.disableAutoConnect()
.build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

State rpcSection = RpcGeneratedSectionFactory.create(State.class, wsProvider);

// xxhash128("Balances") = 0xc2261276cc9d1f8598ea4b6a74b15c2f
// xxhash128("StorageVersion") = 0x308ce9615de0775a82f8a94dc3d285a1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ void accountNextIndex() throws ExecutionException, InterruptedException, Timeout
try (WsProvider wsProvider = WsProvider.builder().setEndpoint(substrate.getWsAddress()).disableAutoConnect().build()) {
wsProvider.connect().get(WAIT_TIMEOUT, TimeUnit.SECONDS);

val sectionFactory = new RpcGeneratedSectionFactory();
System rpcSection = sectionFactory.create(System.class, wsProvider);
System rpcSection = RpcGeneratedSectionFactory.create(System.class, wsProvider);

val alicePublicKey = HexConverter.toBytes("0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d");
val result = rpcSection.accountNextIndex(AccountId.fromBytes(alicePublicKey))
Expand Down
Loading

0 comments on commit 67065db

Please sign in to comment.