Browse Source

Hello World gRPC call

checkpoints
Aditya Kulkarni 5 years ago
parent
commit
42444e87ff
  1. 2
      rust-lightclient/.gitignore
  2. 22
      rust-lightclient/Cargo.toml
  3. 12
      rust-lightclient/build.rs
  4. 48
      rust-lightclient/proto/compact_formats.proto
  5. 49
      rust-lightclient/proto/service.proto
  6. 48
      rust-lightclient/src/main.rs

2
rust-lightclient/.gitignore

@ -0,0 +1,2 @@
target/
Cargo.lock

22
rust-lightclient/Cargo.toml

@ -0,0 +1,22 @@
[package]
name = "rust-lightclient"
version = "0.1.0"
edition = "2018"
[dependencies]
tower-grpc = { git = "https://github.com/tower-rs/tower-grpc" }
futures = "0.1"
bytes = "0.4"
env_logger = { version = "0.5", default-features = false }
log = "0.4"
http = "0.1"
prost = "0.5"
tokio = "0.1"
tower-request-modifier = { git = "https://github.com/tower-rs/tower-http" }
tower-hyper = "0.1"
hyper = "0.12"
tower-service = "0.2"
tower-util = "0.1"
[build-dependencies]
tower-grpc-build = { git = "https://github.com/tower-rs/tower-grpc", features = ["tower-hyper"] }

12
rust-lightclient/build.rs

@ -0,0 +1,12 @@
fn main() {
// Build proto files
tower_grpc_build::Config::new()
.enable_server(false)
.enable_client(true)
.build(
&["proto/service.proto", "proto/compact_formats.proto"],
&["proto"],
)
.unwrap_or_else(|e| panic!("protobuf compilation failed: {}", e));
println!("cargo:rerun-if-changed=proto/service.proto");
}

48
rust-lightclient/proto/compact_formats.proto

@ -0,0 +1,48 @@
syntax = "proto3";
package cash.z.wallet.sdk.rpc;
option go_package = "walletrpc";
// Remember that proto3 fields are all optional. A field that is not present will be set to its zero value.
// bytes fields of hashes are in canonical little-endian format.
// CompactBlock is a packaging of ONLY the data from a block that's needed to:
// 1. Detect a payment to your shielded Sapling address
// 2. Detect a spend of your shielded Sapling notes
// 3. Update your witnesses to generate new Sapling spend proofs.
message CompactBlock {
uint32 protoVersion = 1; // the version of this wire format, for storage
uint64 height = 2; // the height of this block
bytes hash = 3;
bytes prevHash = 4;
uint32 time = 5;
bytes header = 6; // (hash, prevHash, and time) OR (full header)
repeated CompactTx vtx = 7; // compact transactions from this block
}
message CompactTx {
// Index and hash will allow the receiver to call out to chain
// explorers or other data structures to retrieve more information
// about this transaction.
uint64 index = 1;
bytes hash = 2;
// The transaction fee: present if server can provide. In the case of a
// stateless server and a transaction with transparent inputs, this will be
// unset because the calculation requires reference to prior transactions.
// in a pure-Sapling context, the fee will be calculable as:
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
uint32 fee = 3;
repeated CompactSpend spends = 4;
repeated CompactOutput outputs = 5;
}
message CompactSpend {
bytes nf = 1;
}
message CompactOutput {
bytes cmu = 1;
bytes epk = 2;
bytes ciphertext = 3;
}

49
rust-lightclient/proto/service.proto

@ -0,0 +1,49 @@
syntax = "proto3";
package cash.z.wallet.sdk.rpc;
option go_package = "walletrpc";
import "compact_formats.proto";
// A BlockID message contains identifiers to select a block: a height or a
// hash. If the hash is present it takes precedence.
message BlockID {
uint64 height = 1;
bytes hash = 2;
}
// BlockRange technically allows ranging from hash to hash etc but this is not
// currently intended for support, though there is no reason you couldn't do
// it. Further permutations are left as an exercise.
message BlockRange {
BlockID start = 1;
BlockID end = 2;
}
// A TxFilter contains the information needed to identify a particular
// transaction: either a block and an index, or a direct transaction hash.
message TxFilter {
BlockID block = 1;
uint64 index = 2;
bytes hash = 3;
}
// RawTransaction contains the complete transaction data.
message RawTransaction {
bytes data = 1;
}
message SendResponse {
int32 errorCode = 1;
string errorMessage = 2;
}
// Empty placeholder. Someday we may want to specify e.g. a particular chain fork.
message ChainSpec {}
service CompactTxStreamer {
rpc GetLatestBlock(ChainSpec) returns (BlockID) {}
rpc GetBlock(BlockID) returns (CompactBlock) {}
rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {}
rpc GetTransaction(TxFilter) returns (RawTransaction) {}
rpc SendTransaction(RawTransaction) returns (SendResponse) {}
}

48
rust-lightclient/src/main.rs

@ -0,0 +1,48 @@
use futures::Future;
use hyper::client::connect::{Destination, HttpConnector};
use tower_grpc::Request;
use tower_hyper::{client, util};
use tower_util::MakeService;
pub mod grpc_client {
include!(concat!(env!("OUT_DIR"), "/cash.z.wallet.sdk.rpc.rs"));
}
pub fn main() {
let uri: http::Uri = format!("http://127.0.0.1:9067").parse().unwrap();
let dst = Destination::try_from_uri(uri.clone()).unwrap();
let connector = util::Connector::new(HttpConnector::new(4));
let settings = client::Builder::new().http2_only(true).clone();
let mut make_client = client::Connect::with_builder(connector, settings);
let say_hello = make_client
.make_service(dst)
.map_err(|e| panic!("connect error: {:?}", e))
.and_then(move |conn| {
use crate::grpc_client::client::CompactTxStreamer;
let conn = tower_request_modifier::Builder::new()
.set_origin(uri)
.build(conn)
.unwrap();
// Wait until the client is ready...
CompactTxStreamer::new(conn).ready()
})
.and_then(|mut client| {
use crate::grpc_client::ChainSpec;
client.get_latest_block(Request::new(ChainSpec {}))
})
.and_then(|response| {
println!("RESPONSE = {:?}", response);
Ok(())
})
.map_err(|e| {
println!("ERR = {:?}", e);
});
tokio::run(say_hello);
}
Loading…
Cancel
Save