Giter VIP home page Giter VIP logo

liana's People

Contributors

darosior avatar edouardparis avatar eunovo avatar fanquake avatar jp1ac4 avatar kloaec avatar omahs avatar pythcoiner avatar raphjaph avatar stevenroose avatar trigger67 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

liana's Issues

Couple `block_height` and `block_time` together in DB and Bitcoin interfaces

In #29 we introduced the block time in addition to the block height in the confirmed_coins and confirm_coins result, as well as in the structures managing transaction (GetTxRes and DbCoin for instance).

Both fields are optional, but they should always either both be there or both not be. It would be cleaner to have a BlockInfo that itself is optional with time and height non-optional fields. So that we can avoid passing around confusing tuples, and avoid unwrapping on one field after we checked the other was present.

Automated coin selection

The first release of the software won't come with any automated coin selection. Users will have to pick their coins on the interface when crafting a spending transaction ("coin control"). We might want to implement some automated coin selections in the future.

If we do it, what coin selections should we implement? How should people define which one to use? I can think of a few strategies we could have:

  • Regular BnB
  • Oldest-coin (or a BnB biased toward using old coins) first to prevent them to have to rotate their coins in a dedicated transaction.
  • Regular BnB + batch in coins that are about to "expire"

Also, i don't think it's worth re-implementing the wheel. Coin selection algorithm can be tricky to implement, and have been implemented many times already. Let's just re-use and contribute review to an existing implementation. For this purpose i've asked @danielabrozzoni if she thought it could be reasonable to make @bitcoindevkit's coinselection into its own crate.

Thoughts? Is there any interest from users to have this?

Absolute timelocks support

For now, we restrict the descriptors to relative timelocks. This presents two limitations:

  • The wallet has to be used in order to "rotate" the coins (re-start the timelock)
  • The timelock value is 2 bytes and thus can't be greater than 2**16 (65536), that is approximately 15 months:
    >>> 2**16 / 6 / 24 / 365
    1.2468797564687975

This makes it not a very good fit for cold wallets that are never accessed, and for which not all coins are used in a transaction around once per year.
This also makes it hard for a non-technical heir to sweep the coins of a deceased parent that was using Liana: not all coins may be available at the same height.

The main and obvious drawback of using an absolute timelock is that the descriptor would be have an EOL. After (or shortly before) the expiration of the absolute timelock, one would have to sweep their coins to a new descriptor with a later expiration date. Still, this tradeoff may be worth it for some usages such as the one depicted above (longer timelocks without the need to rotate, simpler inheritance recovery).

Thoughts?

Documentation

There are two main documentation efforts:

  • A README.md to present the project, along with a CONTRIBUTING.md and common documentation (API.md, etc..)
  • A RECOVERY.md documenting how one can use the timelocked recovery path to spend the coins in case of [a parent death / a key loss]

Hot/Laptop signer (signing without a hardware signing device)

For the first release of Liana, we plan to support the only two hardware signing devices supporting Miniscript: the Ledger and the Specter hardware wallets.

Some people using hot keys on their laptop at the moment might be willing to switch to Liana for, say, the inheritance planning but not be willing to start using a hardware signing device. For this usecase we could implement private key storage in the data directory and signing on the GUI directly without having to connect a signing device.
First, is there such an interest?

Second, if we decide to do it we need to discuss how to approach it. Do we want to encrypt it? Probably? How long do we keep it in memory? How do we mlock the secrets in a portable manner? Is Rust going to be a footgun when managing secrets?

Thoughs?

Multi timelocked paths support

