@@ -21,7 +21,7 @@ Run `silentdragonlite-cli help` to see a list of all commands.
|
||||
### Note Management
|
||||
silentdragonlite does automatic note and utxo management, which means it doesn't allow you to manually select which address to send outgoing transactions from. It follows these principles:
|
||||
* Defaults to sending shielded transactions, even if you're sending to a transparent address
|
||||
* Sapling funds need at least 4 confirmations before they can be spent
|
||||
* Sapling funds need at least 5 confirmations before they can be spent
|
||||
* Can select funds from multiple shielded addresses in the same transaction
|
||||
* Will automatically shield your transparent funds at the first opportunity
|
||||
* When sending an outgoing transaction to a shielded address, silentdragonlite can decide to use the transaction to additionally shield your transparent funds (i.e., send your transparent funds to your own shielded address in the same transaction)
|
||||
|
||||
@@ -1,35 +1,41 @@
|
||||
FROM rust:1.38
|
||||
FROM ubuntu:16.04
|
||||
LABEL Description="Rust compile env for Linux + Windows (cross)"
|
||||
|
||||
RUN apt update
|
||||
RUN apt install -y build-essential mingw-w64 gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf
|
||||
RUN apt install -y build-essential mingw-w64 gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf curl vim wget
|
||||
|
||||
# Get Rust
|
||||
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y
|
||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||
|
||||
RUN rustup target add x86_64-pc-windows-gnu
|
||||
RUN rustup target add aarch64-unknown-linux-gnu
|
||||
RUN rustup target add armv7-unknown-linux-gnueabihf
|
||||
|
||||
# Append the linker to the cargo config for Windows cross compile
|
||||
RUN echo "[target.x86_64-pc-windows-gnu]" >> /usr/local/cargo/config && \
|
||||
echo "linker = '/usr/bin/x86_64-w64-mingw32-gcc'" >> /usr/local/cargo/config
|
||||
RUN echo "[target.x86_64-pc-windows-gnu]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/x86_64-w64-mingw32-gcc'" >> /root/.cargo/config
|
||||
|
||||
RUN echo "[target.aarch64-unknown-linux-gnu]" >> /usr/local/cargo/config && \
|
||||
echo "linker = '/usr/bin/aarch64-linux-gnu-gcc'" >> /usr/local/cargo/config
|
||||
RUN echo "[target.aarch64-unknown-linux-gnu]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/aarch64-linux-gnu-gcc'" >> /root/.cargo/config
|
||||
|
||||
RUN echo "[target.armv7-unknown-linux-gnueabihf]" >> /usr/local/cargo/config && \
|
||||
echo "linker = '/usr/bin/arm-linux-gnueabihf-gcc'" >> /usr/local/cargo/config
|
||||
RUN echo "[target.armv7-unknown-linux-gnueabihf]" >> /root/.cargo/config && \
|
||||
echo "linker = '/usr/bin/arm-linux-gnueabihf-gcc'" >> /root/.cargo/config
|
||||
|
||||
ENV CC_x86_64_unknown_linux_musl="gcc"
|
||||
ENV CC_aarch64_unknown_linux_gnu="aarch64-linux-gnu-gcc"
|
||||
ENV CC_armv7_unknown_linux_gnueabhihf="arm-linux-gnueabihf-gcc"
|
||||
|
||||
# This is a bug fix for the windows cross compiler for Rust.
|
||||
RUN cp /usr/x86_64-w64-mingw32/lib/crt2.o /usr/local/rustup/toolchains/1.38.0-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o
|
||||
RUN cp /usr/x86_64-w64-mingw32/lib/crt2.o /root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-pc-windows-gnu/lib/crt2.o
|
||||
|
||||
# For windows cross compilation, use a pre-build binary. Remember to set the
|
||||
# SODIUM_LIB_DIR for windows cross compilation
|
||||
RUN cd /opt && wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.17-mingw.tar.gz && \
|
||||
tar xvf libsodium-1.0.17-mingw.tar.gz
|
||||
|
||||
RUN apt install -y git
|
||||
|
||||
# Cargo fetch the dependencies so we don't download them over and over again
|
||||
RUN cd /tmp && git clone https://github.com/adityapk00/silentdragonlite-light-cli.git && \
|
||||
cd silentdragonlite-light-cli && \
|
||||
|
||||
@@ -35,6 +35,26 @@ impl Command for SyncCommand {
|
||||
}
|
||||
}
|
||||
|
||||
struct EncryptionStatusCommand {}
|
||||
impl Command for EncryptionStatusCommand {
|
||||
fn help(&self) -> String {
|
||||
let mut h = vec![];
|
||||
h.push("Check if the wallet is encrypted and if it is locked");
|
||||
h.push("Usage:");
|
||||
h.push("encryptionstatus");
|
||||
h.push("");
|
||||
|
||||
h.join("\n")
|
||||
}
|
||||
|
||||
fn short_help(&self) -> String {
|
||||
"Check if the wallet is encrypted and if it is locked".to_string()
|
||||
}
|
||||
|
||||
fn exec(&self, _args: &[&str], lightclient: &LightClient) -> String {
|
||||
lightclient.do_encryption_status().pretty(2)
|
||||
}
|
||||
}
|
||||
|
||||
struct SyncStatusCommand {}
|
||||
impl Command for SyncStatusCommand {
|
||||
@@ -440,9 +460,7 @@ impl Command for SendCommand {
|
||||
|
||||
// Check for a single argument that can be parsed as JSON
|
||||
let send_args = if args.len() == 1 {
|
||||
// Sometimes on the command line, people use "'" for the quotes, which json::parse doesn't
|
||||
// understand. So replace it with double-quotes
|
||||
let arg_list = args[0].replace("'", "\"");
|
||||
let arg_list = args[0];
|
||||
|
||||
let json_args = match json::parse(&arg_list) {
|
||||
Ok(j) => j,
|
||||
@@ -731,27 +749,28 @@ impl Command for QuitCommand {
|
||||
pub fn get_commands() -> Box<HashMap<String, Box<dyn Command>>> {
|
||||
let mut map: HashMap<String, Box<dyn Command>> = HashMap::new();
|
||||
|
||||
map.insert("sync".to_string(), Box::new(SyncCommand{}));
|
||||
map.insert("syncstatus".to_string(), Box::new(SyncStatusCommand{}));
|
||||
map.insert("rescan".to_string(), Box::new(RescanCommand{}));
|
||||
map.insert("help".to_string(), Box::new(HelpCommand{}));
|
||||
map.insert("balance".to_string(), Box::new(BalanceCommand{}));
|
||||
map.insert("addresses".to_string(), Box::new(AddressCommand{}));
|
||||
map.insert("height".to_string(), Box::new(HeightCommand{}));
|
||||
map.insert("export".to_string(), Box::new(ExportCommand{}));
|
||||
map.insert("info".to_string(), Box::new(InfoCommand{}));
|
||||
map.insert("send".to_string(), Box::new(SendCommand{}));
|
||||
map.insert("save".to_string(), Box::new(SaveCommand{}));
|
||||
map.insert("quit".to_string(), Box::new(QuitCommand{}));
|
||||
map.insert("list".to_string(), Box::new(TransactionsCommand{}));
|
||||
map.insert("notes".to_string(), Box::new(NotesCommand{}));
|
||||
map.insert("new".to_string(), Box::new(NewAddressCommand{}));
|
||||
map.insert("seed".to_string(), Box::new(SeedCommand{}));
|
||||
map.insert("encrypt".to_string(), Box::new(EncryptCommand{}));
|
||||
map.insert("decrypt".to_string(), Box::new(DecryptCommand{}));
|
||||
map.insert("unlock".to_string(), Box::new(UnlockCommand{}));
|
||||
map.insert("lock".to_string(), Box::new(LockCommand{}));
|
||||
map.insert("fixbip39bug".to_string(), Box::new(FixBip39BugCommand{}));
|
||||
map.insert("sync".to_string(), Box::new(SyncCommand{}));
|
||||
map.insert("syncstatus".to_string(), Box::new(SyncStatusCommand{}));
|
||||
map.insert("encryptionstatus".to_string(), Box::new(EncryptionStatusCommand{}));
|
||||
map.insert("rescan".to_string(), Box::new(RescanCommand{}));
|
||||
map.insert("help".to_string(), Box::new(HelpCommand{}));
|
||||
map.insert("balance".to_string(), Box::new(BalanceCommand{}));
|
||||
map.insert("addresses".to_string(), Box::new(AddressCommand{}));
|
||||
map.insert("height".to_string(), Box::new(HeightCommand{}));
|
||||
map.insert("export".to_string(), Box::new(ExportCommand{}));
|
||||
map.insert("info".to_string(), Box::new(InfoCommand{}));
|
||||
map.insert("send".to_string(), Box::new(SendCommand{}));
|
||||
map.insert("save".to_string(), Box::new(SaveCommand{}));
|
||||
map.insert("quit".to_string(), Box::new(QuitCommand{}));
|
||||
map.insert("list".to_string(), Box::new(TransactionsCommand{}));
|
||||
map.insert("notes".to_string(), Box::new(NotesCommand{}));
|
||||
map.insert("new".to_string(), Box::new(NewAddressCommand{}));
|
||||
map.insert("seed".to_string(), Box::new(SeedCommand{}));
|
||||
map.insert("encrypt".to_string(), Box::new(EncryptCommand{}));
|
||||
map.insert("decrypt".to_string(), Box::new(DecryptCommand{}));
|
||||
map.insert("unlock".to_string(), Box::new(UnlockCommand{}));
|
||||
map.insert("lock".to_string(), Box::new(LockCommand{}));
|
||||
map.insert("fixbip39bug".to_string(), Box::new(FixBip39BugCommand{}));
|
||||
|
||||
Box::new(map)
|
||||
}
|
||||
|
||||
@@ -639,6 +639,14 @@ impl LightClient {
|
||||
res
|
||||
}
|
||||
|
||||
pub fn do_encryption_status(&self) -> JsonValue {
|
||||
let wallet = self.wallet.read().unwrap();
|
||||
object!{
|
||||
"encrypted" => wallet.is_encrypted(),
|
||||
"locked" => !wallet.is_unlocked_for_spending()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_list_transactions(&self) -> JsonValue {
|
||||
let wallet = self.wallet.read().unwrap();
|
||||
|
||||
|
||||
@@ -769,7 +769,7 @@ impl LightWallet {
|
||||
None => true
|
||||
}
|
||||
})
|
||||
.map(|nd| if nd.spent.is_none() && nd.unconfirmed_spent.is_none() { nd.note.value } else { 0 })
|
||||
.map(|nd| if nd.spent.is_none() { nd.note.value } else { 0 })
|
||||
.sum::<u64>()
|
||||
})
|
||||
.sum::<u64>() as u64
|
||||
@@ -1471,7 +1471,7 @@ impl LightWallet {
|
||||
if selected_value < u64::from(target_value) {
|
||||
let e = format!(
|
||||
"Insufficient verified funds (have {}, need {:?}). NOTE: funds need {} confirmations before they can be spent.",
|
||||
selected_value, target_value, self.config.anchor_offset
|
||||
selected_value, target_value, self.config.anchor_offset + 1
|
||||
);
|
||||
error!("{}", e);
|
||||
return Err(e);
|
||||
|
||||
@@ -706,6 +706,12 @@ fn test_z_spend_to_z() {
|
||||
let branch_id = u32::from_str_radix("76b809bb", 16).unwrap();
|
||||
let (ss, so) = get_sapling_params().unwrap();
|
||||
|
||||
// Make sure that the balance exists
|
||||
{
|
||||
assert_eq!(wallet.zbalance(None), AMOUNT1);
|
||||
assert_eq!(wallet.verified_zbalance(None), AMOUNT1);
|
||||
}
|
||||
|
||||
// Create a tx and send to address
|
||||
let raw_tx = wallet.send_to_address(branch_id, &ss, &so,
|
||||
vec![(&ext_address, AMOUNT_SENT, Some(outgoing_memo.clone()))]).unwrap();
|
||||
@@ -736,6 +742,12 @@ fn test_z_spend_to_z() {
|
||||
assert_eq!(mem[&sent_txid].outgoing_metadata[0].memo.to_utf8().unwrap().unwrap(), outgoing_memo);
|
||||
}
|
||||
|
||||
{
|
||||
// The wallet should deduct this from the verified balance. The zbalance still includes it
|
||||
assert_eq!(wallet.zbalance(None), AMOUNT1);
|
||||
assert_eq!(wallet.verified_zbalance(None), 0);
|
||||
}
|
||||
|
||||
let mut cb3 = FakeCompactBlock::new(2, block_hash);
|
||||
cb3.add_tx(&sent_tx);
|
||||
wallet.scan_block(&cb3.as_bytes()).unwrap();
|
||||
@@ -751,6 +763,7 @@ fn test_z_spend_to_z() {
|
||||
// The sent tx should generate change
|
||||
assert_eq!(txs[&sent_txid].notes.len(), 1);
|
||||
assert_eq!(txs[&sent_txid].notes[0].note.value, AMOUNT1 - AMOUNT_SENT - fee);
|
||||
assert_eq!(wallet.zbalance(None), AMOUNT1 - AMOUNT_SENT - fee);
|
||||
assert_eq!(txs[&sent_txid].notes[0].is_change, true);
|
||||
assert_eq!(txs[&sent_txid].notes[0].spent, None);
|
||||
assert_eq!(txs[&sent_txid].notes[0].unconfirmed_spent, None);
|
||||
|
||||
Reference in New Issue
Block a user