From d9f3e925a43fee5bf51e0078fc14664bddcda480 Mon Sep 17 00:00:00 2001 From: Juan Pablo Civile Date: Tue, 13 May 2025 11:10:08 -0300 Subject: [PATCH] Update project structure and build process --- .github/workflows/pr.yml | 40 +- BUILD.md | 4 +- go.work | 4 + .../muun/libwallet => libwallet}/.gitignore | 0 LICENSE => libwallet/LICENSE | 0 .../muun/libwallet => libwallet}/README.md | 0 .../muun/libwallet => libwallet}/V1.go | 0 .../muun/libwallet => libwallet}/V2.go | 0 .../muun/libwallet => libwallet}/V3.go | 0 .../muun/libwallet => libwallet}/V4.go | 0 .../muun/libwallet => libwallet}/V5.go | 0 .../muun/libwallet => libwallet}/address.go | 0 libwallet/address_test.go | 321 +++ .../addresses/addresses.go | 0 libwallet/addresses/addresses_test.go | 30 + .../libwallet => libwallet}/addresses/v1.go | 0 .../libwallet => libwallet}/addresses/v2.go | 0 libwallet/addresses/v2_test.go | 57 + .../libwallet => libwallet}/addresses/v3.go | 0 libwallet/addresses/v3_test.go | 54 + .../libwallet => libwallet}/addresses/v4.go | 0 libwallet/addresses/v4_test.go | 52 + .../libwallet => libwallet}/addresses/v5.go | 0 libwallet/addresses/v5_test.go | 34 + .../libwallet => libwallet}/aescbc/aescbc.go | 0 libwallet/aescbc/aescbc_test.go | 36 + .../muun/libwallet => libwallet}/bip70.pb.go | 0 .../muun/libwallet => libwallet}/bip70.proto | 0 .../muun/libwallet => libwallet}/bridge.go | 0 .../btcsuitew/bech32m/bech32m.go | 0 libwallet/btcsuitew/bech32m/bech32m_test.go | 66 + .../btcsuitew/btcutilw/address.go | 0 .../btcsuitew/btcutilw/segwit.go | 0 .../btcsuitew/chainhashw/chainhashw.go | 0 .../btcsuitew/txscriptw/hashcache.go | 0 .../btcsuitew/txscriptw/script.go | 0 libwallet/btcsuitew/txscriptw/script_test.go | 139 + .../btcsuitew/txscriptw/standard.go | 0 .../libwallet => libwallet}/challenge_keys.go | 0 libwallet/challenge_keys_test.go | 160 ++ .../challenge_public_key.go | 0 .../libwallet => libwallet}/emergency_kit.go | 0 libwallet/emergency_kit_test.go | 15 + .../emergencykit/content.go | 0 .../emergencykit/css.go | 0 .../emergencykit/descriptors.go | 0 libwallet/emergencykit/descriptors_test.go | 34 + .../emergencykit/emergencykit.go | 0 libwallet/emergencykit/emergencykit_test.go | 105 + .../emergencykit/metadata.go | 0 libwallet/emergencykit/metadata_test.go | 121 + .../muun/libwallet => libwallet}/encodings.go | 0 libwallet/encodings_test.go | 46 + .../muun/libwallet => libwallet}/encrypt.go | 0 libwallet/encrypt_test.go | 252 ++ .../muun/libwallet => libwallet}/errors.go | 0 .../libwallet => libwallet}/errors/errors.go | 0 .../muun/libwallet => libwallet}/features.go | 0 libwallet/features_test.go | 211 ++ .../muun/libwallet => libwallet}/fees.go | 0 .../muun/libwallet => libwallet}/fees/fees.go | 0 libwallet/fees/fees_test.go | 363 +++ .../muun/libwallet => libwallet}/go.mod | 0 .../muun/libwallet => libwallet}/go.sum | 0 .../muun/libwallet => libwallet}/hashes.go | 0 .../libwallet => libwallet}/hdpath/hdpath.go | 0 libwallet/hdpath/hdpath_test.go | 82 + .../libwallet => libwallet}/hdprivatekey.go | 0 libwallet/hdprivatekey_test.go | 294 ++ .../libwallet => libwallet}/hdpublickey.go | 0 libwallet/hdpublickey_test.go | 36 + .../libwallet => libwallet}/incoming_swap.go | 0 libwallet/incoming_swap_test.go | 791 ++++++ .../muun/libwallet => libwallet}/init.go | 0 libwallet/init_test.go | 14 + .../muun/libwallet => libwallet}/invoice.go | 0 libwallet/invoice_test.go | 215 ++ .../muun/libwallet => libwallet}/invoices.go | 0 libwallet/invoices_test.go | 276 ++ .../keycrypt/keycrypt.go | 0 libwallet/keycrypt/keycrypt_test.go | 87 + .../libwallet => libwallet}/keycrypter.go | 0 libwallet/keycrypter_test.go | 54 + .../muun/libwallet => libwallet}/lnurl.go | 0 .../libwallet => libwallet}/lnurl/lnurl.go | 0 libwallet/lnurl/lnurl_test.go | 771 ++++++ .../libwallet => libwallet}/musig/README.md | 0 .../musig/adaptor_impl.h | 0 .../musig/assumptions.h | 0 .../musig/basic-config.h | 0 .../libwallet => libwallet}/musig/eccommit.h | 0 .../musig/eccommit_impl.h | 0 .../libwallet => libwallet}/musig/ecdsa.h | 0 .../musig/ecdsa_impl.h | 0 .../libwallet => libwallet}/musig/eckey.h | 0 .../musig/eckey_impl.h | 0 .../libwallet => libwallet}/musig/ecmult.h | 0 .../musig/ecmult_const.h | 0 .../musig/ecmult_const_impl.h | 0 .../musig/ecmult_gen.h | 0 .../musig/ecmult_gen_impl.h | 0 .../musig/ecmult_impl.h | 0 .../musig/ecmult_static_context.h | 0 .../musig/extrakeys_main_impl.h | 0 .../libwallet => libwallet}/musig/field.h | 0 .../musig/field_10x26.h | 0 .../musig/field_10x26_impl.h | 0 .../musig/field_5x52.h | 0 .../musig/field_5x52_asm_impl.h | 0 .../musig/field_5x52_impl.h | 0 .../musig/field_5x52_int128_impl.h | 0 .../musig/field_impl.h | 0 .../libwallet => libwallet}/musig/group.h | 0 .../musig/group_impl.h | 0 .../muun/libwallet => libwallet}/musig/hash.h | 0 .../libwallet => libwallet}/musig/hash_impl.h | 0 .../libwallet => libwallet}/musig/hsort.h | 0 .../musig/hsort_impl.h | 0 .../libwallet => libwallet}/musig/import.sh | 0 .../libwallet => libwallet}/musig/keyagg.h | 0 .../musig/keyagg_impl.h | 0 .../musig/libsecp256k1-config.h | 0 .../libwallet => libwallet}/musig/modinv32.h | 0 .../musig/modinv32_impl.h | 0 .../libwallet => libwallet}/musig/modinv64.h | 0 .../musig/modinv64_impl.h | 0 .../libwallet => libwallet}/musig/musig.go | 0 .../musig/musig_main_impl.h | 0 libwallet/musig/musig_test.go | 253 ++ .../libwallet => libwallet}/musig/scalar.h | 0 .../musig/scalar_4x64.h | 0 .../musig/scalar_4x64_impl.h | 0 .../musig/scalar_8x32.h | 0 .../musig/scalar_8x32_impl.h | 0 .../musig/scalar_impl.h | 0 .../musig/scalar_low.h | 0 .../musig/scalar_low_impl.h | 0 .../musig/schnorrsig_main_impl.h | 0 .../libwallet => libwallet}/musig/scratch.h | 0 .../musig/scratch_impl.h | 0 .../libwallet => libwallet}/musig/secp256k1.h | 0 .../libwallet => libwallet}/musig/secp256k1.k | 0 .../musig/secp256k1_extrakeys.h | 0 .../musig/secp256k1_musig.h | 0 .../musig/secp256k1_preallocated.h | 0 .../musig/secp256k1_schnorrsig.h | 0 .../libwallet => libwallet}/musig/selftest.h | 0 .../libwallet => libwallet}/musig/session.h | 0 .../musig/session_impl.h | 0 .../libwallet => libwallet}/musig/testrand.h | 0 .../musig/testrand_impl.h | 0 .../libwallet => libwallet}/musig/umbrella.c | 0 .../libwallet => libwallet}/musig/umbrella.h | 0 .../muun/libwallet => libwallet}/musig/util.h | 0 .../muun/libwallet => libwallet}/network.go | 0 libwallet/network_test.go | 75 + libwallet/newop/context.go | 36 + libwallet/newop/context_test.go | 65 + libwallet/newop/exchange_rates.go | 39 + libwallet/newop/exchange_rates_test.go | 27 + libwallet/newop/fee_state.go | 26 + libwallet/newop/fee_window.go | 35 + libwallet/newop/money.go | 86 + libwallet/newop/money_test.go | 67 + libwallet/newop/nts.go | 51 + libwallet/newop/state.go | 1106 ++++++++ libwallet/newop/state_test.go | 1398 ++++++++++ libwallet/newop/swaps.go | 105 + libwallet/operation/fee_window.go | 79 + libwallet/operation/fee_window_test.go | 172 ++ libwallet/operation/fees.go | 60 + libwallet/operation/fees_test.go | 301 +++ libwallet/operation/payment_analyzer.go | 562 ++++ libwallet/operation/payment_analyzer_test.go | 2408 +++++++++++++++++ .../partiallysignedtransaction.go | 0 libwallet/partiallysignedtransaction_test.go | 830 ++++++ .../muun/libwallet => libwallet}/publickey.go | 0 .../libwallet => libwallet}/recoverycode.go | 0 .../recoverycode/recoverycode.go | 0 libwallet/recoverycode/recoverycode_test.go | 86 + libwallet/recoverycode_test.go | 41 + .../muun/libwallet => libwallet}/ripemd160.go | 0 libwallet/ripemd160_test.go | 42 + .../muun/libwallet => libwallet}/scrypt.go | 0 .../muun/libwallet => libwallet}/segwit.go | 0 .../libwallet => libwallet}/sphinx/sphinx.go | 0 .../libwallet => libwallet}/submarineSwap.go | 0 .../submarineSwapV1.go | 0 .../submarineSwapV2.go | 0 .../libwallet => libwallet}/swaps/swaps.go | 0 .../muun/libwallet => libwallet}/swaps/v1.go | 0 libwallet/swaps/v1_test.go | 75 + .../muun/libwallet => libwallet}/swaps/v2.go | 0 libwallet/swaps/v2_test.go | 133 + .../walletdb/walletdb.go | 0 libwallet/walletdb/walletdb_test.go | 95 + .gitignore => recovery_tool/.gitignore | 0 Dockerfile => recovery_tool/Dockerfile | 33 +- .../muun/libwallet => recovery_tool}/LICENSE | 0 Makefile => recovery_tool/Makefile | 23 +- .../address_generator.go | 0 {cmd => recovery_tool/cmd}/survey/main.go | 0 .../electrum}/client.go | 0 {electrum => recovery_tool/electrum}/pool.go | 0 .../electrum}/servers.go | 0 go.mod => recovery_tool/go.mod | 2 + go.sum => recovery_tool/go.sum | 0 .../keys_generator.go | 0 main.go => recovery_tool/main.go | 0 {readme => recovery_tool/readme}/demo.gif | Bin {readme => recovery_tool/readme}/demo.yml | 0 recovery-tool => recovery_tool/recovery-tool | 0 .../recovery_tool.go | 0 {scanner => recovery_tool/scanner}/scanner.go | 0 {scanner => recovery_tool/scanner}/task.go | 0 {survey => recovery_tool/survey}/survey.go | 0 sweeper.go => recovery_tool/sweeper.go | 0 {utils => recovery_tool/utils}/logger.go | 0 version.go => recovery_tool/version.go | 0 vendor/github.com/btcsuite/btcutil/go.mod | 11 - vendor/github.com/btcsuite/btcutil/go.sum | 54 - .../github.com/btcsuite/btcutil/psbt/go.mod | 9 - .../github.com/btcsuite/btcutil/psbt/go.sum | 36 - .../btcsuite/btcwallet/wallet/txauthor/go.mod | 14 - .../btcsuite/btcwallet/wallet/txauthor/go.sum | 66 - .../btcsuite/btcwallet/wallet/txrules/go.mod | 8 - .../btcsuite/btcwallet/wallet/txrules/go.sum | 33 - .../btcsuite/btcwallet/wallet/txsizes/go.mod | 17 - .../btcsuite/btcwallet/wallet/txsizes/go.sum | 65 - .../btcsuite/btcwallet/walletdb/go.mod | 9 - .../btcsuite/btcwallet/walletdb/go.sum | 8 - .../btcsuite/btcwallet/wtxmgr/go.mod | 12 - .../btcsuite/btcwallet/wtxmgr/go.sum | 66 - vendor/github.com/decred/dcrd/lru/go.mod | 3 - vendor/github.com/fiatjaf/go-lnurl/go.mod | 8 - vendor/github.com/fiatjaf/go-lnurl/go.sum | 35 - vendor/github.com/gookit/color/go.mod | 9 - vendor/github.com/gookit/color/go.sum | 15 - vendor/github.com/hhrutter/lzw/go.mod | 3 - vendor/github.com/hhrutter/tiff/go.mod | 8 - vendor/github.com/hhrutter/tiff/go.sum | 6 - vendor/github.com/jinzhu/gorm/go.mod | 14 - vendor/github.com/jinzhu/gorm/go.sum | 33 - vendor/github.com/jinzhu/inflection/go.mod | 1 - vendor/github.com/lightninglabs/gozmq/go.mod | 3 - .../github.com/lightninglabs/neutrino/go.mod | 14 - .../github.com/lightninglabs/neutrino/go.sum | 94 - .../lightningnetwork/lightning-onion/go.mod | 13 - .../lightningnetwork/lightning-onion/go.sum | 42 - .../lightningnetwork/lnd/clock/go.mod | 3 - .../lightningnetwork/lnd/queue/go.mod | 7 - .../lightningnetwork/lnd/queue/go.sum | 0 .../lightningnetwork/lnd/ticker/go.mod | 1 - vendor/github.com/mattn/go-sqlite3/go.mod | 8 - vendor/github.com/mattn/go-sqlite3/go.sum | 13 - vendor/github.com/miekg/dns/go.mod | 11 - vendor/github.com/miekg/dns/go.sum | 39 - .../github.com/shopspring/decimal/.gitignore | 6 + .../github.com/shopspring/decimal/.travis.yml | 13 + .../shopspring/decimal/CHANGELOG.md | 19 + vendor/github.com/shopspring/decimal/LICENSE | 45 + .../github.com/shopspring/decimal/README.md | 130 + .../shopspring/decimal/decimal-go.go | 415 +++ .../github.com/shopspring/decimal/decimal.go | 1477 ++++++++++ .../github.com/shopspring/decimal/rounding.go | 119 + vendor/github.com/tidwall/gjson/go.mod | 8 - vendor/github.com/tidwall/gjson/go.sum | 4 - vendor/github.com/xo/terminfo/go.mod | 3 - vendor/github.com/xo/terminfo/go.sum | 0 vendor/go.etcd.io/bbolt/go.mod | 5 - vendor/go.etcd.io/bbolt/go.sum | 2 - vendor/golang.org/x/term/go.mod | 5 - vendor/golang.org/x/term/go.sum | 2 - vendor/gopkg.in/gormigrate.v1/go.mod | 19 - vendor/gopkg.in/gormigrate.v1/go.sum | 38 - vendor/gopkg.in/yaml.v2/go.mod | 5 - vendor/modules.txt | 70 +- 277 files changed, 15321 insertions(+), 930 deletions(-) create mode 100644 go.work rename {vendor/github.com/muun/libwallet => libwallet}/.gitignore (100%) mode change 100644 => 100755 rename LICENSE => libwallet/LICENSE (100%) rename {vendor/github.com/muun/libwallet => libwallet}/README.md (100%) rename {vendor/github.com/muun/libwallet => libwallet}/V1.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/V2.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/V3.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/V4.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/V5.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/address.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/address_test.go rename {vendor/github.com/muun/libwallet => libwallet}/addresses/addresses.go (100%) create mode 100644 libwallet/addresses/addresses_test.go rename {vendor/github.com/muun/libwallet => libwallet}/addresses/v1.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/addresses/v2.go (100%) create mode 100755 libwallet/addresses/v2_test.go rename {vendor/github.com/muun/libwallet => libwallet}/addresses/v3.go (100%) create mode 100755 libwallet/addresses/v3_test.go rename {vendor/github.com/muun/libwallet => libwallet}/addresses/v4.go (100%) create mode 100755 libwallet/addresses/v4_test.go rename {vendor/github.com/muun/libwallet => libwallet}/addresses/v5.go (100%) create mode 100644 libwallet/addresses/v5_test.go rename {vendor/github.com/muun/libwallet => libwallet}/aescbc/aescbc.go (100%) mode change 100644 => 100755 create mode 100644 libwallet/aescbc/aescbc_test.go rename {vendor/github.com/muun/libwallet => libwallet}/bip70.pb.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/bip70.proto (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/bridge.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/btcsuitew/bech32m/bech32m.go (100%) create mode 100644 libwallet/btcsuitew/bech32m/bech32m_test.go rename {vendor/github.com/muun/libwallet => libwallet}/btcsuitew/btcutilw/address.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/btcsuitew/btcutilw/segwit.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/btcsuitew/chainhashw/chainhashw.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/btcsuitew/txscriptw/hashcache.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/btcsuitew/txscriptw/script.go (100%) create mode 100644 libwallet/btcsuitew/txscriptw/script_test.go rename {vendor/github.com/muun/libwallet => libwallet}/btcsuitew/txscriptw/standard.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/challenge_keys.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/challenge_keys_test.go rename {vendor/github.com/muun/libwallet => libwallet}/challenge_public_key.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/emergency_kit.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/emergency_kit_test.go rename {vendor/github.com/muun/libwallet => libwallet}/emergencykit/content.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/emergencykit/css.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/emergencykit/descriptors.go (100%) create mode 100644 libwallet/emergencykit/descriptors_test.go rename {vendor/github.com/muun/libwallet => libwallet}/emergencykit/emergencykit.go (100%) create mode 100644 libwallet/emergencykit/emergencykit_test.go rename {vendor/github.com/muun/libwallet => libwallet}/emergencykit/metadata.go (100%) create mode 100644 libwallet/emergencykit/metadata_test.go rename {vendor/github.com/muun/libwallet => libwallet}/encodings.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/encodings_test.go rename {vendor/github.com/muun/libwallet => libwallet}/encrypt.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/encrypt_test.go rename {vendor/github.com/muun/libwallet => libwallet}/errors.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/errors/errors.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/features.go (100%) create mode 100644 libwallet/features_test.go rename {vendor/github.com/muun/libwallet => libwallet}/fees.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/fees/fees.go (100%) create mode 100644 libwallet/fees/fees_test.go rename {vendor/github.com/muun/libwallet => libwallet}/go.mod (100%) rename {vendor/github.com/muun/libwallet => libwallet}/go.sum (100%) rename {vendor/github.com/muun/libwallet => libwallet}/hashes.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/hdpath/hdpath.go (100%) create mode 100644 libwallet/hdpath/hdpath_test.go rename {vendor/github.com/muun/libwallet => libwallet}/hdprivatekey.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/hdprivatekey_test.go rename {vendor/github.com/muun/libwallet => libwallet}/hdpublickey.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/hdpublickey_test.go rename {vendor/github.com/muun/libwallet => libwallet}/incoming_swap.go (100%) create mode 100644 libwallet/incoming_swap_test.go rename {vendor/github.com/muun/libwallet => libwallet}/init.go (100%) create mode 100644 libwallet/init_test.go rename {vendor/github.com/muun/libwallet => libwallet}/invoice.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/invoice_test.go rename {vendor/github.com/muun/libwallet => libwallet}/invoices.go (100%) create mode 100644 libwallet/invoices_test.go rename {vendor/github.com/muun/libwallet => libwallet}/keycrypt/keycrypt.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/keycrypt/keycrypt_test.go rename {vendor/github.com/muun/libwallet => libwallet}/keycrypter.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/keycrypter_test.go rename {vendor/github.com/muun/libwallet => libwallet}/lnurl.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/lnurl/lnurl.go (100%) create mode 100644 libwallet/lnurl/lnurl_test.go rename {vendor/github.com/muun/libwallet => libwallet}/musig/README.md (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/adaptor_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/assumptions.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/basic-config.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/eccommit.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/eccommit_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecdsa.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecdsa_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/eckey.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/eckey_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecmult.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecmult_const.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecmult_const_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecmult_gen.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecmult_gen_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecmult_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/ecmult_static_context.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/extrakeys_main_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/field.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/field_10x26.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/field_10x26_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/field_5x52.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/field_5x52_asm_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/field_5x52_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/field_5x52_int128_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/field_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/group.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/group_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/hash.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/hash_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/hsort.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/hsort_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/import.sh (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/keyagg.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/keyagg_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/libsecp256k1-config.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/modinv32.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/modinv32_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/modinv64.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/modinv64_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/musig.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/musig_main_impl.h (100%) create mode 100644 libwallet/musig/musig_test.go rename {vendor/github.com/muun/libwallet => libwallet}/musig/scalar.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scalar_4x64.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scalar_4x64_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scalar_8x32.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scalar_8x32_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scalar_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scalar_low.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scalar_low_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/schnorrsig_main_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scratch.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/scratch_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/secp256k1.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/secp256k1.k (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/secp256k1_extrakeys.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/secp256k1_musig.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/secp256k1_preallocated.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/secp256k1_schnorrsig.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/selftest.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/session.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/session_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/testrand.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/testrand_impl.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/umbrella.c (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/umbrella.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/musig/util.h (100%) rename {vendor/github.com/muun/libwallet => libwallet}/network.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/network_test.go create mode 100644 libwallet/newop/context.go create mode 100644 libwallet/newop/context_test.go create mode 100644 libwallet/newop/exchange_rates.go create mode 100644 libwallet/newop/exchange_rates_test.go create mode 100644 libwallet/newop/fee_state.go create mode 100644 libwallet/newop/fee_window.go create mode 100644 libwallet/newop/money.go create mode 100644 libwallet/newop/money_test.go create mode 100644 libwallet/newop/nts.go create mode 100644 libwallet/newop/state.go create mode 100644 libwallet/newop/state_test.go create mode 100644 libwallet/newop/swaps.go create mode 100644 libwallet/operation/fee_window.go create mode 100644 libwallet/operation/fee_window_test.go create mode 100644 libwallet/operation/fees.go create mode 100644 libwallet/operation/fees_test.go create mode 100644 libwallet/operation/payment_analyzer.go create mode 100644 libwallet/operation/payment_analyzer_test.go rename {vendor/github.com/muun/libwallet => libwallet}/partiallysignedtransaction.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/partiallysignedtransaction_test.go rename {vendor/github.com/muun/libwallet => libwallet}/publickey.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/recoverycode.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/recoverycode/recoverycode.go (100%) create mode 100644 libwallet/recoverycode/recoverycode_test.go create mode 100644 libwallet/recoverycode_test.go rename {vendor/github.com/muun/libwallet => libwallet}/ripemd160.go (100%) mode change 100644 => 100755 create mode 100755 libwallet/ripemd160_test.go rename {vendor/github.com/muun/libwallet => libwallet}/scrypt.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/segwit.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/sphinx/sphinx.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/submarineSwap.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/submarineSwapV1.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/submarineSwapV2.go (100%) mode change 100644 => 100755 rename {vendor/github.com/muun/libwallet => libwallet}/swaps/swaps.go (100%) rename {vendor/github.com/muun/libwallet => libwallet}/swaps/v1.go (100%) create mode 100755 libwallet/swaps/v1_test.go rename {vendor/github.com/muun/libwallet => libwallet}/swaps/v2.go (100%) create mode 100644 libwallet/swaps/v2_test.go rename {vendor/github.com/muun/libwallet => libwallet}/walletdb/walletdb.go (100%) create mode 100644 libwallet/walletdb/walletdb_test.go rename .gitignore => recovery_tool/.gitignore (100%) rename Dockerfile => recovery_tool/Dockerfile (61%) rename {vendor/github.com/muun/libwallet => recovery_tool}/LICENSE (100%) rename Makefile => recovery_tool/Makefile (73%) rename address_generator.go => recovery_tool/address_generator.go (100%) rename {cmd => recovery_tool/cmd}/survey/main.go (100%) rename {electrum => recovery_tool/electrum}/client.go (100%) rename {electrum => recovery_tool/electrum}/pool.go (100%) rename {electrum => recovery_tool/electrum}/servers.go (100%) rename go.mod => recovery_tool/go.mod (85%) rename go.sum => recovery_tool/go.sum (100%) rename keys_generator.go => recovery_tool/keys_generator.go (100%) rename main.go => recovery_tool/main.go (100%) rename {readme => recovery_tool/readme}/demo.gif (100%) rename {readme => recovery_tool/readme}/demo.yml (100%) rename recovery-tool => recovery_tool/recovery-tool (100%) rename recovery_tool.go => recovery_tool/recovery_tool.go (100%) rename {scanner => recovery_tool/scanner}/scanner.go (100%) rename {scanner => recovery_tool/scanner}/task.go (100%) rename {survey => recovery_tool/survey}/survey.go (100%) rename sweeper.go => recovery_tool/sweeper.go (100%) rename {utils => recovery_tool/utils}/logger.go (100%) rename version.go => recovery_tool/version.go (100%) delete mode 100644 vendor/github.com/btcsuite/btcutil/go.mod delete mode 100644 vendor/github.com/btcsuite/btcutil/go.sum delete mode 100644 vendor/github.com/btcsuite/btcutil/psbt/go.mod delete mode 100644 vendor/github.com/btcsuite/btcutil/psbt/go.sum delete mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txauthor/go.mod delete mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txauthor/go.sum delete mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txrules/go.mod delete mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txrules/go.sum delete mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txsizes/go.mod delete mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txsizes/go.sum delete mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/go.mod delete mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/go.sum delete mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/go.mod delete mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/go.sum delete mode 100644 vendor/github.com/decred/dcrd/lru/go.mod delete mode 100644 vendor/github.com/fiatjaf/go-lnurl/go.mod delete mode 100644 vendor/github.com/fiatjaf/go-lnurl/go.sum delete mode 100644 vendor/github.com/gookit/color/go.mod delete mode 100644 vendor/github.com/gookit/color/go.sum delete mode 100644 vendor/github.com/hhrutter/lzw/go.mod delete mode 100644 vendor/github.com/hhrutter/tiff/go.mod delete mode 100644 vendor/github.com/hhrutter/tiff/go.sum delete mode 100644 vendor/github.com/jinzhu/gorm/go.mod delete mode 100644 vendor/github.com/jinzhu/gorm/go.sum delete mode 100644 vendor/github.com/jinzhu/inflection/go.mod delete mode 100644 vendor/github.com/lightninglabs/gozmq/go.mod delete mode 100644 vendor/github.com/lightninglabs/neutrino/go.mod delete mode 100644 vendor/github.com/lightninglabs/neutrino/go.sum delete mode 100644 vendor/github.com/lightningnetwork/lightning-onion/go.mod delete mode 100644 vendor/github.com/lightningnetwork/lightning-onion/go.sum delete mode 100644 vendor/github.com/lightningnetwork/lnd/clock/go.mod delete mode 100644 vendor/github.com/lightningnetwork/lnd/queue/go.mod delete mode 100644 vendor/github.com/lightningnetwork/lnd/queue/go.sum delete mode 100644 vendor/github.com/lightningnetwork/lnd/ticker/go.mod delete mode 100644 vendor/github.com/mattn/go-sqlite3/go.mod delete mode 100644 vendor/github.com/mattn/go-sqlite3/go.sum delete mode 100644 vendor/github.com/miekg/dns/go.mod delete mode 100644 vendor/github.com/miekg/dns/go.sum create mode 100644 vendor/github.com/shopspring/decimal/.gitignore create mode 100644 vendor/github.com/shopspring/decimal/.travis.yml create mode 100644 vendor/github.com/shopspring/decimal/CHANGELOG.md create mode 100644 vendor/github.com/shopspring/decimal/LICENSE create mode 100644 vendor/github.com/shopspring/decimal/README.md create mode 100644 vendor/github.com/shopspring/decimal/decimal-go.go create mode 100644 vendor/github.com/shopspring/decimal/decimal.go create mode 100644 vendor/github.com/shopspring/decimal/rounding.go delete mode 100644 vendor/github.com/tidwall/gjson/go.mod delete mode 100644 vendor/github.com/tidwall/gjson/go.sum delete mode 100644 vendor/github.com/xo/terminfo/go.mod delete mode 100644 vendor/github.com/xo/terminfo/go.sum delete mode 100644 vendor/go.etcd.io/bbolt/go.mod delete mode 100644 vendor/go.etcd.io/bbolt/go.sum delete mode 100644 vendor/golang.org/x/term/go.mod delete mode 100644 vendor/golang.org/x/term/go.sum delete mode 100644 vendor/gopkg.in/gormigrate.v1/go.mod delete mode 100644 vendor/gopkg.in/gormigrate.v1/go.sum delete mode 100644 vendor/gopkg.in/yaml.v2/go.mod diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7d70a1c..94a9a0d 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-12, macos-11] + os: [macos-13, macos-14, macos-15] arch: [amd64, arm64] runs-on: ${{ matrix.os }} @@ -19,32 +19,32 @@ jobs: out: recovery-tool-${{ matrix.os }}-${{ matrix.arch }} steps: - name: Checkout - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - name: Create output dir run: | mkdir -p bin - name: Set up Go - uses: actions/setup-go@268d8c0ca0432bb2cf416faae41297df9d262d7f + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 with: - go-version: 1.18.1 + go-version: '1.22.6' - name: Build run: | CGO_ENABLED=1 \ GOOS=darwin \ GOARCH=${{ matrix.arch }} \ - go build -mod=vendor -a -trimpath -o bin/${{ env.out }} + go build -mod=vendor -a -trimpath -o bin/${{ env.out }} ./recovery_tool - name: Upload binary - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with: name: ${{ env.out }} path: bin/${{ env.out }} build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -53,9 +53,15 @@ jobs: - os: "linux" arch: "386" out: "recovery-tool-linux32" + cc: "i686-linux-gnu-gcc-12" - os: "linux" arch: "amd64" out: "recovery-tool-linux64" + cc: "x86_64-linux-gnu-gcc-12" + - os: "linux" + arch: "arm64" + out: "recovery-tool-linuxaarch64" + cc: "aarch64-linux-gnu-gcc-12" - os: "windows" arch: "386" cc: "i686-w64-mingw32-gcc" @@ -67,21 +73,21 @@ jobs: steps: - name: Set up Docker Buildx - uses: docker/setup-buildx-action@dc7b9719a96d48369863986a06765841d7ea23f6 + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 with: buildkitd-flags: --debug - name: Checkout - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - name: Create output dir run: | mkdir -p bin - name: Build - uses: docker/build-push-action@c84f38281176d4c9cdb1626ffafcd6b3911b5d94 + uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 with: - file: Dockerfile + file: recovery_tool/Dockerfile context: . outputs: bin cache-from: type=gha @@ -93,21 +99,25 @@ jobs: out=${{ matrix.target.out }} - name: Upload binary - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with: name: ${{ matrix.target.out }} path: bin/${{ matrix.target.out }} release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: [build-mac, build] + permissions: + contents: write + steps: - name: Download artifacts - uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 if: startsWith(github.ref, 'refs/tags/') with: path: artifacts + pattern: recovery-tool-* - name: Compute SHA256 checksums run: | @@ -117,7 +127,7 @@ jobs: - name: Release - uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 + uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 if: startsWith(github.ref, 'refs/tags/') with: body_path: sha_sum_table diff --git a/BUILD.md b/BUILD.md index 7922096..2c04bea 100644 --- a/BUILD.md +++ b/BUILD.md @@ -7,7 +7,7 @@ To build the tool locally and run it, you must: ``` git clone https://github.com/muun/recovery - cd recovery + cd recovery/recovery_tool ``` 3. Run the tool with: @@ -40,4 +40,4 @@ We use Docker for these builds to ensure they are reproducible. For the 2.2 release, we had to disable reproducible builds for MacOS. The inclusion of C code for the musig implementation made building the tool inside a Linux container extremely difficult. We'll be moving the process to GitHub actions soon, which can be easily audited and can build natively on -MacOS. \ No newline at end of file +MacOS. diff --git a/go.work b/go.work new file mode 100644 index 0000000..818fbfc --- /dev/null +++ b/go.work @@ -0,0 +1,4 @@ +go 1.22.1 + +use ./libwallet +use ./recovery_tool diff --git a/vendor/github.com/muun/libwallet/.gitignore b/libwallet/.gitignore old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/.gitignore rename to libwallet/.gitignore diff --git a/LICENSE b/libwallet/LICENSE similarity index 100% rename from LICENSE rename to libwallet/LICENSE diff --git a/vendor/github.com/muun/libwallet/README.md b/libwallet/README.md similarity index 100% rename from vendor/github.com/muun/libwallet/README.md rename to libwallet/README.md diff --git a/vendor/github.com/muun/libwallet/V1.go b/libwallet/V1.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/V1.go rename to libwallet/V1.go diff --git a/vendor/github.com/muun/libwallet/V2.go b/libwallet/V2.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/V2.go rename to libwallet/V2.go diff --git a/vendor/github.com/muun/libwallet/V3.go b/libwallet/V3.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/V3.go rename to libwallet/V3.go diff --git a/vendor/github.com/muun/libwallet/V4.go b/libwallet/V4.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/V4.go rename to libwallet/V4.go diff --git a/vendor/github.com/muun/libwallet/V5.go b/libwallet/V5.go similarity index 100% rename from vendor/github.com/muun/libwallet/V5.go rename to libwallet/V5.go diff --git a/vendor/github.com/muun/libwallet/address.go b/libwallet/address.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/address.go rename to libwallet/address.go diff --git a/libwallet/address_test.go b/libwallet/address_test.go new file mode 100755 index 0000000..49de037 --- /dev/null +++ b/libwallet/address_test.go @@ -0,0 +1,321 @@ +package libwallet + +import ( + "encoding/hex" + "net/http" + "net/http/httptest" + "reflect" + "strings" + "testing" + + "google.golang.org/protobuf/proto" +) + +const ( + address = "2NDhvuRPCYXq4fB8SprminieZ2a1i3JFXyS" + amountURI = address + "?amount=1.2" + completeURI = amountURI + "&label=hola&message=mensaje%20con%20espacios" + uriWithSlashes = "bitcoin://" + amountURI + + invalidAddress = "2NDhvuRPCYXq4fB8SprminieZ2a1i3JFXya" + randomText = "fooo" + + bip70URL = "https://bitpay.com/i/KXCEAtJQssR9vG2BxdjFwx" + bip70NonRetroCompatAddress = bitcoinScheme + "?r=" + bip70URL + bip70RetroCompatAddress = bitcoinScheme + address + "?r=" + bip70URL +) + +func TestGetPaymentURI(t *testing.T) { + + const ( + invoice = "lnbcrt1pwtpd4xpp55meuklpslk5jtxytyh7u2q490c2xhm68dm3a94486zntsg7ad4vsdqqcqzys763w70h39ze44ngzhdt2mag84wlkefqkphuy7ssg4la5gt9vcpmqts00fnapf8frs928mc5ujfutzyu8apkezhrfvydx82l40w0fckqqmerzjc" + invoiceHashHex = "a6f3cb7c30fda925988b25fdc502a57e146bef476ee3d2d6a7d0a6b823dd6d59" + invoiceDestinationHex = "028cfad4e092191a41f081bedfbe5a6e8f441603c78bf9001b8fb62ac0858f20edasd" + ) + + invoiceDestination, _ := hex.DecodeString(invoiceDestinationHex) + invoicePaymentHash := make([]byte, 32) + hex.Decode(invoicePaymentHash[:], []byte(invoiceHashHex)) + + type args struct { + address string + network Network + } + + tests := []struct { + name string + args args + want *MuunPaymentURI + wantErr bool + }{ + + { + name: "validAddress", + args: args{ + address: address, + network: *Regtest(), + }, + want: &MuunPaymentURI{ + Address: address, + Uri: bitcoinScheme + address, + }, + }, + { + name: "amountValidAddress", + args: args{ + address: amountURI, + network: *Regtest(), + }, + want: &MuunPaymentURI{ + Address: address, + Amount: "1.2", + Uri: bitcoinScheme + amountURI, + }, + }, + { + name: "completeValidAddress", + args: args{ + address: completeURI, + network: *Regtest(), + }, + want: &MuunPaymentURI{ + Address: address, + Amount: "1.2", + Label: "hola", + Message: "mensaje con espacios", + Uri: bitcoinScheme + completeURI, + }, + }, + { + name: "invalidAddress", + args: args{ + address: invalidAddress, + network: *Regtest(), + }, + wantErr: true, + }, + { + name: "randomText", + args: args{ + address: randomText, + network: *Regtest(), + }, + wantErr: true, + }, + { + name: "BIP70NonRetroCompatAddress", + args: args{ + address: bip70NonRetroCompatAddress, + network: *Regtest(), + }, + want: &MuunPaymentURI{ + Uri: bip70NonRetroCompatAddress, + Bip70Url: bip70URL, + }, + }, + { + name: "BIP70RetroCompatAddress", + args: args{ + address: bip70RetroCompatAddress, + network: *Regtest(), + }, + want: &MuunPaymentURI{ + Address: address, + Uri: bip70RetroCompatAddress, + Bip70Url: bip70URL, + }, + }, + { + name: "URL like address", + args: args{ + address: uriWithSlashes, + network: *Regtest(), + }, + want: &MuunPaymentURI{ + Address: address, + Uri: uriWithSlashes, + Amount: "1.2", + }, + }, + { + name: "bad url", + args: args{ + address: ":foo#%--", + network: *Regtest(), + }, + wantErr: true, + }, + { + name: "bad query", + args: args{ + address: "bitcoin:123123?%&-=asd", + network: *Regtest(), + }, + wantErr: true, + }, + { + name: "network mismatch", + args: args{ + address: amountURI, + network: *Mainnet(), + }, + wantErr: true, + }, + { + name: "BIP with lightning", + args: args{ + address: "bitcoin:123123?lightning=" + invoice, + network: *network, + }, + want: &MuunPaymentURI{Invoice: &Invoice{ + RawInvoice: invoice, + FallbackAddress: nil, + Network: network, + MilliSat: "", + Destination: invoiceDestination, + PaymentHash: invoicePaymentHash, + Description: "", + }}, + }, + { + name: "ALL CAPS", + args: args{ + address: "BITCOIN:BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2", + network: *Mainnet(), + }, + want: &MuunPaymentURI{ + Address: strings.ToLower("BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2"), + Uri: "BITCOIN:BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2", + }, + }, + { + name: "MiXeD Case", + args: args{ + address: "BiTcOiN:BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2", + network: *Mainnet(), + }, + want: &MuunPaymentURI{ + Address: strings.ToLower("BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2"), + Uri: "BiTcOiN:BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetPaymentURI(tt.args.address, &tt.args.network) + if (err != nil) != tt.wantErr { + t.Errorf("GetPaymentURI() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != nil && got.Invoice != nil { + // expiry is relative to now, so ignore it + got.Invoice.Expiry = 0 + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetPaymentURI() = %+v, want %+v", got, tt.want) + } + }) + } +} + +func Test_normalizeAddress(t *testing.T) { + type args struct { + rawAddress string + targetScheme string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "normalAddress", + args: args{ + rawAddress: address, + targetScheme: bitcoinScheme, + }, + want: bitcoinScheme + address, + }, + { + name: "bitcoinAddress", + args: args{ + rawAddress: bitcoinScheme + address, + targetScheme: bitcoinScheme, + }, + want: bitcoinScheme + address, + }, + { + name: "muunAddress", + args: args{ + rawAddress: muunScheme + address, + targetScheme: bitcoinScheme, + }, + want: bitcoinScheme + address, + }, + { + name: "muun to lightning", + args: args{ + rawAddress: muunScheme + address, + targetScheme: lightningScheme, + }, + want: lightningScheme + address, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got, _ := buildUriFromString(tt.args.rawAddress, tt.args.targetScheme); got != tt.want { + t.Errorf("buildUriFromString() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDoPaymentRequestCall(t *testing.T) { + mux := http.NewServeMux() + mux.HandleFunc("/payment-request/", func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Accept") != "application/bitcoin-paymentrequest" { + t.Fatal("expected Accept header to be application/bitcoin-paymentrequest") + } + + script, _ := hex.DecodeString("76a9146efcf883b4b6f9997be9a0600f6c095fe2bd2d9288ac") + + serializedPaymentDetails, _ := proto.Marshal(&PaymentDetails{ + Network: "test", + Outputs: []*Output{ + { + Script: script, + Amount: 2500, + }, + }, + Time: 100000, + Expires: 102000, + Memo: "Hello World", + PaymentUrl: "http://localhost:8000/pay", + MerchantData: []byte(""), + }) + payReq, _ := proto.Marshal(&PaymentRequest{SerializedPaymentDetails: serializedPaymentDetails}) + + w.Write(payReq) + }) + server := httptest.NewServer(mux) + defer server.Close() + + url := server.URL + "/payment-request/" + paymentURI, err := DoPaymentRequestCall(url, Testnet()) + if err != nil { + t.Fatal(err) + } + + expected := &MuunPaymentURI{ + Address: "mqdofsXHpePPGBFXuwwypAqCcXi48Xhb2f", + Message: "Hello World", + Amount: "0.000025", + Bip70Url: url, + CreationTime: "100000", + ExpiresTime: "102000", + } + if !reflect.DeepEqual(paymentURI, expected) { + t.Fatalf("decoded URI struct does not match expected, %+v != %+v", paymentURI, expected) + } +} diff --git a/vendor/github.com/muun/libwallet/addresses/addresses.go b/libwallet/addresses/addresses.go similarity index 100% rename from vendor/github.com/muun/libwallet/addresses/addresses.go rename to libwallet/addresses/addresses.go diff --git a/libwallet/addresses/addresses_test.go b/libwallet/addresses/addresses_test.go new file mode 100644 index 0000000..f045050 --- /dev/null +++ b/libwallet/addresses/addresses_test.go @@ -0,0 +1,30 @@ +package addresses + +import ( + "github.com/btcsuite/btcutil/hdkeychain" + "github.com/muun/libwallet/hdpath" +) + +func parseKey(s string) *hdkeychain.ExtendedKey { + key, err := hdkeychain.NewKeyFromString(s) + if err != nil { + panic(err) + } + return key +} + +func derive(key *hdkeychain.ExtendedKey, fromPath, toPath string) *hdkeychain.ExtendedKey { + indexes := hdpath.MustParse(toPath).IndexesFrom(hdpath.MustParse(fromPath)) + for _, index := range indexes { + var err error + var modifier uint32 + if index.Hardened { + modifier = hdkeychain.HardenedKeyStart + } + key, err = key.Child(index.Index | modifier) + if err != nil { + panic(err) + } + } + return key +} diff --git a/vendor/github.com/muun/libwallet/addresses/v1.go b/libwallet/addresses/v1.go similarity index 100% rename from vendor/github.com/muun/libwallet/addresses/v1.go rename to libwallet/addresses/v1.go diff --git a/vendor/github.com/muun/libwallet/addresses/v2.go b/libwallet/addresses/v2.go similarity index 100% rename from vendor/github.com/muun/libwallet/addresses/v2.go rename to libwallet/addresses/v2.go diff --git a/libwallet/addresses/v2_test.go b/libwallet/addresses/v2_test.go new file mode 100755 index 0000000..3088884 --- /dev/null +++ b/libwallet/addresses/v2_test.go @@ -0,0 +1,57 @@ +package addresses + +import ( + "reflect" + "testing" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcutil/hdkeychain" +) + +var network = &chaincfg.RegressionNetParams + +func TestCreateAddressV2(t *testing.T) { + + const ( + addressPath = "m/schema:1'/recovery:1'/external:1/0" + originAddress = "2NDeWrsJEwvxwVnvtWzPjhDC5B2LYkFuX2s" + + encodedMuunKey = "tpubDBYMnFoxYLdMBZThTk4uARTe4kGPeEYWdKcaEzaUxt1cesetnxtTqmAxVkzDRou51emWytommyLWcF91SdF5KecA6Ja8oHK1FF7d5U2hMxX" + encodedUserKey = "tprv8dfM4H5fYJirMai5Er3LguicgUAyxmcSQbFub5ens16amX1e1HAFiW4SXnFVw9nu9FedFQqTPGTTjPEmgfvvXMKww3UcRpFbbC4DFjbCcTb" + basePath = "m/schema:1'/recovery:1'" + v2EncodedScript = "5221029fa5af7a34c142c1ce348b360abeb7de01df25b1d50129e58a67a6b846c9303b21025714f6b3670d4a38f5e2d6e8f239c9fc072543ce33dca54fcb4f4886a5cb87a652ae" + ) + + baseMuunKey := parseKey(encodedMuunKey) + muunKey := derive(baseMuunKey, basePath, addressPath) + + baseUserKey := parseKey(encodedUserKey) + userKey := derive(baseUserKey, basePath, addressPath) + + type args struct { + userKey *hdkeychain.ExtendedKey + muunKey *hdkeychain.ExtendedKey + } + tests := []struct { + name string + args args + want *WalletAddress + wantErr bool + }{ + {name: "gen address", + args: args{userKey: userKey, muunKey: muunKey}, + want: &WalletAddress{address: originAddress, derivationPath: addressPath, version: V2}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CreateAddressV2(tt.args.userKey, tt.args.muunKey, addressPath, network) + if (err != nil) != tt.wantErr { + t.Errorf("CreateAddressV2() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("CreateAddressV2() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/vendor/github.com/muun/libwallet/addresses/v3.go b/libwallet/addresses/v3.go similarity index 100% rename from vendor/github.com/muun/libwallet/addresses/v3.go rename to libwallet/addresses/v3.go diff --git a/libwallet/addresses/v3_test.go b/libwallet/addresses/v3_test.go new file mode 100755 index 0000000..5d5bd8b --- /dev/null +++ b/libwallet/addresses/v3_test.go @@ -0,0 +1,54 @@ +package addresses + +import ( + "reflect" + "testing" + + "github.com/btcsuite/btcutil/hdkeychain" +) + +func TestCreateAddressV3(t *testing.T) { + + const ( + addressPath = "m/schema:1'/recovery:1'/external:1/0" + + v3Address = "2MswEXmCLaHQq6pUTtnUVF8wVArfYSqUec5" + basePK = "tpubDAN21T1DFREQQS4FvpUktKRBzXXsj5ddenAa5u198hLXvErFFR4Lj8bt8xMG3xnZr6u8mx1vrFW9RwCDXQwQuYRCLq1j9Nr2VJUrENzteQH" + baseCosigningPK = "tpubDAsVhzq6otpasovieofhiaY38bSFGyJaBGvrJjBv9whhSnftUXfMTMVrq4BbTXT5A9b78CqqbPuM2j1ZGWdiggd7JHUTZAHh8GXDTt4Pkj9" + basePath = "m/schema:1'/recovery:1'" + v3EncodedScript = "0020e1fbfbd395aff8b4087fee3e4488815ef659b559b3cd0d6800b5a591efd99f38" + ) + + baseMuunKey := parseKey(baseCosigningPK) + muunKey := derive(baseMuunKey, basePath, addressPath) + + baseUserKey := parseKey(basePK) + userKey := derive(baseUserKey, basePath, addressPath) + + type args struct { + userKey *hdkeychain.ExtendedKey + muunKey *hdkeychain.ExtendedKey + } + tests := []struct { + name string + args args + want *WalletAddress + wantErr bool + }{ + {name: "gen address", + args: args{userKey: userKey, muunKey: muunKey}, + want: &WalletAddress{address: v3Address, derivationPath: addressPath, version: V3}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CreateAddressV3(tt.args.userKey, tt.args.muunKey, addressPath, network) + if (err != nil) != tt.wantErr { + t.Errorf("CreateAddressV3() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("CreateAddressV3() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/vendor/github.com/muun/libwallet/addresses/v4.go b/libwallet/addresses/v4.go similarity index 100% rename from vendor/github.com/muun/libwallet/addresses/v4.go rename to libwallet/addresses/v4.go diff --git a/libwallet/addresses/v4_test.go b/libwallet/addresses/v4_test.go new file mode 100755 index 0000000..b0293e3 --- /dev/null +++ b/libwallet/addresses/v4_test.go @@ -0,0 +1,52 @@ +package addresses + +import ( + "reflect" + "testing" + + "github.com/btcsuite/btcutil/hdkeychain" +) + +func TestCreateAddressV4(t *testing.T) { + const ( + addressPath = "m/schema:1'/recovery:1'/external:1/2" + + v4Address = "bcrt1qrs3vk4dzv70syck2qdz3g06tgckq4pftenuk5p77st9glnskpvtqe2tvvk" + basePK = "tpubDBf5wCeqg3KrLJiXaveDzD5JtFJ1ss9NVvFMx4RYS73SjwPEEawcAQ7V1B5DGM4gunWDeYNrnkc49sUaf7mS1wUKiJJQD6WEctExUQoLvrg" + baseCosigningPK = "tpubDB22PFkUaHoB7sgxh7exCivV5rAevVSzbB8WkFCCdbHq39r8xnYexiot4NGbi8PM6E1ySVeaHsoDeMYb6EMndpFrzVmuX8iQNExzwNpU61B" + basePath = "m/schema:1'/recovery:1'" + ) + + baseMuunKey := parseKey(baseCosigningPK) + muunKey := derive(baseMuunKey, basePath, addressPath) + + baseUserKey := parseKey(basePK) + userKey := derive(baseUserKey, basePath, addressPath) + + type args struct { + userKey *hdkeychain.ExtendedKey + muunKey *hdkeychain.ExtendedKey + } + tests := []struct { + name string + args args + want *WalletAddress + wantErr bool + }{ + {name: "gen bech32 address", + args: args{userKey: userKey, muunKey: muunKey}, + want: &WalletAddress{address: v4Address, derivationPath: addressPath, version: V4}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CreateAddressV4(tt.args.userKey, tt.args.muunKey, addressPath, network) + if (err != nil) != tt.wantErr { + t.Errorf("CreateAddressV4() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("CreateAddressV4() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/vendor/github.com/muun/libwallet/addresses/v5.go b/libwallet/addresses/v5.go similarity index 100% rename from vendor/github.com/muun/libwallet/addresses/v5.go rename to libwallet/addresses/v5.go diff --git a/libwallet/addresses/v5_test.go b/libwallet/addresses/v5_test.go new file mode 100644 index 0000000..0aefcb1 --- /dev/null +++ b/libwallet/addresses/v5_test.go @@ -0,0 +1,34 @@ +package addresses + +import ( + "reflect" + "testing" +) + +func TestCreateAddressV5(t *testing.T) { + const ( + addressPath = "m/schema:1'/recovery:1'/external:1/17" + + v5Address = "bcrt1pvqngr85tm8hmsv2hjyrejlpsy7u65f7vke8mmrxnyuj3aj3xsapqvh8yrf" + basePK = "tpubDBf5wCeqg3KrLJiXaveDzD5JtFJ1ss9NVvFMx4RYS73SjwPEEawcAQ7V1B5DGM4gunWDeYNrnkc49sUaf7mS1wUKiJJQD6WEctExUQoLvrg" + baseCosigningPK = "tpubDB22PFkUaHoB7sgxh7exCivV5rAevVSzbB8WkFCCdbHq39r8xnYexiot4NGbi8PM6E1ySVeaHsoDeMYb6EMndpFrzVmuX8iQNExzwNpU61B" + basePath = "m/schema:1'/recovery:1'" + ) + + baseMuunKey := parseKey(baseCosigningPK) + muunKey := derive(baseMuunKey, basePath, addressPath) + + baseUserKey := parseKey(basePK) + userKey := derive(baseUserKey, basePath, addressPath) + + expectedAddr := &WalletAddress{address: v5Address, derivationPath: addressPath, version: V5} + + actualAddr, err := CreateAddressV5(userKey, muunKey, addressPath, network) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(actualAddr, expectedAddr) { + t.Errorf("Created v5 address %v, expected %v", actualAddr, expectedAddr) + } +} diff --git a/vendor/github.com/muun/libwallet/aescbc/aescbc.go b/libwallet/aescbc/aescbc.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/aescbc/aescbc.go rename to libwallet/aescbc/aescbc.go diff --git a/libwallet/aescbc/aescbc_test.go b/libwallet/aescbc/aescbc_test.go new file mode 100644 index 0000000..5c2c5f5 --- /dev/null +++ b/libwallet/aescbc/aescbc_test.go @@ -0,0 +1,36 @@ +package aescbc + +import ( + "bytes" + "crypto/rand" + "testing" +) + +func TestEncryptionWithPkcs7Padding(t *testing.T) { + key := randomBytes(32) + iv := randomBytes(16) + + plaintext := []byte("foobar") + ciphertext, err := EncryptPkcs7(key, iv, plaintext) + if err != nil { + t.Fatal(err) + } + + decrypted, err := DecryptPkcs7(key, iv, ciphertext) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(decrypted, plaintext) { + t.Fatalf("expected decrypted text to match plaintext") + } +} + +func randomBytes(count int) []byte { + buf := make([]byte, count) + _, err := rand.Read(buf) + if err != nil { + panic("couldn't read random bytes") + } + + return buf +} diff --git a/vendor/github.com/muun/libwallet/bip70.pb.go b/libwallet/bip70.pb.go similarity index 100% rename from vendor/github.com/muun/libwallet/bip70.pb.go rename to libwallet/bip70.pb.go diff --git a/vendor/github.com/muun/libwallet/bip70.proto b/libwallet/bip70.proto old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/bip70.proto rename to libwallet/bip70.proto diff --git a/vendor/github.com/muun/libwallet/bridge.go b/libwallet/bridge.go similarity index 100% rename from vendor/github.com/muun/libwallet/bridge.go rename to libwallet/bridge.go diff --git a/vendor/github.com/muun/libwallet/btcsuitew/bech32m/bech32m.go b/libwallet/btcsuitew/bech32m/bech32m.go similarity index 100% rename from vendor/github.com/muun/libwallet/btcsuitew/bech32m/bech32m.go rename to libwallet/btcsuitew/bech32m/bech32m.go diff --git a/libwallet/btcsuitew/bech32m/bech32m_test.go b/libwallet/btcsuitew/bech32m/bech32m_test.go new file mode 100644 index 0000000..d363551 --- /dev/null +++ b/libwallet/btcsuitew/bech32m/bech32m_test.go @@ -0,0 +1,66 @@ +package bech32m + +import ( + "testing" +) + +// The following test vectors were taken from BIP-350. +// We only test for valid/invalid (and not decoded data), since only the checksum changed. + +var validBech32m = []string{ + "A1LQFN3A", + "a1lqfn3a", + "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6", + "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx", + "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8", + "split1checkupstagehandshakeupstreamerranterredcaperredlc445v", + "?1v759aa", +} + +var invalidBech32m = []string{ + "\x201xj0phk", // HRP character out of range + "\x7f1g6xzxy", // HRP character out of range + "\x801vctc34", // HRP character out of range + + "an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11d6pts4", // Overall max length exceeded + + "qyrz8wqd2c9m", // No separator + "1qyrz8wqd2c9m", // Empty HRP + "16plkw9", // Empty HRP + "1p2gdwpf", // Empty HRP + + "y1b0jsk6g", // Invalid data character + "lt1igcx5c0", // Invalid data character + + "in1muywd", // Too short checksum + "mm1crxm3i", // Invalid character in checksum + "au1s5cgom", // Invalid character in checksum + "M1VUXWEZ", // checksum calculated with uppercase form of HRP +} + +func TestDecodeValid(t *testing.T) { + for _, validBech := range validBech32m { + _, _, err := Decode(validBech) + if err != nil { + t.Fatalf("failed to decode valid bech32m %s: %v", validBech, err) + } + } +} + +func TestDecodeInvalid(t *testing.T) { + for _, invalidBech := range invalidBech32m { + _, _, err := Decode(invalidBech) + if err == nil { + t.Fatalf("success decoding invalid string %s", invalidBech) + } + } +} + +func TestNotCompat(t *testing.T) { + someBech32 := "bcrt1q77ayq0ldrwr3vg0rl0ss8u0ne0hajllz4h7yrqm8ldyy2v0860vs9xzmr4" + + _, _, err := Decode(someBech32) + if err == nil { + t.Fatalf("success decoding bech32 with bech32m %s (expected checksum failure)", someBech32) + } +} diff --git a/vendor/github.com/muun/libwallet/btcsuitew/btcutilw/address.go b/libwallet/btcsuitew/btcutilw/address.go similarity index 100% rename from vendor/github.com/muun/libwallet/btcsuitew/btcutilw/address.go rename to libwallet/btcsuitew/btcutilw/address.go diff --git a/vendor/github.com/muun/libwallet/btcsuitew/btcutilw/segwit.go b/libwallet/btcsuitew/btcutilw/segwit.go similarity index 100% rename from vendor/github.com/muun/libwallet/btcsuitew/btcutilw/segwit.go rename to libwallet/btcsuitew/btcutilw/segwit.go diff --git a/vendor/github.com/muun/libwallet/btcsuitew/chainhashw/chainhashw.go b/libwallet/btcsuitew/chainhashw/chainhashw.go similarity index 100% rename from vendor/github.com/muun/libwallet/btcsuitew/chainhashw/chainhashw.go rename to libwallet/btcsuitew/chainhashw/chainhashw.go diff --git a/vendor/github.com/muun/libwallet/btcsuitew/txscriptw/hashcache.go b/libwallet/btcsuitew/txscriptw/hashcache.go similarity index 100% rename from vendor/github.com/muun/libwallet/btcsuitew/txscriptw/hashcache.go rename to libwallet/btcsuitew/txscriptw/hashcache.go diff --git a/vendor/github.com/muun/libwallet/btcsuitew/txscriptw/script.go b/libwallet/btcsuitew/txscriptw/script.go similarity index 100% rename from vendor/github.com/muun/libwallet/btcsuitew/txscriptw/script.go rename to libwallet/btcsuitew/txscriptw/script.go diff --git a/libwallet/btcsuitew/txscriptw/script_test.go b/libwallet/btcsuitew/txscriptw/script_test.go new file mode 100644 index 0000000..7a0fba1 --- /dev/null +++ b/libwallet/btcsuitew/txscriptw/script_test.go @@ -0,0 +1,139 @@ +package txscriptw + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "testing" + _ "unsafe" + + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +// These test cases were taken from rust-bitcoin, which in turn took them from Bitcoin Core: +var sigHashTestCases = []sigHashTestCase{ + { + tx: "020000000164eb050a5e3da0c2a65e4786f26d753b7bc69691fabccafb11f7acef36641f1846010000003101b2b404392a22000000000017a9147f2bde86fe78bf68a0544a4f290e12f0b7e0a08c87580200000000000017a91425d11723074ecfb96a0a83c3956bfaf362ae0c908758020000000000001600147e20f938993641de67bb0cdd71682aa34c4d29ad5802000000000000160014c64984dc8761acfa99418bd6bedc79b9287d652d72000000", + prevOuts: "01365724000000000023542156b39dab4f8f3508e0432cfb41fab110170acaa2d4c42539cb90a4dc7c093bc500", + index: 0, + hashType: txscript.SigHashOld, + // expectSigHash: "33ca0ebfb4a945eeee9569fc0f5040221275f88690b7f8592ada88ce3bdf6703", + expectError: true, + }, + { + tx: "0200000002fff49be59befe7566050737910f6ccdc5e749c7f8860ddc140386463d88c5ad0f3000000002cf68eb4a3d67f9d4c079249f7e4f27b8854815cb1ed13842d4fbf395f9e217fd605ee24090100000065235d9203f458520000000000160014b6d48333bb13b4c644e57c43a9a26df3a44b785e58020000000000001976a914eea9461a9e1e3f765d3af3e726162e0229fe3eb688ac58020000000000001976a9143a8869c9f2b5ea1d4ff3aeeb6a8fb2fffb1ad5fe88ac0ad7125c", + prevOuts: "02591f220000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece48fb310000000000225120f25ad35583ea31998d968871d7de1abd2a52f6fe4178b54ea158274806ff4ece", + index: 1, + hashType: txscript.SigHashAll, + expectSigHash: "626ab955d58c9a8a600a0c580549d06dc7da4e802eb2a531f62a588e430967a8", + expectError: false, + }, + { + tx: "0200000001350005f65aa830ced2079df348e2d8c2bdb4f10e2dde6a161d8a07b40d1ad87dae000000001611d0d603d9dc0e000000000017a914459b6d7d6bbb4d8837b4bf7e9a4556f952da2f5c8758020000000000001976a9141dd70e1299ffc2d5b51f6f87de9dfe9398c33cbb88ac58020000000000001976a9141dd70e1299ffc2d5b51f6f87de9dfe9398c33cbb88aca71c1f4f", + prevOuts: "01c4811000000000002251201bf9297d0a2968ae6693aadd0fa514717afefd218087a239afb7418e2d22e65c", + index: 0, + hashType: txscript.SigHashAll | txscript.SigHashAnyOneCanPay, + // expectSigHash: "dfa9437f9c9a1d1f9af271f79f2f5482f287cdb0d2e03fa92c8a9b216cc6061c", + expectError: true, + }, + { + tx: "020000000185bed1a6da2bffbd60ec681a1bfb71c5111d6395b99b3f8b2bf90167111bcb18f5010000007c83ace802ded24a00000000001600142c4698f9f7a773866879755aa78c516fb332af8e5802000000000000160014d38639dfbac4259323b98a472405db0c461b31fa61073747", + prevOuts: "0144c84d0000000000225120e3f2107989c88e67296ab2faca930efa2e3a5bd3ff0904835a11c9e807458621", + index: 0, + hashType: txscript.SigHashNone, + // expectSigHash: "3129de36a5d05fff97ffca31eb75fcccbbbc27b3147a7a36a9e4b45d8b625067", + expectError: true, + }, + { + tx: "eb93dbb901028c8515589dac980b6e7f8e4088b77ed866ca0d6d210a7218b6fd0f6b22dd6d7300000000eb4740a9047efc0e0000000000160014913da2128d8fcf292b3691db0e187414aa1783825802000000000000160014913da2128d8fcf292b3691db0e187414aa178382580200000000000017a9143dd27f01c6f7ef9bb9159937b17f17065ed01a0c875802000000000000160014d7630e19df70ada9905ede1722b800c0005f246641000000", + prevOuts: "013fed110000000000225120eb536ae8c33580290630fc495046e998086a64f8f33b93b07967d9029b265c55", + index: 0, + hashType: txscript.SigHashNone | txscript.SigHashAnyOneCanPay, + // expectSigHash: "2441e8b0e063a2083ee790f14f2045022f07258ddde5ee01de543c9e789d80ae", + expectError: true, + }, + { + tx: "02000000017836b409a5fed32211407e44b971591f2032053f14701fb5b3a30c0ff382f2cc9c0100000061ac55f60288fb5600000000001976a9144ea02f6f182b082fb6ce47e36bbde390b6a41b5088ac58020000000000001976a9144ea02f6f182b082fb6ce47e36bbde390b6a41b5088ace4000000", + prevOuts: "01efa558000000000022512007071ea3dc7e331b0687d0193d1e6d6ed10e645ef36f10ef8831d5e522ac9e80", + index: 0, + hashType: txscript.SigHashSingle, + // expectSigHash: "30239345177cadd0e3ea413d49803580abb6cb27971b481b7788a78d35117a88", + expectError: true, + }, + { + tx: "0100000001aa6deae89d5e0aaca58714fc76ef6f3c8284224888089232d4e663843ed3ab3eae010000008b6657a60450cb4c0000000000160014a3d42b5413ef0c0701c4702f3cd7d4df222c147058020000000000001976a91430b4ed8723a4ee8992aa2c8814cfe5c3ad0ab9d988ac5802000000000000160014365b1166a6ed0a5e8e9dff17a6d00bbb43454bc758020000000000001976a914bc98c51a84fe7fad5dc380eb8b39586eff47241688ac4f313247", + prevOuts: "0107af4e00000000002251202c36d243dfc06cb56a248e62df27ecba7417307511a81ae61aa41c597a929c69", + index: 0, + hashType: txscript.SigHashSingle | txscript.SigHashAnyOneCanPay, + // expectSigHash: "bf9c83f26c6dd16449e4921f813f551c4218e86f2ec906ca8611175b41b566df", + expectError: true, + }, +} + +func TestTaprootSigHash(t *testing.T) { + for i, testCase := range sigHashTestCases { + tx := testCase.ParseTx() + prevOuts := testCase.ParsePrevOuts() + + sigHashes := NewTaprootSigHashes(tx, prevOuts) + + sigHash, err := CalcTaprootSigHash(tx, sigHashes, testCase.index, testCase.hashType) + if (err != nil) != testCase.expectError { + t.Fatalf("case %d: expect error %v, actual error: %v", i, testCase.expectError, err) + } + + if !bytes.Equal(sigHash, testCase.ParseExpectedSigHash()) { + t.Fatalf("case %d: sigHash does not match expected value", i) + } + } +} + +type sigHashTestCase struct { + tx string + prevOuts string + index int + hashType txscript.SigHashType + expectSigHash string + expectError bool +} + +func (c *sigHashTestCase) ParseTx() *wire.MsgTx { + b, _ := hex.DecodeString(c.tx) + r := bytes.NewReader(b) + + tx := wire.NewMsgTx(0) + tx.BtcDecode(r, 0, wire.WitnessEncoding) + + return tx +} + +func (c *sigHashTestCase) ParsePrevOuts() []*wire.TxOut { + b, _ := hex.DecodeString(c.prevOuts) + r := bytes.NewReader(b) + + prevOutCount, _ := wire.ReadVarInt(r, 0) + prevOuts := make([]*wire.TxOut, prevOutCount) + + for i := 0; i < int(prevOutCount); i++ { + valueLe := make([]byte, 8) + r.Read(valueLe[:]) + value := binary.LittleEndian.Uint64(valueLe) + + pkScriptSize, _ := wire.ReadVarInt(r, 0) + pkScript := make([]byte, pkScriptSize) + r.Read(pkScript) + + prevOuts[i] = &wire.TxOut{ + Value: int64(value), + PkScript: pkScript, + } + } + + return prevOuts +} + +func (c *sigHashTestCase) ParseExpectedSigHash() []byte { + b, _ := hex.DecodeString(c.expectSigHash) + return b +} diff --git a/vendor/github.com/muun/libwallet/btcsuitew/txscriptw/standard.go b/libwallet/btcsuitew/txscriptw/standard.go similarity index 100% rename from vendor/github.com/muun/libwallet/btcsuitew/txscriptw/standard.go rename to libwallet/btcsuitew/txscriptw/standard.go diff --git a/vendor/github.com/muun/libwallet/challenge_keys.go b/libwallet/challenge_keys.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/challenge_keys.go rename to libwallet/challenge_keys.go diff --git a/libwallet/challenge_keys_test.go b/libwallet/challenge_keys_test.go new file mode 100755 index 0000000..aa4fb7c --- /dev/null +++ b/libwallet/challenge_keys_test.go @@ -0,0 +1,160 @@ +package libwallet + +import ( + "reflect" + "testing" + + "github.com/btcsuite/btcutil/base58" +) + +func TestNewChallengePrivateKey(t *testing.T) { + type args struct { + input []byte + salt []byte + } + tests := []struct { + name string + args args + want *ChallengePrivateKey + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewChallengePrivateKey(tt.args.input, tt.args.salt); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewChallengePrivateKey() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestChallengeKeySignSha(t *testing.T) { + input := randomBytes(32) + salt := randomBytes(32) + challengePrivKey := NewChallengePrivateKey(input, salt) + + payload := []byte("foobar") + _, err := challengePrivKey.SignSha(payload) + if err != nil { + t.Fatal(err) + } + // TODO(federicobond): assert that signature verifies +} + +func TestChallengeKeyCrypto(t *testing.T) { + + const birthday = 376 + network := Regtest() + salt := randomBytes(8) + + privKey, _ := NewHDPrivateKey(randomBytes(32), network) + challengePrivKey := NewChallengePrivateKey([]byte("a very good password"), salt) + + encryptedKey, err := challengePrivKey.PubKey().EncryptKey(privKey, salt, birthday) + if err != nil { + t.Fatal(err) + } + + decryptedKey, err := challengePrivKey.DecryptRawKey(encryptedKey, network) + if err != nil { + t.Fatal(err) + } + + if privKey.String() != decryptedKey.Key.String() { + t.Fatalf("keys dont match: orig %v vs decrypted %v", privKey.String(), decryptedKey.Key.String()) + } + if birthday != decryptedKey.Birthday { + t.Fatalf("birthdays dont match: expected %v got %v", birthday, decryptedKey.Birthday) + } +} + +func TestChallengeKeyCryptoV2(t *testing.T) { + + const ( + encodedKey = "tprv8ZgxMBicQKsPcxg1GFGZgL5zALjPwijrYNUqTi2s9JsVqDLzbpX55U9JH2PKAQKExtpdTyboZmV2ytaqr9pAHuxE1hX8k9bQgZAjq25E6P7" + encryptedKey = "4LbSKwcepbbx4dPetoxvTWszb6mLyJHFhumzmdPRVprbn8XZBvFa6Ffarm6R3WGKutFzdxxJgQDdSHuYdjhDp1EZfSNbj12gXMND1AgmNijSxEua3LwVURU3nzWsvV5b1AsWEjJca24CaFY6T3C" + password = "a very good password" + saltLength = 8 + birthday = 376 + ) + + extractSalt := func(rawKey string) []byte { + bytes := base58.Decode(rawKey) + return bytes[len(bytes)-saltLength:] + } + + challengeKey := NewChallengePrivateKey([]byte(password), extractSalt(encryptedKey)) + decryptedKey, err := challengeKey.DecryptRawKey(encryptedKey, Regtest()) + if err != nil { + t.Fatal(err) + } + + if decryptedKey.Birthday != birthday { + t.Fatalf("decrypted birthday %v differs from expected %v", decryptedKey.Birthday, birthday) + } + + if decryptedKey.Key.String() != encodedKey { + t.Fatalf("key doesnt match\ngot %v\nexpected %v\n", decryptedKey.Key.String(), encodedKey) + } + + _, err = challengeKey.PubKey().EncryptKey(decryptedKey.Key, extractSalt(encryptedKey), birthday) + if err != nil { + t.Fatal(err) + } +} + +func TestDecodeKeyWithOrWithoutSalt(t *testing.T) { + const ( + // The same encoded key, with one version missing the salt field: + saltedKey = "4LbSKwcepbbx4dPetoxvTWszb6mLyJHFhumzmdPRVprbn8XZBvFa6Ffarm6R3WGKutFzdxxJgQDdSHuYdjhDp1EZfSNbj12gXMND1AgmNijSxEua3LwVURU3nzWsvV5b1AsWEjJca24CaFY6T3C" + unsaltedKey = "5XEEts6mc9WV34krDWsqmpLcPCw2JkK8qJu3gFdZpP8ngkERuQEsaDvYrGkhXUpM6jQRtimTYm4XnBPujpo3MsdYBedsNVxvT3WC6uCCFuzNUZCoydVY39yJXbxva7naDxH5iTra" + ) + + expected := &EncryptedPrivateKeyInfo{ + Version: 2, + Birthday: 376, + CipherText: "f6af1ecd17052a81b75902c1712567cf1c650329875feb7e24af3e27235f384054ea549025e99dc2659f95bb6447cf861aa2ec0407ea74baf5a9d6a885ae184b", + EphPublicKey: "020a8d322dda8ff685d80b16681d4e87c109664cdc246a9d3625adfe0de203e71e", + Salt: "e3305526d0cd675f", + } + + // Verify the salted version: + actual, err := DecodeEncryptedPrivateKey(saltedKey) + if err != nil { + t.Fatal(err) + } + + assertDecodedKeysEqual(t, actual, expected) + + // Verify the unsalted version: + actual, err = DecodeEncryptedPrivateKey(unsaltedKey) + if err != nil { + t.Fatal(err) + } + + expected.Salt = "0000000000000000" // unsalted key should decode with zeroed field + + assertDecodedKeysEqual(t, actual, expected) +} + +func assertDecodedKeysEqual(t *testing.T, actual, expected *EncryptedPrivateKeyInfo) { + if actual.Version != expected.Version { + t.Fatalf("version %v expected %v", actual.Version, expected.Version) + } + + if actual.Birthday != expected.Birthday { + t.Fatalf("birthday %v, expected %v", actual.Birthday, expected.Birthday) + } + + if actual.CipherText != expected.CipherText { + t.Fatalf("cipherText %x expected %x", actual.CipherText, expected.CipherText) + } + + if actual.EphPublicKey != expected.EphPublicKey { + t.Fatalf("ephPublicKey %x expected %x", actual.EphPublicKey, expected.EphPublicKey) + } + + if actual.Salt != expected.Salt { + t.Fatalf("salt %x expected %x", actual.Salt, expected.Salt) + } +} diff --git a/vendor/github.com/muun/libwallet/challenge_public_key.go b/libwallet/challenge_public_key.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/challenge_public_key.go rename to libwallet/challenge_public_key.go diff --git a/vendor/github.com/muun/libwallet/emergency_kit.go b/libwallet/emergency_kit.go old mode 100644 new mode 100755 similarity index 100% rename from vendor/github.com/muun/libwallet/emergency_kit.go rename to libwallet/emergency_kit.go diff --git a/libwallet/emergency_kit_test.go b/libwallet/emergency_kit_test.go new file mode 100755 index 0000000..3423426 --- /dev/null +++ b/libwallet/emergency_kit_test.go @@ -0,0 +1,15 @@ +package libwallet + +import ( + "testing" +) + +func TestGenerateEmergencyKitHTML(t *testing.T) { + _, err := GenerateEmergencyKitHTML(&EKInput{ + FirstEncryptedKey: "5zZPk5V7oJcXtQyFgdxrP6D5A4Xck2XMC2FG7rrxeDu89K4YuuMoAdZ2MeAGqMU28aR4Lsa5HRxB5mDXmajmYgLaZi6CivXeBRSzazJb8T4VizArrDA8NDH8TipEsHnwCyCd6eiNQYbedyRPw4B", + SecondEncryptedKey: "4RLVcRNPSdCcV5pdd6FsNuUzhGwp3h7piXhpDkHbF31PrHmNqsyMd9vRveXsBVsWPLXHvMkvhzk68yGw4Wwcxfz55yPeN5Jogqpmn7BQc7P1SNymwtgbatLiJfwqFLm1iqoLPobCmK6wH7MY9N7", + }, "es") + if err != nil { + t.Fatal(err) + } +} diff --git a/vendor/github.com/muun/libwallet/emergencykit/content.go b/libwallet/emergencykit/content.go similarity index 100% rename from vendor/github.com/muun/libwallet/emergencykit/content.go rename to libwallet/emergencykit/content.go diff --git a/vendor/github.com/muun/libwallet/emergencykit/css.go b/libwallet/emergencykit/css.go similarity index 100% rename from vendor/github.com/muun/libwallet/emergencykit/css.go rename to libwallet/emergencykit/css.go diff --git a/vendor/github.com/muun/libwallet/emergencykit/descriptors.go b/libwallet/emergencykit/descriptors.go similarity index 100% rename from vendor/github.com/muun/libwallet/emergencykit/descriptors.go rename to libwallet/emergencykit/descriptors.go diff --git a/libwallet/emergencykit/descriptors_test.go b/libwallet/emergencykit/descriptors_test.go new file mode 100644 index 0000000..a69ab45 --- /dev/null +++ b/libwallet/emergencykit/descriptors_test.go @@ -0,0 +1,34 @@ +package emergencykit + +import "testing" + +func TestChecksum(t *testing.T) { + // These descriptors are in https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md and + // their expected checksums obtained via the `getdescriptorinfo` RPC endpoint. Note that, to + // reproduce these results, you need a mainnet Bitcoin node (HD key parsing fails otherwise). + + testChecksum(t, "gn28ywm7", "pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)") + testChecksum(t, "8fhd9pwu", "pkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5)") + testChecksum(t, "8zl0zxma", "wpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9)") + testChecksum(t, "qkrrc7je", "sh(wpkh(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556))") + testChecksum(t, "lq9sf04s", "combo(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)") + testChecksum(t, "2wtr0ej5", "sh(wsh(pkh(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)))") + testChecksum(t, "hzhjw406", "multi(1,022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)") + testChecksum(t, "y9zthqta", "sh(multi(2,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))") + testChecksum(t, "en3tu306", "wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))") + testChecksum(t, "ks05yr6p", "sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))") + testChecksum(t, "qwx6n9lh", "sh(sortedmulti(2,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))") + testChecksum(t, "axav5m0j", "pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8)") + testChecksum(t, "kczqajcv", "pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1/2)") + testChecksum(t, "ml40v0wf", "pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)") + testChecksum(t, "t2zpj2eu", "wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))") + testChecksum(t, "v66cvalc", "wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))") +} + +func testChecksum(t *testing.T, expectedChecksum string, descriptor string) { + actualChecksum := calculateChecksum(descriptor) + + if actualChecksum != expectedChecksum { + t.Errorf("Descriptor %s checksum was %s expecting %s", descriptor, actualChecksum, expectedChecksum) + } +} diff --git a/vendor/github.com/muun/libwallet/emergencykit/emergencykit.go b/libwallet/emergencykit/emergencykit.go similarity index 100% rename from vendor/github.com/muun/libwallet/emergencykit/emergencykit.go rename to libwallet/emergencykit/emergencykit.go diff --git a/libwallet/emergencykit/emergencykit_test.go b/libwallet/emergencykit/emergencykit_test.go new file mode 100644 index 0000000..23670fa --- /dev/null +++ b/libwallet/emergencykit/emergencykit_test.go @@ -0,0 +1,105 @@ +package emergencykit + +import ( + "strings" + "testing" +) + +func TestGenerateHTML(t *testing.T) { + out, err := GenerateHTML(&Input{ + FirstEncryptedKey: "MyFirstEncryptedKey", + SecondEncryptedKey: "MySecondEncryptedKey", + }, "en") + if err != nil { + t.Fatal(err) + } + + if len(out.VerificationCode) != 6 { + t.Fatal("expected verification code to have length 6") + } + if !strings.Contains(out.HTML, out.VerificationCode) { + t.Fatal("expected output html to contain verification code") + } + if !strings.Contains(out.HTML, "MyFirstEncryptedKey") { + t.Fatal("expected output html to contain first encrypted key") + } + if !strings.Contains(out.HTML, "MySecondEncryptedKey") { + t.Fatal("expected output html to contain second encrypted key") + } + if !strings.Contains(out.HTML, `