Compiling with tonic.
This commit is contained in:
parent
3dac89ef26
commit
1b45874191
|
@ -8,11 +8,17 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
failure = "0.1"
|
||||
|
||||
tonic = { version = "0.4.2", features = ["tls", "tls-roots"] }
|
||||
prost = "0.7"
|
||||
|
||||
tiny-bip39 = "0.8.0"
|
||||
zcash_primitives = "0.5"
|
||||
zcash_client_sqlite = "0.3"
|
||||
zcash_client_backend = "0.5"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.4"
|
||||
|
||||
[patch.crates-io]
|
||||
zcash_primitives = { path = '../../clones/librustzcash/zcash_primitives' }
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
tonic_build::configure()
|
||||
.build_server(false)
|
||||
.compile(&["proto/compact_formats.proto", "proto/service.proto"], &["proto"])?;
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = "walletrpc";
|
||||
option swift_prefix = "";
|
||||
// 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;
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
// Copyright (c) 2019-2020 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
syntax = "proto3";
|
||||
package cash.z.wallet.sdk.rpc;
|
||||
option go_package = ".;walletrpc";
|
||||
option swift_prefix = "";
|
||||
import "compact_formats.proto";
|
||||
|
||||
// A BlockID message contains identifiers to select a block: a height or a
|
||||
// hash. Specification by hash is not implemented, but may be in the future.
|
||||
message BlockID {
|
||||
uint64 height = 1;
|
||||
bytes hash = 2;
|
||||
}
|
||||
|
||||
// BlockRange specifies a series of blocks from start to end inclusive.
|
||||
// Both BlockIDs must be heights; specification by hash is not yet supported.
|
||||
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.
|
||||
// Currently, only specification by hash is supported.
|
||||
message TxFilter {
|
||||
BlockID block = 1; // block identifier, height or hash
|
||||
uint64 index = 2; // index within the block
|
||||
bytes hash = 3; // transaction ID (hash, txid)
|
||||
}
|
||||
|
||||
// RawTransaction contains the complete transaction data. It also optionally includes
|
||||
// the block height in which the transaction was included.
|
||||
message RawTransaction {
|
||||
bytes data = 1; // exact data returned by Zcash 'getrawtransaction'
|
||||
uint64 height = 2; // height that the transaction was mined (or -1)
|
||||
}
|
||||
|
||||
// A SendResponse encodes an error code and a string. It is currently used
|
||||
// only by SendTransaction(). If error code is zero, the operation was
|
||||
// successful; if non-zero, it and the message specify the failure.
|
||||
message SendResponse {
|
||||
int32 errorCode = 1;
|
||||
string errorMessage = 2;
|
||||
}
|
||||
|
||||
// Chainspec is a placeholder to allow specification of a particular chain fork.
|
||||
message ChainSpec {}
|
||||
|
||||
// Empty is for gRPCs that take no arguments, currently only GetLightdInfo.
|
||||
message Empty {}
|
||||
|
||||
// LightdInfo returns various information about this lightwalletd instance
|
||||
// and the state of the blockchain.
|
||||
message LightdInfo {
|
||||
string version = 1;
|
||||
string vendor = 2;
|
||||
bool taddrSupport = 3; // true
|
||||
string chainName = 4; // either "main" or "test"
|
||||
uint64 saplingActivationHeight = 5; // depends on mainnet or testnet
|
||||
string consensusBranchId = 6; // protocol identifier, see consensus/upgrades.cpp
|
||||
uint64 blockHeight = 7; // latest block on the best chain
|
||||
string gitCommit = 8;
|
||||
string branch = 9;
|
||||
string buildDate = 10;
|
||||
string buildUser = 11;
|
||||
uint64 estimatedHeight = 12; // less than tip height if zcashd is syncing
|
||||
string zcashdBuild = 13; // example: "v4.1.1-877212414"
|
||||
string zcashdSubversion = 14; // example: "/MagicBean:4.1.1/"
|
||||
}
|
||||
|
||||
// TransparentAddressBlockFilter restricts the results to the given address
|
||||
// or block range.
|
||||
message TransparentAddressBlockFilter {
|
||||
string address = 1; // t-address
|
||||
BlockRange range = 2; // start, end heights
|
||||
}
|
||||
|
||||
// Duration is currently used only for testing, so that the Ping rpc
|
||||
// can simulate a delay, to create many simultaneous connections. Units
|
||||
// are microseconds.
|
||||
message Duration {
|
||||
int64 intervalUs = 1;
|
||||
}
|
||||
|
||||
// PingResponse is used to indicate concurrency, how many Ping rpcs
|
||||
// are executing upon entry and upon exit (after the delay).
|
||||
// This rpc is used for testing only.
|
||||
message PingResponse {
|
||||
int64 entry = 1;
|
||||
int64 exit = 2;
|
||||
}
|
||||
|
||||
message Address {
|
||||
string address = 1;
|
||||
}
|
||||
message AddressList {
|
||||
repeated string addresses = 1;
|
||||
}
|
||||
message Balance {
|
||||
int64 valueZat = 1;
|
||||
}
|
||||
|
||||
message Exclude {
|
||||
repeated bytes txid = 1;
|
||||
}
|
||||
|
||||
// The TreeState is derived from the Zcash z_gettreestate rpc.
|
||||
message TreeState {
|
||||
string network = 1; // "main" or "test"
|
||||
uint64 height = 2;
|
||||
string hash = 3; // block id
|
||||
uint32 time = 4; // Unix epoch time when the block was mined
|
||||
string tree = 5; // sapling commitment tree state
|
||||
}
|
||||
|
||||
message GetAddressUtxosArg {
|
||||
string address = 1;
|
||||
uint64 startHeight = 2;
|
||||
uint32 maxEntries = 3; // zero means unlimited
|
||||
}
|
||||
message GetAddressUtxosReply {
|
||||
bytes txid = 1;
|
||||
int32 index = 2;
|
||||
bytes script = 3;
|
||||
int64 valueZat = 4;
|
||||
uint64 height = 5;
|
||||
}
|
||||
message GetAddressUtxosReplyList {
|
||||
repeated GetAddressUtxosReply addressUtxos = 1;
|
||||
}
|
||||
|
||||
service CompactTxStreamer {
|
||||
// Return the height of the tip of the best chain
|
||||
rpc GetLatestBlock(ChainSpec) returns (BlockID) {}
|
||||
// Return the compact block corresponding to the given block identifier
|
||||
rpc GetBlock(BlockID) returns (CompactBlock) {}
|
||||
// Return a list of consecutive compact blocks
|
||||
rpc GetBlockRange(BlockRange) returns (stream CompactBlock) {}
|
||||
|
||||
// Return the requested full (not compact) transaction (as from zcashd)
|
||||
rpc GetTransaction(TxFilter) returns (RawTransaction) {}
|
||||
// Submit the given transaction to the Zcash network
|
||||
rpc SendTransaction(RawTransaction) returns (SendResponse) {}
|
||||
|
||||
// Return the txids corresponding to the given t-address within the given block range
|
||||
rpc GetTaddressTxids(TransparentAddressBlockFilter) returns (stream RawTransaction) {}
|
||||
rpc GetTaddressBalance(AddressList) returns (Balance) {}
|
||||
rpc GetTaddressBalanceStream(stream Address) returns (Balance) {}
|
||||
|
||||
// Return the compact transactions currently in the mempool; the results
|
||||
// can be a few seconds out of date. If the Exclude list is empty, return
|
||||
// all transactions; otherwise return all *except* those in the Exclude list
|
||||
// (if any); this allows the client to avoid receiving transactions that it
|
||||
// already has (from an earlier call to this rpc). The transaction IDs in the
|
||||
// Exclude list can be shortened to any number of bytes to make the request
|
||||
// more bandwidth-efficient; if two or more transactions in the mempool
|
||||
// match a shortened txid, they are all sent (none is excluded). Transactions
|
||||
// in the exclude list that don't exist in the mempool are ignored.
|
||||
rpc GetMempoolTx(Exclude) returns (stream CompactTx) {}
|
||||
|
||||
// GetTreeState returns the note commitment tree state corresponding to the given block.
|
||||
// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
||||
// values also (even though they can be obtained using GetBlock).
|
||||
// The block can be specified by either height or hash.
|
||||
rpc GetTreeState(BlockID) returns (TreeState) {}
|
||||
|
||||
rpc GetAddressUtxos(GetAddressUtxosArg) returns (GetAddressUtxosReplyList) {}
|
||||
rpc GetAddressUtxosStream(GetAddressUtxosArg) returns (stream GetAddressUtxosReply) {}
|
||||
|
||||
// Return information about this lightwalletd instance and the blockchain
|
||||
rpc GetLightdInfo(Empty) returns (LightdInfo) {}
|
||||
// Testing-only
|
||||
rpc Ping(Duration) returns (PingResponse) {}
|
||||
}
|
94
src/main.rs
94
src/main.rs
|
@ -3,20 +3,35 @@ use bip39::{Mnemonic, Language, Seed};
|
|||
use failure::format_err;
|
||||
use std::path::Path;
|
||||
|
||||
use zcash_primitives::{consensus::{MainNetwork, Parameters}, transaction::Transaction};
|
||||
use zcash_client_backend::data_api::WalletRead;
|
||||
use zcash_primitives::{
|
||||
consensus::{
|
||||
MainNetwork, Parameters, NetworkUpgrade
|
||||
},
|
||||
transaction::Transaction
|
||||
};
|
||||
use zcash_client_backend::{data_api::{DecryptedTransaction, WalletRead, WalletWrite, error::Error}, decrypt_transaction};
|
||||
use zcash_client_sqlite::WalletDB;
|
||||
|
||||
fn main() {
|
||||
// TODO: get this path from CLI args
|
||||
let network = MainNetwork;
|
||||
let db_path = "/home/gmale/kg/work/clones/librustzcash/ZcashSdk_mainnet_Data.db";
|
||||
let db_data = wallet_db(db_path, MainNetwork).unwrap();
|
||||
let db_path_tmp = "/home/gmale/kg/work/clones/librustzcash/temp.db";
|
||||
|
||||
let db_data = wallet_db(db_path, network).unwrap();
|
||||
let db_tmp = wallet_db(db_path_tmp, network).unwrap();
|
||||
|
||||
let phrase = "chat error pigeon main parade window scene breeze scene frog inherit enforce wise resist rotate van pistol coral tide faint arm elegant velvet anxiety";
|
||||
|
||||
show_seed(phrase);
|
||||
let tx = load_tx(&db_data, 3);
|
||||
println!("loaded tx: {:?}", &tx.unwrap());
|
||||
let tx = load_tx(&db_data, 25);
|
||||
let t = tx.unwrap();
|
||||
println!("loaded tx: {:?}", &t);
|
||||
println!("tx.vout: {} tx.vin: {} tx.shout: {} tx.shin: {}", t.vout.len(), t.vin.len(), t.shielded_outputs.len(), t.shielded_spends.len());
|
||||
|
||||
let mut db_tmp = db_tmp.get_update_ops().unwrap();
|
||||
println!("decrypting transaction into temp DB...");
|
||||
decrypt_tx_to(&db_data, &mut db_tmp, &network, 3).unwrap()
|
||||
}
|
||||
|
||||
fn wallet_db<P: Parameters>(db_path: &str, params: P) -> Result<WalletDB<P>, failure::Error> {
|
||||
|
@ -28,10 +43,49 @@ fn wallet_db<P: Parameters>(db_path: &str, params: P) -> Result<WalletDB<P>, fai
|
|||
}
|
||||
}
|
||||
|
||||
fn load_tx(db_data: &WalletDB<MainNetwork>, id_tx: i64) -> Result<Transaction, failure::Error> {
|
||||
// fn fetch_tx<P: Parameters>(db_data: &WalletDB<P>, id_tx: i64) -> Result<Transaction, failure::Error> {
|
||||
// let tx = load_tx(&db_data, id_tx);
|
||||
// }
|
||||
|
||||
fn load_tx<P: Parameters>(db_data: &WalletDB<P>, id_tx: i64) -> Result<Transaction, failure::Error> {
|
||||
return (&db_data).get_transaction(id_tx).map_err(|_| format_err!("Invalid amount, out of range"));
|
||||
}
|
||||
|
||||
/// Take a transaction out of one db, then decrypt it and store it in another db.
|
||||
/// This is useful for exercising decrypt code to see what it discovers,
|
||||
/// without contaminating the original data.
|
||||
fn decrypt_tx_to<P, W, E, N>(db_src: &WalletDB<P>, db_dest: &mut W, params: &P, id_tx: i64) -> Result<(), E>
|
||||
where
|
||||
E: From<Error<N>>,
|
||||
P: Parameters,
|
||||
W: WalletWrite<Error = E>
|
||||
{
|
||||
let tx = &load_tx(&db_src, id_tx).unwrap();
|
||||
// Fetch the ExtendedFullViewingKeys we are tracking
|
||||
let extfvks = db_src.get_extended_full_viewing_keys().unwrap();
|
||||
|
||||
// Height is block height for mined transactions, and the "mempool height" (chain height + 1)
|
||||
// for mempool transactions.
|
||||
let height = db_src
|
||||
.get_tx_height(tx.txid()).unwrap()
|
||||
.or(db_src
|
||||
.block_height_extrema().unwrap()
|
||||
.map(|(_, max_height)| max_height + 1))
|
||||
.or_else(|| params.activation_height(NetworkUpgrade::Sapling))
|
||||
.ok_or(Error::SaplingNotActive)?;
|
||||
|
||||
let sapling_outputs = decrypt_transaction(params, height, tx, &extfvks);
|
||||
let nullifiers = db_src.get_nullifiers().unwrap();
|
||||
|
||||
if !(sapling_outputs.is_empty() && tx.vout.is_empty()) {
|
||||
db_dest.store_decrypted_tx(
|
||||
&DecryptedTransaction { tx, sapling_outputs: &sapling_outputs, },
|
||||
&nullifiers,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -42,4 +96,30 @@ fn show_seed(phrase: &str) {
|
|||
let mnemonic = Mnemonic::from_phrase(phrase, Language::English).unwrap();
|
||||
let seed = Seed::new(&mnemonic, "");
|
||||
println!("{:X}", seed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// GRPC things
|
||||
|
||||
// fn init_grpc() -> CompactTxStreamerClient {
|
||||
// let tls = {
|
||||
// let mut tls_connector = tls_api_rustls::TlsConnector::builder()?;
|
||||
|
||||
// if tls_api_rustls::TlsConnector::supports_alpn() {
|
||||
// tls_connector.set_alpn_protocols(&[b"h2"])?;
|
||||
// }
|
||||
|
||||
// let tls_connector = tls_connector.build()?;
|
||||
|
||||
// let tls_connector = Arc::new(tls_connector);
|
||||
// ClientTlsOption::Tls(LIGHTWALLETD_HOST.to_owned(), tls_connector)
|
||||
// };
|
||||
|
||||
// return grpc::ClientBuilder::new(LIGHTWALLETD_HOST, LIGHTWALLETD_PORT)
|
||||
// .explicit_tls(tls)
|
||||
// .build()
|
||||
// .map(|c| service_grpc::CompactTxStreamerClient::with_client(Arc::new(c)))?;
|
||||
|
||||
// }
|
Loading…
Reference in New Issue