The first version will only support one directly available path and a second, timelocked, path. We plan to add multisig support to each of these paths in the second version (#53).

In the third release of the software the user should be able to use multiple timelocked paths. For instance (throwing random ideas, haven't thought this setup through):

  • After 6 months my recovery key with a cosigner
  • After 8 months my recovery key alone
  • After 10 months a multisig between my heirs
  • After 12 months a smaller-threshold multisig between my heirs
  • After 14 months some kind of social recovery because everyone fucked up somehow

Make SQLite a (default) feature

Technically SQLite isn't needed, as one could implement the DatabaseInterface trait themselves. For now however it is the only database we provide.

Make the SQLite dependency, and implementation of DatabaseInterface, a feature enabled by default.

Rescan integration in the GUI

Needs #28.

  • When importing a fresh descriptor through the installer, we should hint at rescanning to retrieve coins that were received before the import
  • We should have a rescan button in the settings

`macos-latest` + `rustc 1.48` = ` error: linking with cc failed: exit code: 1`

The rust 1.48 build started failing on macOS in #67.

   Compiling proc-macro2 v1.0.40
   Compiling cc v1.0.73
   Compiling quote v1.0.20
     Running `rustc --crate-name build_script_build --edition=2018 /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-1.0.40/build.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="default"' --cfg 'feature="proc-macro"' -C metadata=a775773b1c4d6d13 -C extra-filename=-a775773b1c4d6d13 --out-dir /Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13 -L dependency=/Users/runner/work/minisafe/minisafe/target/debug/deps --cap-lints allow`
     Running `rustc --crate-name cc --edition=2018 /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/cc-1.0.73/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=6951f41806db0446 -C extra-filename=-6951f41806db0446 --out-dir /Users/runner/work/minisafe/minisafe/target/debug/deps -L dependency=/Users/runner/work/minisafe/minisafe/target/debug/deps --cap-lints allow`
     Running `rustc --crate-name build_script_build --edition=2018 /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/quote-1.0.20/build.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="default"' --cfg 'feature="proc-macro"' -C metadata=43d0865adc1d5c42 -C extra-filename=-43d0865adc1d5c42 --out-dir /Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42 -L dependency=/Users/runner/work/minisafe/minisafe/target/debug/deps --cap-lints allow`
   Compiling unicode-ident v1.0.2
     Running `rustc --crate-name unicode_ident --edition=2018 /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/unicode-ident-1.0.2/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=830f4edd07508c85 -C extra-filename=-830f4edd07508c85 --out-dir /Users/runner/work/minisafe/minisafe/target/debug/deps -L dependency=/Users/runner/work/minisafe/minisafe/target/debug/deps --cap-lints allow`
   Compiling syn v1.0.98
     Running `rustc --crate-name build_script_build --edition=2018 /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-1.0.98/build.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="clone-impls"' --cfg 'feature="default"' --cfg 'feature="derive"' --cfg 'feature="parsing"' --cfg 'feature="printing"' --cfg 'feature="proc-macro"' --cfg 'feature="quote"' -C metadata=f23be10b00cb500d -C extra-filename=-f23be10b00cb500d --out-dir /Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d -L dependency=/Users/runner/work/minisafe/minisafe/target/debug/deps --cap-lints allow`
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-m64" "-arch" "x86_64" "-L" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.0.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.1.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.10.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.11.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.12.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.13.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.14.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.15.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.2.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.3.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.4.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.5.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.6.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.7.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.8.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.build_script_build.ac18yd7a-cgu.9.rcgu.o" "-o" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42" "/Users/runner/work/minisafe/minisafe/target/debug/build/quote-43d0865adc1d5c42/build_script_build-43d0865adc1d5c42.2vq3dqw043l0ru7x.rcgu.o" "-Wl,-dead_strip" "-nodefaultlibs" "-L" "/Users/runner/work/minisafe/minisafe/target/debug/deps" "-L" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd-688c1376a25c049d.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libobject-fec020208bc1ad3c.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libaddr2line-38540dcacc9fd218.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgimli-6f613179f618c598.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_demangle-4d1a5d7118aaeaf2.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libhashbrown-d88fab3b1b9d8356.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_alloc-a21754532a052f2f.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libunwind-2e9ebc4127641a96.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcfg_if-82d0f961232a05ca.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liblibc-370b1b71f08bac3c.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liballoc-816106c1f35f5421.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_core-20f3a030f1a56a86.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcore-60333aa00936c5ce.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_builtins-116aaeaea873ef94.rlib" "-lSystem" "-lresolv" "-lc" "-lm"
  = note: ld: in /Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib(lib.rmeta), archive member 'lib.rmeta' with length 29624 is not mach-o or llvm bitcode file '/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib'
          clang: error: linker command failed with exit code 1 (use -v to see invocation)
          

error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-m64" "-arch" "x86_64" "-L" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.0.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.1.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.10.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.11.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.12.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.13.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.14.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.15.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.2.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.3.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.4.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.5.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.6.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.7.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.8.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.build_script_build.8y8agsyp-cgu.9.rcgu.o" "-o" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d" "/Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d/build_script_build-f23be10b00cb500d.3iv5l76q37nbdd9h.rcgu.o" "-Wl,-dead_strip" "-nodefaultlibs" "-L" "/Users/runner/work/minisafe/minisafe/target/debug/deps" "-L" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd-688c1376a25c049d.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libobject-fec020208bc1ad3c.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libaddr2line-38540dcacc9fd218.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgimli-6f613179f618c598.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_demangle-4d1a5d7118aaeaf2.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libhashbrown-d88fab3b1b9d8356.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_alloc-a21754532a052f2f.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libunwind-2e9ebc4127641a96.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcfg_if-82d0f961232a05ca.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liblibc-370b1b71f08bac3c.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liballoc-816106c1f35f5421.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_core-20f3a030f1a56a86.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcore-60333aa00936c5ce.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_builtins-116aaeaea873ef94.rlib" "-lSystem" "-lresolv" "-lc" "-lm"
  = note: ld: in /Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib(lib.rmeta), archive member 'lib.rmeta' with length 29624 is not mach-o or llvm bitcode file '/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib'
          clang: error: linker command failed with exit code 1 (use -v to see invocation)
          

error: aborting due to previous error

error: aborting due to previous error

error: could not compile `syn`

Caused by:
  process didn't exit successfully: `rustc --crate-name build_script_build --edition=2018 /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-1.0.98/build.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="clone-impls"' --cfg 'feature="default"' --cfg 'feature="derive"' --cfg 'feature="parsing"' --cfg 'feature="printing"' --cfg 'feature="proc-macro"' --cfg 'feature="quote"' -C metadata=f23be10b00cb500d -C extra-filename=-f23be10b00cb500d --out-dir /Users/runner/work/minisafe/minisafe/target/debug/build/syn-f23be10b00cb500d -L dependency=/Users/runner/work/minisafe/minisafe/target/debug/deps --cap-lints allow` (exit code: 1)
warning: build failed, waiting for other jobs to finish...
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-m64" "-arch" "x86_64" "-L" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.0.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.1.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.10.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.11.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.12.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.13.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.14.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.15.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.2.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.3.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.4.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.5.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.6.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.7.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.8.rcgu.o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.build_script_build.6v3bvynn-cgu.9.rcgu.o" "-o" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13" "/Users/runner/work/minisafe/minisafe/target/debug/build/proc-macro2-a775773b1c4d6d13/build_script_build-a775773b1c4d6d13.3mcole49nmerkt58.rcgu.o" "-Wl,-dead_strip" "-nodefaultlibs" "-L" "/Users/runner/work/minisafe/minisafe/target/debug/deps" "-L" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd-688c1376a25c049d.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libobject-fec020208bc1ad3c.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libaddr2line-38540dcacc9fd218.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgimli-6f613179f618c598.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_demangle-4d1a5d7118aaeaf2.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libhashbrown-d88fab3b1b9d8356.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_alloc-a21754532a052f2f.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libunwind-2e9ebc4127641a96.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcfg_if-82d0f961232a05ca.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liblibc-370b1b71f08bac3c.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liballoc-816106c1f35f5421.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_core-20f3a030f1a56a86.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcore-60333aa00936c5ce.rlib" "/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_builtins-116aaeaea873ef94.rlib" "-lSystem" "-lresolv" "-lc" "-lm"
  = note: ld: in /Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib(lib.rmeta), archive member 'lib.rmeta' with length 29624 is not mach-o or llvm bitcode file '/Users/runner/.rustup/toolchains/1.48-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-078f89c2cdb6d46b.rlib'
          clang: error: linker command failed with exit code 1 (use -v to see invocation)
          

error: aborting due to previous error

error: build failed
Error: Process completed with exit code 101.

Ledger interface in the GUI

This is a lot of work. We don't want to pull a whole CPython in the binary so we can't "just use HWI lolz". We need to:

  • #57
  • Implement the Ledger interface in our "rust HWI" crate.
  • Implement registration of a descriptor on the Ledger in the installer.
  • Implement signing of PSBTs in the upcoming Spend screens in the GUI.

Distribution of binaries

Once we have reproducibly-built binaries (#41), we'll need to distribute them. I'll probably sign them with my GPG key, and invite any contributor to do the same (again taking a lot of inspiration from what the Bitcoin Core project did).

We'll probably have a website for hosting binaries, as well as publishing them here as releases. We need to decide what OS-architecture pairs we want to target, as well as the release process (how do we do branch-offs, bugfix releases, EOL, etc..).

RBF support for Spend transactions

The biggest part is probably going to be the GUI's. Should we have a "bump fee" interface or a whole "replace by another Spend" interface?

Make `confirm_spend` database interface explicit

At the moment, as introduced in #29, this method needs to:

  1. Replace the existing spend txid with the given one if it's different
  2. Mark the spend txid as confirmed

It would be clearer to have two different methods for those 2 different responsibilities.

Clippy

Since we are starting fresh, let's fix all the clippy lints and add it to the CI.

Fee estimation

In the first version of the software, users will have to input the feerate they want to use when creating a spending transaction. They may want to have an automated estimation instead. We could provide this by querying our Bitcoin backend for a fee estimate. If it fails we could optionally fall back to an aggregate of the estimation given by some web APIs. The query could also be made through Tor.

This is something we can iterate over. We don't need to do all at once. But users must have a way to opt-in or out.

Thoughts? Is it something users would be interested in?

UI / UX review of the GUI for the first version

Before releasing the first version of the software, we need to make a reasonable effort to have a good UX in the GUI. This can be split-off into multiple stages:

  1. Inform the development of the GUI. This can for instance take the form of a Bitcoin designer review club.
  2. Feature freeze for the first version.
  3. First pass at a UI / UX review from our end.
  4. Second pass with someone who doesn't know well the product, and is ideally well versed in design and user interfaces.

This issue is an umbrella to centralize the discussion around improving the GUI for the first release of the software. Discussions on specific technicalities can go into their own issue and be linked from there. Discussions on what isn't prioritized for the first version should go in their own issues / another umbrella issues.
Let's discuss everything else here.

Taproot support

As Miniscript for Tapscript isn't formally specified yet, we are going to start without Taproot support. We need to have Taproot support as soon as possible, and for this i need to make progress on the C++ implementation of Tap-Miniscript.

Hopefully we'll have it in Bitcoin Core 25.0, in approximately 6 months from now. Alternately, maybe we can carve out something similar to what we used to do in revaultd before we had Miniscript support in bitcoind (watch by address)... But that's ugly 😭

Spend screens in the GUI

The interface to create and manage Spend transactions was introduced on the daemon part. Now we need the GUI to use it.

Alternative Bitcoin backend(s)

The only Bitcoin backend the first release will have, and that we'll support in the near future, is Bitcoin Core using a watchonly wallet there. Other software tend to (ab)use the Electrum protocol and other kinds of backends (explorer APIs for instance). We might want to support other Bitcoin backends than Bitcoin Core.

For instance i can think of those as being desirable:

  • Electrum (but we need to introduce Tor, and/or TLS... Meh)
  • Maybe a Bitcoin Core backend that does not require a watchonly wallet (scantxoutset?)

Thoughts? Is there interest from users for prioritising this feature?

The `test_update_spend` test may pass an invalid PSBT to `updatespend`

I could reproduce this by stress-testing the functional test suite (running each test a dozen time, and running 20 of them in parallel). Here is the trace:

minisafed = <test_framework.minisafed.Minisafed object at 0x7f016ab015b0>, bitcoind = <test_framework.bitcoind.Bitcoind object at 0x7f016a235190>                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                           
    def test_update_spend(minisafed, bitcoind):                                                                                                                                                                                                                                                                                                                            
        # Start by creating a Spend PSBT                                                                                                                                                                                                                                                                                                                                   
        addr = minisafed.rpc.getnewaddress()["address"]                                                                                                                                                                                                                                                                                                                    
        bitcoind.rpc.sendtoaddress(addr, 0.2567)                                                                                                                                                                                                                                                                                                                           
        wait_for(lambda: len(minisafed.rpc.listcoins()["coins"]) > 0)                                                                                                                                                                                                                                                                                                      
        outpoints = [c["outpoint"] for c in minisafed.rpc.listcoins()["coins"]]                                                                                                                                                                                                                                                                                            
        destinations = {                                                                                                                                                                                                                                                                                                                                                   
            bitcoind.rpc.getnewaddress(): 200_000,                                                                                                                                                                                                                                                                                                                         
        }                                                                                                                                                                                                                                                                                                                                                                  
        res = minisafed.rpc.createspend(outpoints, destinations, 6)                                                                                                                                                                                                                                                                                                        
        assert "psbt" in res                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                           
        # Now update it                                                                                                                                                                                                                                                                                                                                                    
        assert len(minisafed.rpc.listspendtxs()["spend_txs"]) == 0                                                                                                                                                                                                                                                                                                         
        minisafed.rpc.updatespend(res["psbt"])                                                                                                                                                                                                                                                                                                                             
        list_res = minisafed.rpc.listspendtxs()["spend_txs"]                                                                                                                                                                                                                                                                                                               
        assert len(list_res) == 1                                                                                                                                                                                                                                                                                                                                          
        assert list_res[0]["psbt"] == res["psbt"]                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                           
        # Keep a copy for later.                                                                                                                                                                                                                                                                                                                                           
        psbt_no_sig = PSBT()                                                                                                                                                                                                                                                                                                                                               
        psbt_no_sig.deserialize(res["psbt"])                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                           
        # We can add a signature and update it                                                                                                                                                                                                                                                                                                                             
        psbt_sig_a = PSBT()                                                                                                                                                                                                                                                                                                                                                
        psbt_sig_a.deserialize(res["psbt"])                                                                                                                                                                                                                                                                                                                                
        dummy_pk_a = bytes.fromhex(                                                                                                                                                                                                                                                                                                                                        
            "0375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c"                                                                                                                                                                                                                                                                                           
        )                                                                                                                                                                                                                                                                                                                                                                  
        dummy_sig_a = bytes.fromhex(                                                                                                                                                                                                                                                                                                                                       
            "304402202b925395cfeaa0171a7a92982bb4891acc4a312cbe7691d8375d36796d5b570a0220378a8ab42832848e15d1aedded5fb360fedbdd6c39226144e527f0f1e19d5398"                                                                                                                                                                                                                 
        )                                                                                                                                                                                                                                                                                                                                                                  
        psbt_sig_a.inputs[0].partial_sigs[dummy_pk_a] = dummy_sig_a                                                                                                                                                                                                                                                                                                        
        psbt_sig_a_ser = psbt_sig_a.serialize()                                                                                                                                                                                                                                                                                                                            
>       minisafed.rpc.updatespend(psbt_sig_a_ser)                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                           
tests/test_rpc.py:204:                                                                                                                                                                                                                                                                                                                                                     
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _                                                                                                                                                                                        
tests/test_framework/utils.py:192: in wrapper                                                                                                                                                                                                                                                                                                                              
    return self.call(name, params=args or kwargs)                                                                                                                                                                                                                                                                                                                          
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                           
self = <test_framework.utils.UnixDomainSocketRpc object at 0x7f016ab01970>, method = 'updatespend'                                                                                                                                                                                                                                                                         
params = ('cHNidP8BAH0CAAAAAdZ3tAhuLjlmIiMbOglxoMs9U7RhO44UVGT5YIwCJfkSAAAAAAD/////AkANAwAAAAAAFgAU9lUPboqXX6UK33mwhwwCN4RT+u40...AbP80ILAnT1JcB4/AUQhA7dGO9gcJ01qHlitjRlyEFmo6j1WefLxWHfB/4BDHen1rHNkdqkU/g/83EjSWTTSvK0AMjPiYu8Sx5KIrQPo/QCyaAAAAA==',)                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                           
    def call(self, method, params={}):                                                                                                                                                                                                                                                                                                                                     
        self.logger.debug(f"Calling {method} with params {params}")                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                    
        # FIXME: we open a new socket for every readobj call...                                                                                                                     
        sock = UnixSocket(self.socket_path)                                                                                                                                         
        msg = json.dumps(                                                                                                                                                           
            {                                                                                                                                                                       
                "jsonrpc": "2.0",                                                                                                                                                   
                "id": 0,                                                                                                                                                            
                "method": method,                                                                                                                                                   
                "params": params,                                                                                                                                                   
            }                                                                                                                                                                       
        )                                                                                                                                                                           
        sock.sendall(msg.encode() + b"\n")                                                                                                                                          
        this_id = self.next_id                                                                                                                                                      
        resp = self._readobj(sock)                                                                                                                                                  
                                                                                                                                                                                    
        self.logger.debug(f"Received response for {method} call: {resp}")                                                                                                           
        if "id" in resp and resp["id"] != this_id:                                                                                                                                  
            raise ValueError(                                                                                                                                                       
                "Malformed response, id is not {}: {}.".format(this_id, resp)                                                                                                       
            )                                                                                                                                                                       
        sock.close()                                                                                                                                                                
                                                                                                                                                                                    
        if not isinstance(resp, dict):                                                                                                                                              
            raise ValueError(                                                                                                                                                       
                f"Malformed response, response is not a dictionary: {resp}"                                                                                                         
            )                                                                                                                                                                       
        elif "error" in resp:                                                                                                                                                       
>           raise RpcError(method, params, resp["error"])                                                                                                                           
E           test_framework.utils.RpcError: RPC call failed: method: updatespend, params: ('cHNidP8BAH0CAAAAAdZ3tAhuLjlmIiMbOglxoMs9U7RhO44UVGT5YIwCJfkSAAAAAAD/////AkANAwAAAAAAFgAU9lUPboqXX6UK33mwhwwCN4RT+u40oIQBAAAAACIAIDXvbJZFritqW7xET1twUHgAP6xkIiN0F2WJYqH2KBRlAAAAAAABAStwsYcBAAAAACIAIDXvbJZFritqW7xET1twUHgAP6xkIiN0F2WJYqH2KBRlAQgCSDBFAiEAuZYvKjORaXD2S7xBZqI4
xbNnrcUA3iQQLta9GPM1VC0CIFhSaycEgPUypZctLC9VdncdjhyWAbP80ILAnT1JcB4/AUQhA7dGO9gcJ01qHlitjRlyEFmo6j1WefLxWHfB/4BDHen1rHNkdqkU/g/83EjSWTTSvK0AMjPiYu8Sx5KIrQPo/QCyaAAAAA==',), error: {'code': -32602, 'message': "Invalid params: Invalid 'feerate' parameter."}

(I fixed the "invalid 'feerate' parameter" typo in #15)

At what derivation should the GUI installer query the key from a signing device?

We need to query from the signing device some xpubs at a specific derivation index, to be used in the descriptor registered in minisafed. We'd like to use the same derivation path for all devices. Ledger only allows to sanely query the xpubs from paths that were standardized by BIPs which give an implicit meaning that the key will be used in a specific script (BIP-44 and friends if i'm remembering correctly).

However, i had figured that using a derivation that was already standardized previously could be a source of confusion for the user. We'd query the key for a path with an implicit meaning, and actually not use it in a corresponding Script type.

I now think this isn't actually an issue. There is nowhere the derivation path would be backed up and the user would recover from this. Even in the legacy recovery process, it was the other way around: select the script ("address") type and the software will know from what derivation index to derive keys from for the rescan. Furthermore, we already require the descriptor for recovery. The derivation path used in this descriptor cannot become a source of confusion for the user.

Another consideration that was brought up by Salvatore Ingala is about reusing public keys. It's possible we use the derivation path that other software would use let's say for P2WPKH. If someone uses the same signing device on the two software the same public keys (but not addresses obviously) would be used twice onchain.
I think it's not crucial to address, as we can't prevent it: the user could also just use our software twice. But if we can do something like use a different derivation index somewhere in the path (like the "account" thing), let's do it.

My suggestion is therefore:

  1. Pick any standard derivation path (for instance the one used for P2WPKH?), and use it for all signing devices
  2. Make a best effort at using a different "account" that other software would otherwise use, or even let the user pick one in the installer

qa: test Spend transaction RBF handling

#29 added support for detecting a Spend transaction confirmation. In so doing it checked if a Spend we checked had been replaced.

However, this isn't currently tested. We should have a functional test for this.

At fresh daemon startup, setup first bitcoind before database

During a fresh install the bitcoind should be setup before installing the sqlite database,
because if done after and the bitcoind port in the config is wrong for example, the database and the datadir are already created which force user to remove it by hand before installing again with the good port number

SQLite indexes

I haven't created indexes in the SQLite implementation of the database backend yet to avoid premature optimisation. Let's see if, and where, it'd make sense to have some.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.