-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' into #17-sync-substream
- Loading branch information
Showing
11 changed files
with
12,228 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
src/main/java/com/limechain/network/protobuf/LightClientMessage.proto
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
syntax = "proto3"; | ||
|
||
package com.limechain.network.substream.lightclient.pb; | ||
option java_package = "com.limechain.network.substream.lightclient.pb"; | ||
|
||
// Schema definition for light client messages. | ||
// Copied from https://github.com/paritytech/substrate/blob/9b08105b8c7106d723c4f470304ad9e2868569d9/client/network/src/schema/light.v1.proto | ||
|
||
// A pair of arbitrary bytes. | ||
message Pair { | ||
// The first element of the pair. | ||
bytes fst = 1; | ||
// The second element of the pair. | ||
bytes snd = 2; | ||
} | ||
|
||
// Enumerate all possible light client request messages. | ||
message Request { | ||
oneof request { | ||
RemoteCallRequest remote_call_request = 1; | ||
RemoteReadRequest remote_read_request = 2; | ||
RemoteHeaderRequest remote_header_request = 3; | ||
RemoteReadChildRequest remote_read_child_request = 4; | ||
RemoteChangesRequest remote_changes_request = 5; | ||
} | ||
} | ||
|
||
// Enumerate all possible light client response messages. | ||
message Response { | ||
oneof response { | ||
RemoteCallResponse remote_call_response = 1; | ||
RemoteReadResponse remote_read_response = 2; | ||
RemoteHeaderResponse remote_header_response = 3; | ||
RemoteChangesResponse remote_changes_response = 4; | ||
} | ||
} | ||
|
||
// Remote call request. | ||
message RemoteCallRequest { | ||
// Block at which to perform call. | ||
bytes block = 2; | ||
// Method name. | ||
string method = 3; | ||
// Call data. | ||
bytes data = 4; | ||
} | ||
|
||
// Remote call response. | ||
message RemoteCallResponse { | ||
// Execution proof. | ||
bytes proof = 2; | ||
} | ||
|
||
// Remote storage read request. | ||
message RemoteReadRequest { | ||
// Block at which to perform call. | ||
bytes block = 2; | ||
// Storage keys. | ||
repeated bytes keys = 3; | ||
} | ||
|
||
// Remote read response. | ||
message RemoteReadResponse { | ||
// Read proof. | ||
bytes proof = 2; | ||
} | ||
|
||
// Remote storage read child request. | ||
message RemoteReadChildRequest { | ||
// Block at which to perform call. | ||
bytes block = 2; | ||
// Child Storage key, this is relative | ||
// to the child type storage location. | ||
bytes storage_key = 3; | ||
// Storage keys. | ||
repeated bytes keys = 6; | ||
} | ||
|
||
// Remote header request. | ||
message RemoteHeaderRequest { | ||
// Block number to request header for. | ||
bytes block = 2; | ||
} | ||
|
||
// Remote header response. | ||
message RemoteHeaderResponse { | ||
// Header. None if proof generation has failed (e.g. header is unknown). | ||
bytes header = 2; // optional | ||
// Header proof. | ||
bytes proof = 3; | ||
} | ||
|
||
/// Remote changes request. | ||
message RemoteChangesRequest { | ||
// Hash of the first block of the range (including first) where changes are requested. | ||
bytes first = 2; | ||
// Hash of the last block of the range (including last) where changes are requested. | ||
bytes last = 3; | ||
// Hash of the first block for which the requester has the changes trie root. All other | ||
// affected roots must be proved. | ||
bytes min = 4; | ||
// Hash of the last block that we can use when querying changes. | ||
bytes max = 5; | ||
// Storage child node key which changes are requested. | ||
bytes storage_key = 6; // optional | ||
// Storage key which changes are requested. | ||
bytes key = 7; | ||
} | ||
|
||
// Remote changes response. | ||
message RemoteChangesResponse { | ||
// Proof has been generated using block with this number as a max block. Should be | ||
// less than or equal to the RemoteChangesRequest::max block number. | ||
bytes max = 2; | ||
// Changes proof. | ||
repeated bytes proof = 3; | ||
// Changes tries roots missing on the requester' node. | ||
repeated Pair roots = 4; | ||
// Missing changes tries roots proof. | ||
bytes roots_proof = 5; | ||
} |
74 changes: 74 additions & 0 deletions
74
src/main/java/com/limechain/network/substream/lightclient/LightMessages.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package com.limechain.network.substream.lightclient; | ||
|
||
import com.limechain.network.substream.lightclient.pb.LightClientMessage; | ||
import io.libp2p.core.AddressBook; | ||
import io.libp2p.core.Host; | ||
import io.libp2p.core.PeerId; | ||
import io.libp2p.core.multiformats.Multiaddr; | ||
import io.libp2p.core.multistream.StrictProtocolBinding; | ||
import lombok.extern.java.Log; | ||
|
||
import java.util.concurrent.ExecutionException; | ||
import java.util.logging.Level; | ||
|
||
@Log | ||
public class LightMessages extends StrictProtocolBinding<LightMessagesController> { | ||
public LightMessages(LightMessagesProtocol protocol) { | ||
super("/dot/light/2", protocol); | ||
|
||
} | ||
|
||
public LightClientMessage.Response remoteCallRequest(Host us, AddressBook addrs, PeerId peer, | ||
String blockHash, | ||
String method, | ||
String data) { | ||
LightMessagesController controller = dialPeer(us, peer, addrs); | ||
try { | ||
LightClientMessage.Response resp = controller.remoteCallRequest(blockHash, method, data).get(); | ||
log.log(Level.INFO, "Received response: " + resp.toString()); | ||
return resp; | ||
} catch (ExecutionException | InterruptedException e) { | ||
log.log(Level.SEVERE, "Error while sending remote call request: ", e); | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public LightClientMessage.Response remoteReadRequest(Host us, AddressBook addrs, PeerId peer, | ||
String blockHash, | ||
String[] keys) { | ||
LightMessagesController controller = dialPeer(us, peer, addrs); | ||
try { | ||
LightClientMessage.Response resp = controller.remoteReadRequest(blockHash, keys).get(); | ||
log.log(Level.INFO, "Received response: " + resp.toString()); | ||
return resp; | ||
} catch (ExecutionException | InterruptedException e) { | ||
log.log(Level.SEVERE, "Error while sending remote call request: ", e); | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public LightClientMessage.Response remoteReadChildRequest(Host us, AddressBook addrs, PeerId peer, | ||
String blockHash, | ||
String childStorageKey, | ||
String[] keys) { | ||
LightMessagesController controller = dialPeer(us, peer, addrs); | ||
try { | ||
LightClientMessage.Response resp = | ||
controller.remoteReadChildRequest(blockHash, childStorageKey, keys).get(); | ||
log.log(Level.INFO, "Received response: " + resp.toString()); | ||
return resp; | ||
} catch (ExecutionException | InterruptedException e) { | ||
log.log(Level.SEVERE, "Error while sending remote call request: ", e); | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private LightMessagesController dialPeer(Host us, PeerId peer, AddressBook addrs) { | ||
Multiaddr[] addr = addrs.get(peer).join().toArray(new Multiaddr[0]); | ||
if (addr.length == 0) | ||
throw new IllegalStateException("No addresses known for peer " + peer); | ||
|
||
return dial(us, peer, addr).getController().join(); | ||
} | ||
|
||
} |
69 changes: 69 additions & 0 deletions
69
src/main/java/com/limechain/network/substream/lightclient/LightMessagesController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.limechain.network.substream.lightclient; | ||
|
||
import com.google.protobuf.ByteString; | ||
import com.limechain.network.substream.lightclient.pb.LightClientMessage; | ||
|
||
import java.util.Arrays; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.stream.Collectors; | ||
|
||
public interface LightMessagesController { | ||
CompletableFuture<LightClientMessage.Response> send(LightClientMessage.Request msg); | ||
|
||
default CompletableFuture<LightClientMessage.Response> remoteCallRequest(String blockHash, | ||
String methodName, | ||
String callData) { | ||
return send(LightClientMessage.Request | ||
.newBuilder() | ||
.setRemoteCallRequest( | ||
LightClientMessage.RemoteCallRequest | ||
.newBuilder() | ||
.setBlock(ByteString.copyFrom(blockHash.getBytes())) | ||
.setMethod(methodName) | ||
.setData(ByteString.copyFrom(callData.getBytes())) | ||
.build() | ||
) | ||
.build()); | ||
} | ||
|
||
default CompletableFuture<LightClientMessage.Response> remoteReadRequest(String blockHash, | ||
String[] storageKeys) { | ||
|
||
return send(LightClientMessage.Request | ||
.newBuilder() | ||
.setRemoteReadRequest( | ||
LightClientMessage.RemoteReadRequest | ||
.newBuilder() | ||
.setBlock(ByteString.copyFrom(blockHash.getBytes())) | ||
.addAllKeys( | ||
Arrays.stream(storageKeys) | ||
.map(s -> ByteString.copyFrom(s.getBytes())) | ||
.collect(Collectors.toList()) | ||
) | ||
.build() | ||
) | ||
.build()); | ||
|
||
} | ||
|
||
default CompletableFuture<LightClientMessage.Response> remoteReadChildRequest(String blockHash, | ||
String childStorageKey, | ||
String[] keys) { | ||
return send(LightClientMessage.Request | ||
.newBuilder() | ||
.setRemoteReadChildRequest( | ||
LightClientMessage.RemoteReadChildRequest | ||
.newBuilder() | ||
.setBlock(ByteString.copyFrom(blockHash.getBytes())) | ||
.setStorageKey(ByteString.copyFrom(childStorageKey.getBytes())) | ||
.addAllKeys( | ||
Arrays.stream(keys) | ||
.map(s -> ByteString.copyFrom(s.getBytes())) | ||
.collect(Collectors.toList()) | ||
) | ||
.build() | ||
) | ||
.build()); | ||
} | ||
|
||
} |
37 changes: 37 additions & 0 deletions
37
src/main/java/com/limechain/network/substream/lightclient/LightMessagesEngine.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package com.limechain.network.substream.lightclient; | ||
|
||
import com.google.protobuf.ByteString; | ||
import com.limechain.network.substream.lightclient.pb.LightClientMessage; | ||
import io.libp2p.core.Stream; | ||
import lombok.extern.java.Log; | ||
|
||
import java.util.logging.Level; | ||
|
||
@Log | ||
public class LightMessagesEngine { | ||
|
||
// TODO: Add logic for handling incoming each request type | ||
public void receiveRequest(LightClientMessage.Request msg, Stream stream) { | ||
var builder = LightClientMessage.Response.newBuilder(); | ||
if (msg.hasRemoteCallRequest()) { | ||
log.log(Level.INFO, "Received: RemoteCallRequest"); | ||
builder.setRemoteCallResponse( | ||
LightClientMessage.RemoteCallResponse.newBuilder() | ||
.setProof(ByteString.copyFrom("0x0".getBytes())) | ||
.build()); | ||
} else if (msg.hasRemoteReadRequest()) { | ||
log.log(Level.INFO, "Received: RemoteReadRequest"); | ||
builder.setRemoteReadResponse( | ||
LightClientMessage.RemoteReadResponse.newBuilder() | ||
.setProof(ByteString.copyFrom("0x1".getBytes())) | ||
.build()); | ||
} else if (msg.hasRemoteReadChildRequest()) { | ||
log.log(Level.INFO, "Received: RemoteReadChildRequest"); | ||
builder.setRemoteReadResponse( | ||
LightClientMessage.RemoteReadResponse.newBuilder() | ||
.setProof(ByteString.copyFrom("0x2".getBytes())) | ||
.build()); | ||
} | ||
stream.writeAndFlush(builder.build()); | ||
} | ||
} |
Oops, something went wrong.