From 1782413570a019facba914f91fc91a5dc7cf1828 Mon Sep 17 00:00:00 2001 From: Manu Herrera Date: Mon, 3 Aug 2020 12:17:17 -0300 Subject: [PATCH] Release v0.4.0 --- .gitignore | 18 +- .vscode/launch.json | 17 + .vscode/settings.json | 5 + address.go | 33 +- address_test.go | 55 +- aes.go | 22 +- bip70.pb.go | 691 +- bip70.proto | 36 +- challenge_keys.go | 24 +- challenge_keys_test.go | 43 +- challenge_public_key.go | 32 +- ek_html.go | 289 + emergency_kit.go | 82 + encodings_test.go | 2 +- encrypt.go | 400 + encrypt_test.go | 230 + go.mod | 20 +- go.sum | 142 +- hdprivatekey.go | 16 + hdpublickey.go | 4 + hdpublickey_test.go | 22 + invoice.go | 28 +- invoice_test.go | 33 + keycrypter.go | 4 +- partiallysignedtransaction_test.go | 57 +- publickey.go | 19 + ripemd160.go | 2 +- vendor/github.com/aead/siphash/.gitignore | 25 + vendor/github.com/aead/siphash/.travis.yml | 15 + vendor/github.com/aead/siphash/LICENSE | 21 + vendor/github.com/aead/siphash/README.md | 55 + vendor/github.com/aead/siphash/siphash.go | 157 + vendor/github.com/aead/siphash/siphash128.go | 106 + vendor/github.com/aead/siphash/siphash_386.go | 31 + vendor/github.com/aead/siphash/siphash_386.s | 65 + .../github.com/aead/siphash/siphash_amd64.go | 18 + .../github.com/aead/siphash/siphash_amd64.s | 49 + .../aead/siphash/siphash_generic.go | 188 + vendor/github.com/aead/siphash/siphash_ref.go | 19 + .../btcsuite/btcd/addrmgr/addrmanager.go | 1151 +++ .../btcsuite/btcd/addrmgr/cov_report.sh | 17 + .../github.com/btcsuite/btcd/addrmgr/doc.go | 38 + .../btcsuite/btcd/addrmgr/knownaddress.go | 102 + .../github.com/btcsuite/btcd/addrmgr/log.go | 32 + .../btcsuite/btcd/addrmgr/network.go | 281 + .../btcsuite/btcd/addrmgr/test_coverage.txt | 62 + .../btcsuite/btcd/blockchain/README.md | 103 + .../btcsuite/btcd/blockchain/accept.go | 92 + .../btcsuite/btcd/blockchain/blockindex.go | 348 + .../btcsuite/btcd/blockchain/chain.go | 1803 +++++ .../btcsuite/btcd/blockchain/chainio.go | 1416 ++++ .../btcsuite/btcd/blockchain/chainview.go | 423 + .../btcsuite/btcd/blockchain/checkpoints.go | 261 + .../btcsuite/btcd/blockchain/compress.go | 586 ++ .../btcsuite/btcd/blockchain/difficulty.go | 312 + .../btcsuite/btcd/blockchain/doc.go | 81 + .../btcsuite/btcd/blockchain/error.go | 298 + .../btcsuite/btcd/blockchain/log.go | 30 + .../btcsuite/btcd/blockchain/mediantime.go | 218 + .../btcsuite/btcd/blockchain/merkle.go | 265 + .../btcsuite/btcd/blockchain/notifications.go | 81 + .../btcsuite/btcd/blockchain/process.go | 244 + .../btcsuite/btcd/blockchain/scriptval.go | 319 + .../btcd/blockchain/thresholdstate.go | 356 + .../btcsuite/btcd/blockchain/timesorter.go | 27 + .../btcsuite/btcd/blockchain/upgrade.go | 604 ++ .../btcsuite/btcd/blockchain/utxoviewpoint.go | 642 ++ .../btcsuite/btcd/blockchain/validate.go | 1279 +++ .../btcsuite/btcd/blockchain/versionbits.go | 301 + .../btcsuite/btcd/blockchain/weight.go | 117 + .../btcsuite/btcd/btcjson/CONTRIBUTORS | 16 + .../btcsuite/btcd/btcjson/README.md | 70 + .../btcsuite/btcd/btcjson/btcdextcmds.go | 156 + .../btcsuite/btcd/btcjson/btcdextresults.go | 20 + .../btcsuite/btcd/btcjson/btcwalletextcmds.go | 106 + .../btcsuite/btcd/btcjson/chainsvrcmds.go | 883 +++ .../btcsuite/btcd/btcjson/chainsvrresults.go | 666 ++ .../btcsuite/btcd/btcjson/chainsvrwscmds.go | 241 + .../btcsuite/btcd/btcjson/chainsvrwsntfns.go | 304 + .../btcd/btcjson/chainsvrwsresults.go | 21 + .../btcsuite/btcd/btcjson/cmdinfo.go | 249 + .../btcsuite/btcd/btcjson/cmdparse.go | 550 ++ .../github.com/btcsuite/btcd/btcjson/doc.go | 146 + .../github.com/btcsuite/btcd/btcjson/error.go | 111 + .../github.com/btcsuite/btcd/btcjson/help.go | 560 ++ .../btcsuite/btcd/btcjson/helpers.go | 77 + .../btcsuite/btcd/btcjson/jsonrpc.go | 150 + .../btcsuite/btcd/btcjson/jsonrpcerr.go | 89 + .../btcsuite/btcd/btcjson/register.go | 292 + .../btcsuite/btcd/btcjson/walletsvrcmds.go | 724 ++ .../btcsuite/btcd/btcjson/walletsvrresults.go | 161 + .../btcsuite/btcd/btcjson/walletsvrwscmds.go | 128 + .../btcsuite/btcd/btcjson/walletsvrwsntfns.go | 95 + .../btcsuite/btcd/connmgr/dynamicbanscore.go | 2 +- .../btcsuite/btcd/database/README.md | 57 + .../github.com/btcsuite/btcd/database/doc.go | 91 + .../btcsuite/btcd/database/driver.go | 89 + .../btcsuite/btcd/database/error.go | 197 + .../btcsuite/btcd/database/interface.go | 466 ++ .../github.com/btcsuite/btcd/database/log.go | 37 + .../github.com/btcsuite/btcd/peer/README.md | 73 + vendor/github.com/btcsuite/btcd/peer/doc.go | 150 + vendor/github.com/btcsuite/btcd/peer/log.go | 227 + .../btcsuite/btcd/peer/mruinvmap.go | 127 + .../btcsuite/btcd/peer/mrunoncemap.go | 125 + vendor/github.com/btcsuite/btcd/peer/peer.go | 2280 ++++++ .../btcsuite/btcd/rpcclient/CONTRIBUTORS | 13 + .../btcsuite/btcd/rpcclient/README.md | 56 + .../btcsuite/btcd/rpcclient/chain.go | 1153 +++ .../github.com/btcsuite/btcd/rpcclient/doc.go | 178 + .../btcsuite/btcd/rpcclient/extensions.go | 473 ++ .../btcsuite/btcd/rpcclient/infrastructure.go | 1468 ++++ .../github.com/btcsuite/btcd/rpcclient/log.go | 47 + .../btcsuite/btcd/rpcclient/mining.go | 464 ++ .../github.com/btcsuite/btcd/rpcclient/net.go | 356 + .../btcsuite/btcd/rpcclient/notify.go | 1357 ++++ .../btcsuite/btcd/rpcclient/rawrequest.go | 78 + .../btcd/rpcclient/rawtransactions.go | 699 ++ .../btcsuite/btcd/rpcclient/wallet.go | 2319 ++++++ .../btcsuite/btcd/txscript/engine.go | 2 +- .../github.com/btcsuite/btcutil/gcs/README.md | 24 + .../btcsuite/btcutil/gcs/builder/builder.go | 371 + vendor/github.com/btcsuite/btcutil/gcs/doc.go | 24 + vendor/github.com/btcsuite/btcutil/gcs/gcs.go | 541 ++ vendor/github.com/btcsuite/btcutil/go.mod | 11 + vendor/github.com/btcsuite/btcutil/go.sum | 54 + vendor/github.com/btcsuite/btcwallet/LICENSE | 16 + .../btcwallet/chain/bitcoind_client.go | 1341 ++++ .../btcsuite/btcwallet/chain/bitcoind_conn.go | 460 ++ .../btcwallet/chain/block_filterer.go | 217 + .../btcsuite/btcwallet/chain/interface.go | 124 + .../btcsuite/btcwallet/chain/log.go | 56 + .../btcsuite/btcwallet/chain/neutrino.go | 754 ++ .../btcsuite/btcwallet/chain/queue.go | 88 + .../btcsuite/btcwallet/chain/rpc.go | 461 ++ .../internal/legacy/keystore/keystore.go | 3241 ++++++++ .../internal/legacy/rename/rename_unix.go | 17 + .../internal/legacy/rename/rename_windows.go | 71 + .../btcwallet/internal/prompt/prompt.go | 323 + .../btcsuite/btcwallet/internal/zero/array.go | 17 + .../btcsuite/btcwallet/internal/zero/doc.go | 3 + .../btcsuite/btcwallet/internal/zero/slice.go | 34 + .../btcsuite/btcwallet/snacl/snacl.go | 248 + .../btcsuite/btcwallet/waddrmgr/README.md | 63 + .../btcsuite/btcwallet/waddrmgr/address.go | 648 ++ .../btcsuite/btcwallet/waddrmgr/cov_report.sh | 17 + .../btcsuite/btcwallet/waddrmgr/db.go | 2284 ++++++ .../btcsuite/btcwallet/waddrmgr/doc.go | 155 + .../btcsuite/btcwallet/waddrmgr/error.go | 219 + .../btcsuite/btcwallet/waddrmgr/log.go | 43 + .../btcsuite/btcwallet/waddrmgr/manager.go | 1916 +++++ .../btcsuite/btcwallet/waddrmgr/migrations.go | 412 + .../btcwallet/waddrmgr/scoped_manager.go | 1872 +++++ .../btcsuite/btcwallet/waddrmgr/sync.go | 135 + .../btcwallet/waddrmgr/test_coverage.txt | 126 + .../btcsuite/btcwallet/wallet/README.md | 31 + .../btcsuite/btcwallet/wallet/chainntfns.go | 485 ++ .../btcsuite/btcwallet/wallet/common.go | 88 + .../btcsuite/btcwallet/wallet/createtx.go | 290 + .../btcsuite/btcwallet/wallet/disksync.go | 31 + .../btcsuite/btcwallet/wallet/doc.go | 12 + .../btcsuite/btcwallet/wallet/loader.go | 284 + .../btcsuite/btcwallet/wallet/log.go | 65 + .../btcsuite/btcwallet/wallet/mock.go | 85 + .../btcsuite/btcwallet/wallet/multisig.go | 114 + .../btcwallet/wallet/notifications.go | 637 ++ .../btcsuite/btcwallet/wallet/recovery.go | 410 + .../btcsuite/btcwallet/wallet/rescan.go | 318 + .../btcwallet/wallet/txauthor/LICENSE | 16 + .../btcwallet/wallet/txauthor/author.go | 367 + .../btcwallet/wallet/txauthor/cprng.go | 39 + .../btcsuite/btcwallet/wallet/txauthor/go.mod | 14 + .../btcsuite/btcwallet/wallet/txauthor/go.sum | 66 + .../btcsuite/btcwallet/wallet/txrules/LICENSE | 16 + .../btcsuite/btcwallet/wallet/txrules/go.mod | 8 + .../btcsuite/btcwallet/wallet/txrules/go.sum | 33 + .../btcwallet/wallet/txrules/rules.go | 98 + .../btcsuite/btcwallet/wallet/txsizes/LICENSE | 16 + .../btcsuite/btcwallet/wallet/txsizes/go.mod | 17 + .../btcsuite/btcwallet/wallet/txsizes/go.sum | 65 + .../btcsuite/btcwallet/wallet/txsizes/size.go | 190 + .../btcsuite/btcwallet/wallet/unstable.go | 44 + .../btcsuite/btcwallet/wallet/utxos.go | 90 + .../btcsuite/btcwallet/wallet/wallet.go | 3847 +++++++++ .../btcsuite/btcwallet/walletdb/LICENSE | 16 + .../btcsuite/btcwallet/walletdb/README.md | 75 + .../btcsuite/btcwallet/walletdb/cov_report.sh | 7 + .../btcsuite/btcwallet/walletdb/doc.go | 103 + .../btcsuite/btcwallet/walletdb/error.go | 80 + .../btcsuite/btcwallet/walletdb/go.mod | 9 + .../btcsuite/btcwallet/walletdb/go.sum | 8 + .../btcsuite/btcwallet/walletdb/interface.go | 364 + .../btcwallet/walletdb/migration/log.go | 43 + .../btcwallet/walletdb/migration/manager.go | 162 + .../btcwallet/walletdb/test_coverage.txt | 39 + .../btcsuite/btcwallet/wtxmgr/LICENSE | 16 + .../btcsuite/btcwallet/wtxmgr/README.md | 45 + .../btcsuite/btcwallet/wtxmgr/db.go | 1623 ++++ .../btcsuite/btcwallet/wtxmgr/doc.go | 31 + .../btcsuite/btcwallet/wtxmgr/error.go | 97 + .../btcsuite/btcwallet/wtxmgr/go.mod | 12 + .../btcsuite/btcwallet/wtxmgr/go.sum | 66 + .../btcsuite/btcwallet/wtxmgr/kahnsort.go | 117 + .../btcsuite/btcwallet/wtxmgr/log.go | 47 + .../btcsuite/btcwallet/wtxmgr/migrations.go | 110 + .../btcsuite/btcwallet/wtxmgr/query.go | 458 ++ .../btcsuite/btcwallet/wtxmgr/tx.go | 1228 +++ .../btcsuite/btcwallet/wtxmgr/unconfirmed.go | 222 + vendor/github.com/btcsuite/go-socks/LICENSE | 25 + .../btcsuite/go-socks/socks/addr.go | 21 + .../btcsuite/go-socks/socks/conn.go | 54 + .../btcsuite/go-socks/socks/dial.go | 269 + .../github.com/btcsuite/websocket/.gitignore | 22 + .../github.com/btcsuite/websocket/.travis.yml | 6 + vendor/github.com/btcsuite/websocket/AUTHORS | 8 + vendor/github.com/btcsuite/websocket/LICENSE | 22 + .../github.com/btcsuite/websocket/README.md | 63 + .../github.com/btcsuite/websocket/client.go | 235 + vendor/github.com/btcsuite/websocket/conn.go | 825 ++ vendor/github.com/btcsuite/websocket/doc.go | 148 + vendor/github.com/btcsuite/websocket/json.go | 49 + .../github.com/btcsuite/websocket/server.go | 247 + vendor/github.com/btcsuite/websocket/util.go | 44 + .../github.com/go-errors/errors/.travis.yml | 2 + vendor/github.com/go-errors/errors/README.md | 3 + vendor/github.com/go-errors/errors/error.go | 26 +- .../github.com/go-errors/errors/error_1_13.go | 26 + .../go-errors/errors/error_backward.go | 22 + vendor/github.com/go-errors/errors/go.mod | 3 + .../github.com/go-errors/errors/stackframe.go | 28 +- .../golang/protobuf/proto/buffer.go | 324 + .../github.com/golang/protobuf/proto/clone.go | 253 - .../golang/protobuf/proto/decode.go | 427 - .../golang/protobuf/proto/defaults.go | 63 + .../golang/protobuf/proto/deprecated.go | 105 +- .../golang/protobuf/proto/discard.go | 356 +- .../golang/protobuf/proto/encode.go | 203 - .../github.com/golang/protobuf/proto/equal.go | 301 - .../golang/protobuf/proto/extensions.go | 771 +- .../github.com/golang/protobuf/proto/lib.go | 965 --- .../golang/protobuf/proto/message_set.go | 181 - .../golang/protobuf/proto/pointer_reflect.go | 360 - .../golang/protobuf/proto/pointer_unsafe.go | 313 - .../golang/protobuf/proto/properties.go | 648 +- .../github.com/golang/protobuf/proto/proto.go | 167 + .../golang/protobuf/proto/registry.go | 323 + .../golang/protobuf/proto/table_marshal.go | 2776 ------- .../golang/protobuf/proto/table_merge.go | 654 -- .../golang/protobuf/proto/table_unmarshal.go | 2053 ----- .../github.com/golang/protobuf/proto/text.go | 843 -- .../golang/protobuf/proto/text_decode.go | 801 ++ .../golang/protobuf/proto/text_encode.go | 560 ++ .../golang/protobuf/proto/text_parser.go | 880 --- .../github.com/golang/protobuf/proto/wire.go | 78 + .../golang/protobuf/proto/wrappers.go | 34 + vendor/github.com/kkdai/bstream/.gitignore | 2 + vendor/github.com/kkdai/bstream/.travis.yml | 15 + vendor/github.com/kkdai/bstream/LICENSE | 22 + vendor/github.com/kkdai/bstream/README.md | 61 + vendor/github.com/kkdai/bstream/bstream.go | 179 + vendor/github.com/lightninglabs/gozmq/LICENSE | 21 + .../github.com/lightninglabs/gozmq/README.md | 29 + vendor/github.com/lightninglabs/gozmq/go.mod | 3 + vendor/github.com/lightninglabs/gozmq/zmq.go | 507 ++ .../lightninglabs/neutrino/.gitignore | 30 + .../lightninglabs/neutrino/.travis.yml | 22 + .../github.com/lightninglabs/neutrino/LICENSE | 21 + .../lightninglabs/neutrino/README.md | 25 + .../lightninglabs/neutrino/banman/codec.go | 83 + .../lightninglabs/neutrino/banman/reason.go | 43 + .../lightninglabs/neutrino/banman/store.go | 221 + .../lightninglabs/neutrino/banman/util.go | 48 + .../neutrino/batch_spend_reporter.go | 267 + .../lightninglabs/neutrino/blockmanager.go | 3045 ++++++++ .../lightninglabs/neutrino/blockntfns/log.go | 43 + .../neutrino/blockntfns/manager.go | 353 + .../neutrino/blockntfns/notification.go | 105 + .../lightninglabs/neutrino/btcd_checkout.sh | 12 + .../lightninglabs/neutrino/cache/cache.go | 29 + .../neutrino/cache/cacheable_block.go | 14 + .../neutrino/cache/cacheable_filter.go | 28 + .../lightninglabs/neutrino/cache/lru/lru.go | 167 + .../neutrino/chainsync/filtercontrol.go | 75 + .../lightninglabs/neutrino/errors.go | 11 + .../lightninglabs/neutrino/filterdb/db.go | 228 + .../github.com/lightninglabs/neutrino/go.mod | 14 + .../github.com/lightninglabs/neutrino/go.sum | 101 + .../lightninglabs/neutrino/gotest.sh | 138 + .../lightninglabs/neutrino/headerfs/file.go | 189 + .../lightninglabs/neutrino/headerfs/index.go | 305 + .../lightninglabs/neutrino/headerfs/store.go | 939 +++ .../neutrino/headerfs/truncate.go | 38 + .../neutrino/headerfs/truncate_windows.go | 56 + .../headerlist/bounded_header_list.go | 137 + .../neutrino/headerlist/header_list.go | 46 + .../lightninglabs/neutrino/headerlogger.go | 76 + .../github.com/lightninglabs/neutrino/log.go | 60 + .../lightninglabs/neutrino/mock_store.go | 82 + .../lightninglabs/neutrino/neutrino.go | 1607 ++++ .../lightninglabs/neutrino/notifications.go | 373 + .../neutrino/pushtx/broadcaster.go | 290 + .../lightninglabs/neutrino/pushtx/error.go | 152 + .../lightninglabs/neutrino/pushtx/log.go | 43 + .../lightninglabs/neutrino/query.go | 1182 +++ .../lightninglabs/neutrino/query/interface.go | 145 + .../lightninglabs/neutrino/query/log.go | 43 + .../lightninglabs/neutrino/query/peer_rank.go | 93 + .../lightninglabs/neutrino/query/worker.go | 251 + .../neutrino/query/workmanager.go | 452 ++ .../lightninglabs/neutrino/query/workqueue.go | 57 + .../lightninglabs/neutrino/rescan.go | 1449 ++++ .../lightninglabs/neutrino/utxoscanner.go | 434 ++ .../lightningnetwork/lnd/clock/LICENSE | 19 + .../lnd/clock/default_clock.go | 24 + .../lightningnetwork/lnd/clock/go.mod | 3 + .../lightningnetwork/lnd/clock/interface.go | 16 + .../lightningnetwork/lnd/clock/test_clock.go | 96 + .../lightningnetwork/lnd/input/input.go | 200 + .../lnd/input/script_utils.go | 1298 ++++ .../lnd/input/signdescriptor.go | 226 + .../lightningnetwork/lnd/input/signer.go | 42 + .../lightningnetwork/lnd/input/size.go | 588 ++ .../lightningnetwork/lnd/input/test_utils.go | 191 + .../lightningnetwork/lnd/input/txout.go | 46 + .../lightningnetwork/lnd/input/witnessgen.go | 443 ++ .../lnd/keychain/btcwallet.go | 373 + .../lnd/keychain/derivation.go | 198 + .../lnd/lnwire/accept_channel.go | 28 +- .../lightningnetwork/lnd/lnwire/channel_id.go | 14 +- .../lightningnetwork/lnd/lnwire/features.go | 172 +- .../lnd/lnwire/init_message.go | 24 +- .../lightningnetwork/lnd/lnwire/lnwire.go | 4 +- .../lightningnetwork/lnd/lnwire/msat.go | 12 +- .../lnd/lnwire/node_announcement.go | 8 - .../lnd/lnwire/onion_error.go | 95 + .../lnd/lnwire/open_channel.go | 29 +- .../lnd/lnwire/query_channel_range.go | 12 + .../lnd/lnwire/query_short_chan_ids.go | 100 +- .../lnd/lnwire/reply_channel_range.go | 8 +- .../lightningnetwork/lnd/lnwire/shutdown.go | 16 +- .../lightningnetwork/lnd/lnwire/signature.go | 3 +- .../lightningnetwork/lnd/queue/LICENSE | 19 + .../lnd/queue/circular_buf.go | 116 + .../lightningnetwork/lnd/queue/gc_queue.go | 194 + .../lightningnetwork/lnd/queue/go.mod | 7 + .../lightningnetwork/lnd/queue/go.sum | 0 .../lnd/queue/priority_queue.go | 76 + .../lightningnetwork/lnd/queue/queue.go | 125 + .../lightningnetwork/lnd/ticker/LICENSE | 19 + .../lightningnetwork/lnd/ticker/force.go | 105 + .../lightningnetwork/lnd/ticker/go.mod | 1 + .../lightningnetwork/lnd/ticker/ticker.go | 126 + .../lightningnetwork/lnd/tlv/primitive.go | 309 + .../lightningnetwork/lnd/tlv/record.go | 251 + .../lightningnetwork/lnd/tlv/stream.go | 318 + .../lightningnetwork/lnd/tlv/truncated.go | 207 + .../lightningnetwork/lnd/tlv/varint.go | 116 + .../lightningnetwork/lnd/tor/README.md | 4 +- .../lightningnetwork/lnd/tor/add_onion.go | 217 + .../lightningnetwork/lnd/tor/controller.go | 314 +- .../lightningnetwork/lnd/zpay32/invoice.go | 178 +- vendor/github.com/miekg/dns/.codecov.yml | 8 + vendor/github.com/miekg/dns/.travis.yml | 15 +- vendor/github.com/miekg/dns/CODEOWNERS | 1 + vendor/github.com/miekg/dns/LICENSE | 6 +- vendor/github.com/miekg/dns/Makefile.release | 52 + vendor/github.com/miekg/dns/README.md | 73 +- vendor/github.com/miekg/dns/acceptfunc.go | 61 + vendor/github.com/miekg/dns/client.go | 240 +- vendor/github.com/miekg/dns/clientconfig.go | 16 +- vendor/github.com/miekg/dns/defaults.go | 137 +- vendor/github.com/miekg/dns/dns.go | 71 +- vendor/github.com/miekg/dns/dnssec.go | 230 +- vendor/github.com/miekg/dns/dnssec_keygen.go | 58 +- vendor/github.com/miekg/dns/dnssec_keyscan.go | 231 +- vendor/github.com/miekg/dns/dnssec_privkey.go | 21 +- vendor/github.com/miekg/dns/doc.go | 112 +- vendor/github.com/miekg/dns/duplicate.go | 37 + vendor/github.com/miekg/dns/edns.go | 171 +- vendor/github.com/miekg/dns/format.go | 8 +- vendor/github.com/miekg/dns/fuzz.go | 11 +- vendor/github.com/miekg/dns/generate.go | 320 +- vendor/github.com/miekg/dns/go.mod | 11 + vendor/github.com/miekg/dns/go.sum | 39 + .../miekg/dns/internal/socket/cmsghdr.go | 7 - .../internal/socket/cmsghdr_linux_64bit.go | 20 - .../dns/internal/socket/cmsghdr_other.go | 13 - .../dns/internal/socket/controlmessage.go | 118 - .../miekg/dns/internal/socket/socket.go | 4 - .../miekg/dns/internal/socket/sys.go | 14 - vendor/github.com/miekg/dns/labels.go | 75 +- vendor/github.com/miekg/dns/listen_go111.go | 44 + .../github.com/miekg/dns/listen_go_not111.go | 23 + vendor/github.com/miekg/dns/msg.go | 837 +- vendor/github.com/miekg/dns/msg_helpers.go | 282 +- vendor/github.com/miekg/dns/msg_truncate.go | 111 + vendor/github.com/miekg/dns/nsecx.go | 49 +- vendor/github.com/miekg/dns/privaterr.go | 130 +- vendor/github.com/miekg/dns/rawmsg.go | 49 - vendor/github.com/miekg/dns/reverse.go | 14 + vendor/github.com/miekg/dns/sanitize.go | 10 +- vendor/github.com/miekg/dns/scan.go | 1121 ++- vendor/github.com/miekg/dns/scan_rr.go | 1991 ++--- vendor/github.com/miekg/dns/scanner.go | 56 - vendor/github.com/miekg/dns/serve_mux.go | 122 + vendor/github.com/miekg/dns/server.go | 703 +- vendor/github.com/miekg/dns/sig0.go | 31 +- vendor/github.com/miekg/dns/singleinflight.go | 10 +- vendor/github.com/miekg/dns/smimea.go | 5 +- vendor/github.com/miekg/dns/tlsa.go | 5 +- vendor/github.com/miekg/dns/tsig.go | 31 +- vendor/github.com/miekg/dns/types.go | 432 +- vendor/github.com/miekg/dns/udp.go | 67 +- vendor/github.com/miekg/dns/udp_linux.go | 220 - vendor/github.com/miekg/dns/udp_other.go | 17 - vendor/github.com/miekg/dns/udp_windows.go | 13 +- vendor/github.com/miekg/dns/update.go | 14 +- vendor/github.com/miekg/dns/version.go | 15 + vendor/github.com/miekg/dns/xfr.go | 64 +- vendor/github.com/miekg/dns/zcompress.go | 119 - vendor/github.com/miekg/dns/zduplicate.go | 1157 +++ vendor/github.com/miekg/dns/zmsg.go | 2066 ++--- vendor/github.com/miekg/dns/ztypes.go | 512 +- vendor/github.com/pkg/errors/.travis.yml | 11 +- vendor/github.com/pkg/errors/Makefile | 44 + vendor/github.com/pkg/errors/README.md | 11 +- vendor/github.com/pkg/errors/errors.go | 8 +- vendor/github.com/pkg/errors/go113.go | 38 + vendor/github.com/pkg/errors/stack.go | 58 +- vendor/golang.org/x/crypto/ed25519/ed25519.go | 222 + .../x/crypto/ed25519/ed25519_go113.go | 73 + .../ed25519/internal/edwards25519/const.go | 1422 ++++ .../internal/edwards25519/edwards25519.go | 1793 +++++ .../x/crypto/internal/subtle/aliasing.go | 32 + .../internal/subtle/aliasing_appengine.go | 35 + .../x/crypto/nacl/secretbox/secretbox.go | 173 + .../x/crypto/poly1305/bits_compat.go | 39 + .../x/crypto/poly1305/bits_go1.13.go | 21 + .../golang.org/x/crypto/poly1305/mac_noasm.go | 9 + .../golang.org/x/crypto/poly1305/poly1305.go | 99 + .../golang.org/x/crypto/poly1305/sum_amd64.go | 47 + .../golang.org/x/crypto/poly1305/sum_amd64.s | 108 + .../x/crypto/poly1305/sum_generic.go | 310 + .../x/crypto/poly1305/sum_ppc64le.go | 47 + .../x/crypto/poly1305/sum_ppc64le.s | 181 + .../golang.org/x/crypto/poly1305/sum_s390x.go | 75 + .../golang.org/x/crypto/poly1305/sum_s390x.s | 503 ++ .../x/crypto/salsa20/salsa/hsalsa20.go | 144 + .../x/crypto/salsa20/salsa/salsa208.go | 199 + .../x/crypto/salsa20/salsa/salsa20_amd64.go | 23 + .../x/crypto/salsa20/salsa/salsa20_amd64.s | 883 +++ .../x/crypto/salsa20/salsa/salsa20_noasm.go | 14 + .../x/crypto/salsa20/salsa/salsa20_ref.go | 231 + .../x/crypto/ssh/terminal/terminal.go | 987 +++ .../golang.org/x/crypto/ssh/terminal/util.go | 114 + .../x/crypto/ssh/terminal/util_aix.go | 12 + .../x/crypto/ssh/terminal/util_bsd.go | 12 + .../x/crypto/ssh/terminal/util_linux.go | 10 + .../x/crypto/ssh/terminal/util_plan9.go | 58 + .../x/crypto/ssh/terminal/util_solaris.go | 124 + .../x/crypto/ssh/terminal/util_windows.go | 105 + vendor/golang.org/x/net/bpf/asm.go | 41 + vendor/golang.org/x/net/bpf/constants.go | 222 + vendor/golang.org/x/net/bpf/doc.go | 82 + vendor/golang.org/x/net/bpf/instructions.go | 726 ++ vendor/golang.org/x/net/bpf/setter.go | 10 + vendor/golang.org/x/net/bpf/vm.go | 150 + .../golang.org/x/net/bpf/vm_instructions.go | 182 + .../golang.org/x/net/internal/iana/const.go | 223 + .../x/net/internal/socket/cmsghdr.go | 11 + .../x/net/internal/socket/cmsghdr_bsd.go | 13 + .../internal/socket/cmsghdr_linux_32bit.go | 14 +- .../internal/socket/cmsghdr_linux_64bit.go | 14 + .../internal/socket/cmsghdr_solaris_64bit.go | 14 + .../x/net/internal/socket/cmsghdr_stub.go | 17 + .../golang.org/x/net/internal/socket/empty.s | 7 + .../x/net/internal/socket/error_unix.go | 31 + .../x/net/internal/socket/error_windows.go | 26 + .../x/net/internal/socket/iovec_32bit.go | 19 + .../x/net/internal/socket/iovec_64bit.go | 19 + .../internal/socket/iovec_solaris_64bit.go | 19 + .../x/net/internal/socket/iovec_stub.go | 11 + .../x/net/internal/socket/mmsghdr_stub.go | 21 + .../x/net/internal/socket/mmsghdr_unix.go | 42 + .../x/net/internal/socket/msghdr_bsd.go | 39 + .../x/net/internal/socket/msghdr_bsdvar.go | 16 + .../x/net/internal/socket/msghdr_linux.go | 36 + .../net/internal/socket/msghdr_linux_32bit.go | 24 + .../net/internal/socket/msghdr_linux_64bit.go | 24 + .../x/net/internal/socket/msghdr_openbsd.go | 14 + .../internal/socket/msghdr_solaris_64bit.go | 36 + .../x/net/internal/socket/msghdr_stub.go | 14 + .../x/net/internal/socket/norace.go | 12 + .../golang.org/x/net/internal/socket/race.go | 37 + .../x/net/internal/socket/rawconn.go | 64 + .../x/net/internal/socket/rawconn_mmsg.go | 79 + .../x/net/internal/socket/rawconn_msg.go | 78 + .../x/net/internal/socket/rawconn_nommsg.go | 15 + .../x/net/internal/socket/rawconn_nomsg.go | 15 + .../x/net/internal/socket/socket.go | 288 + .../golang.org/x/net/internal/socket/sys.go | 33 + .../x/net/internal/socket/sys_bsd.go | 15 + .../x/net/internal/socket/sys_bsdvar.go | 23 + .../x/net/internal/socket/sys_const_unix.go | 17 + .../x/net/internal/socket/sys_darwin.go | 7 + .../x/net/internal/socket/sys_dragonfly.go | 32 + .../net/internal/socket/sys_go1_11_darwin.go | 33 + .../x/net/internal/socket/sys_linkname.go | 42 + .../x/net/internal/socket/sys_linux.go | 27 + .../x/net/internal/socket/sys_linux_386.go | 55 + .../x/net/internal/socket/sys_linux_386.s | 11 + .../x/net/internal/socket/sys_linux_amd64.go | 10 + .../x/net/internal/socket/sys_linux_arm.go | 10 + .../x/net/internal/socket/sys_linux_arm64.go | 10 + .../x/net/internal/socket/sys_linux_mips.go | 10 + .../x/net/internal/socket/sys_linux_mips64.go | 10 + .../net/internal/socket/sys_linux_mips64le.go | 10 + .../x/net/internal/socket/sys_linux_mipsle.go | 10 + .../x/net/internal/socket/sys_linux_ppc64.go | 10 + .../net/internal/socket/sys_linux_ppc64le.go | 10 + .../net/internal/socket/sys_linux_riscv64.go | 12 + .../x/net/internal/socket/sys_linux_s390x.go | 55 + .../x/net/internal/socket/sys_linux_s390x.s | 11 + .../x/net/internal/socket/sys_netbsd.go | 25 + .../x/net/internal/socket/sys_posix.go | 183 + .../x/net/internal/socket/sys_solaris.go | 70 + .../x/net/internal/socket/sys_solaris_amd64.s | 11 + .../x/net/internal/socket/sys_stub.go | 63 + .../x/net/internal/socket/sys_unix.go | 33 + .../x/net/internal/socket/sys_windows.go | 71 + .../x/net/internal/socket/zsys_aix_ppc64.go | 60 + .../x/net/internal/socket/zsys_darwin_386.go | 51 + .../net/internal/socket/zsys_darwin_amd64.go | 53 + .../x/net/internal/socket/zsys_darwin_arm.go | 51 + .../net/internal/socket/zsys_darwin_arm64.go | 53 + .../internal/socket/zsys_dragonfly_amd64.go | 53 + .../x/net/internal/socket/zsys_freebsd_386.go | 51 + .../net/internal/socket/zsys_freebsd_amd64.go | 53 + .../x/net/internal/socket/zsys_freebsd_arm.go | 51 + .../net/internal/socket/zsys_freebsd_arm64.go | 53 + .../x/net/internal/socket/zsys_linux_386.go | 54 + .../x/net/internal/socket/zsys_linux_amd64.go | 57 + .../x/net/internal/socket/zsys_linux_arm.go | 55 + .../x/net/internal/socket/zsys_linux_arm64.go | 58 + .../x/net/internal/socket/zsys_linux_mips.go | 55 + .../net/internal/socket/zsys_linux_mips64.go | 58 + .../internal/socket/zsys_linux_mips64le.go | 58 + .../net/internal/socket/zsys_linux_mipsle.go | 55 + .../x/net/internal/socket/zsys_linux_ppc64.go | 58 + .../net/internal/socket/zsys_linux_ppc64le.go | 58 + .../net/internal/socket/zsys_linux_riscv64.go | 59 + .../x/net/internal/socket/zsys_linux_s390x.go | 58 + .../x/net/internal/socket/zsys_netbsd_386.go | 57 + .../net/internal/socket/zsys_netbsd_amd64.go | 60 + .../x/net/internal/socket/zsys_netbsd_arm.go | 57 + .../net/internal/socket/zsys_netbsd_arm64.go | 59 + .../x/net/internal/socket/zsys_openbsd_386.go | 51 + .../net/internal/socket/zsys_openbsd_amd64.go | 53 + .../x/net/internal/socket/zsys_openbsd_arm.go | 51 + .../net/internal/socket/zsys_openbsd_arm64.go | 53 + .../net/internal/socket/zsys_solaris_amd64.go | 52 + .../golang.org/x/net/internal/socks/socks.go | 2 +- vendor/golang.org/x/net/ipv4/batch.go | 194 + vendor/golang.org/x/net/ipv4/control.go | 144 + vendor/golang.org/x/net/ipv4/control_bsd.go | 41 + .../golang.org/x/net/ipv4/control_pktinfo.go | 39 + vendor/golang.org/x/net/ipv4/control_stub.go | 13 + vendor/golang.org/x/net/ipv4/control_unix.go | 73 + .../golang.org/x/net/ipv4/control_windows.go | 12 + vendor/golang.org/x/net/ipv4/dgramopt.go | 264 + vendor/golang.org/x/net/ipv4/doc.go | 244 + vendor/golang.org/x/net/ipv4/endpoint.go | 186 + vendor/golang.org/x/net/ipv4/genericopt.go | 55 + vendor/golang.org/x/net/ipv4/header.go | 173 + vendor/golang.org/x/net/ipv4/helper.go | 77 + vendor/golang.org/x/net/ipv4/iana.go | 38 + vendor/golang.org/x/net/ipv4/icmp.go | 57 + vendor/golang.org/x/net/ipv4/icmp_linux.go | 25 + vendor/golang.org/x/net/ipv4/icmp_stub.go | 25 + vendor/golang.org/x/net/ipv4/packet.go | 117 + vendor/golang.org/x/net/ipv4/payload.go | 23 + vendor/golang.org/x/net/ipv4/payload_cmsg.go | 84 + .../golang.org/x/net/ipv4/payload_nocmsg.go | 39 + vendor/golang.org/x/net/ipv4/sockopt.go | 44 + vendor/golang.org/x/net/ipv4/sockopt_posix.go | 71 + vendor/golang.org/x/net/ipv4/sockopt_stub.go | 42 + vendor/golang.org/x/net/ipv4/sys_aix.go | 38 + vendor/golang.org/x/net/ipv4/sys_asmreq.go | 122 + .../golang.org/x/net/ipv4/sys_asmreq_stub.go | 25 + vendor/golang.org/x/net/ipv4/sys_asmreqn.go | 42 + .../golang.org/x/net/ipv4/sys_asmreqn_stub.go | 21 + vendor/golang.org/x/net/ipv4/sys_bpf.go | 24 + vendor/golang.org/x/net/ipv4/sys_bpf_stub.go | 16 + vendor/golang.org/x/net/ipv4/sys_bsd.go | 37 + vendor/golang.org/x/net/ipv4/sys_darwin.go | 65 + vendor/golang.org/x/net/ipv4/sys_dragonfly.go | 35 + vendor/golang.org/x/net/ipv4/sys_freebsd.go | 76 + vendor/golang.org/x/net/ipv4/sys_linux.go | 60 + vendor/golang.org/x/net/ipv4/sys_solaris.go | 57 + vendor/golang.org/x/net/ipv4/sys_ssmreq.go | 52 + .../golang.org/x/net/ipv4/sys_ssmreq_stub.go | 21 + vendor/golang.org/x/net/ipv4/sys_stub.go | 13 + vendor/golang.org/x/net/ipv4/sys_windows.go | 67 + .../golang.org/x/net/ipv4/zsys_aix_ppc64.go | 33 + vendor/golang.org/x/net/ipv4/zsys_darwin.go | 99 + .../golang.org/x/net/ipv4/zsys_dragonfly.go | 31 + .../golang.org/x/net/ipv4/zsys_freebsd_386.go | 93 + .../x/net/ipv4/zsys_freebsd_amd64.go | 95 + .../golang.org/x/net/ipv4/zsys_freebsd_arm.go | 95 + .../x/net/ipv4/zsys_freebsd_arm64.go | 93 + .../golang.org/x/net/ipv4/zsys_linux_386.go | 130 + .../golang.org/x/net/ipv4/zsys_linux_amd64.go | 132 + .../golang.org/x/net/ipv4/zsys_linux_arm.go | 130 + .../golang.org/x/net/ipv4/zsys_linux_arm64.go | 132 + .../golang.org/x/net/ipv4/zsys_linux_mips.go | 130 + .../x/net/ipv4/zsys_linux_mips64.go | 132 + .../x/net/ipv4/zsys_linux_mips64le.go | 132 + .../x/net/ipv4/zsys_linux_mipsle.go | 130 + .../golang.org/x/net/ipv4/zsys_linux_ppc.go | 130 + .../golang.org/x/net/ipv4/zsys_linux_ppc64.go | 132 + .../x/net/ipv4/zsys_linux_ppc64le.go | 132 + .../x/net/ipv4/zsys_linux_riscv64.go | 134 + .../golang.org/x/net/ipv4/zsys_linux_s390x.go | 132 + vendor/golang.org/x/net/ipv4/zsys_netbsd.go | 30 + vendor/golang.org/x/net/ipv4/zsys_openbsd.go | 30 + vendor/golang.org/x/net/ipv4/zsys_solaris.go | 100 + vendor/golang.org/x/net/ipv6/batch.go | 116 + vendor/golang.org/x/net/ipv6/control.go | 187 + .../x/net/ipv6/control_rfc2292_unix.go | 48 + .../x/net/ipv6/control_rfc3542_unix.go | 94 + vendor/golang.org/x/net/ipv6/control_stub.go | 13 + vendor/golang.org/x/net/ipv6/control_unix.go | 55 + .../golang.org/x/net/ipv6/control_windows.go | 12 + vendor/golang.org/x/net/ipv6/dgramopt.go | 301 + vendor/golang.org/x/net/ipv6/doc.go | 243 + vendor/golang.org/x/net/ipv6/endpoint.go | 127 + vendor/golang.org/x/net/ipv6/genericopt.go | 56 + vendor/golang.org/x/net/ipv6/header.go | 55 + vendor/golang.org/x/net/ipv6/helper.go | 58 + vendor/golang.org/x/net/ipv6/iana.go | 86 + vendor/golang.org/x/net/ipv6/icmp.go | 60 + vendor/golang.org/x/net/ipv6/icmp_bsd.go | 29 + vendor/golang.org/x/net/ipv6/icmp_linux.go | 27 + vendor/golang.org/x/net/ipv6/icmp_solaris.go | 27 + vendor/golang.org/x/net/ipv6/icmp_stub.go | 23 + vendor/golang.org/x/net/ipv6/icmp_windows.go | 22 + vendor/golang.org/x/net/ipv6/payload.go | 23 + vendor/golang.org/x/net/ipv6/payload_cmsg.go | 70 + .../golang.org/x/net/ipv6/payload_nocmsg.go | 38 + vendor/golang.org/x/net/ipv6/sockopt.go | 43 + vendor/golang.org/x/net/ipv6/sockopt_posix.go | 89 + vendor/golang.org/x/net/ipv6/sockopt_stub.go | 46 + vendor/golang.org/x/net/ipv6/sys_aix.go | 77 + vendor/golang.org/x/net/ipv6/sys_asmreq.go | 24 + .../golang.org/x/net/ipv6/sys_asmreq_stub.go | 17 + vendor/golang.org/x/net/ipv6/sys_bpf.go | 24 + vendor/golang.org/x/net/ipv6/sys_bpf_stub.go | 16 + vendor/golang.org/x/net/ipv6/sys_bsd.go | 57 + vendor/golang.org/x/net/ipv6/sys_darwin.go | 78 + vendor/golang.org/x/net/ipv6/sys_freebsd.go | 92 + vendor/golang.org/x/net/ipv6/sys_linux.go | 75 + vendor/golang.org/x/net/ipv6/sys_solaris.go | 74 + vendor/golang.org/x/net/ipv6/sys_ssmreq.go | 54 + .../golang.org/x/net/ipv6/sys_ssmreq_stub.go | 21 + vendor/golang.org/x/net/ipv6/sys_stub.go | 13 + vendor/golang.org/x/net/ipv6/sys_windows.go | 75 + .../golang.org/x/net/ipv6/zsys_aix_ppc64.go | 103 + vendor/golang.org/x/net/ipv6/zsys_darwin.go | 131 + .../golang.org/x/net/ipv6/zsys_dragonfly.go | 88 + .../golang.org/x/net/ipv6/zsys_freebsd_386.go | 122 + .../x/net/ipv6/zsys_freebsd_amd64.go | 124 + .../golang.org/x/net/ipv6/zsys_freebsd_arm.go | 124 + .../x/net/ipv6/zsys_freebsd_arm64.go | 122 + .../golang.org/x/net/ipv6/zsys_linux_386.go | 152 + .../golang.org/x/net/ipv6/zsys_linux_amd64.go | 154 + .../golang.org/x/net/ipv6/zsys_linux_arm.go | 152 + .../golang.org/x/net/ipv6/zsys_linux_arm64.go | 154 + .../golang.org/x/net/ipv6/zsys_linux_mips.go | 152 + .../x/net/ipv6/zsys_linux_mips64.go | 154 + .../x/net/ipv6/zsys_linux_mips64le.go | 154 + .../x/net/ipv6/zsys_linux_mipsle.go | 152 + .../golang.org/x/net/ipv6/zsys_linux_ppc.go | 152 + .../golang.org/x/net/ipv6/zsys_linux_ppc64.go | 154 + .../x/net/ipv6/zsys_linux_ppc64le.go | 154 + .../x/net/ipv6/zsys_linux_riscv64.go | 156 + .../golang.org/x/net/ipv6/zsys_linux_s390x.go | 154 + vendor/golang.org/x/net/ipv6/zsys_netbsd.go | 84 + vendor/golang.org/x/net/ipv6/zsys_openbsd.go | 93 + vendor/golang.org/x/net/ipv6/zsys_solaris.go | 131 + vendor/golang.org/x/net/proxy/dial.go | 54 + vendor/golang.org/x/net/proxy/direct.go | 15 +- vendor/golang.org/x/net/proxy/per_host.go | 15 + vendor/golang.org/x/net/proxy/proxy.go | 24 +- vendor/golang.org/x/net/proxy/socks5.go | 10 +- vendor/golang.org/x/sys/AUTHORS | 3 + vendor/golang.org/x/sys/CONTRIBUTORS | 3 + vendor/golang.org/x/sys/LICENSE | 27 + vendor/golang.org/x/sys/PATENTS | 22 + vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s | 17 + vendor/golang.org/x/sys/cpu/byteorder.go | 60 + vendor/golang.org/x/sys/cpu/cpu.go | 171 + vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go | 34 + vendor/golang.org/x/sys/cpu/cpu_arm.go | 40 + vendor/golang.org/x/sys/cpu/cpu_arm64.go | 138 + vendor/golang.org/x/sys/cpu/cpu_arm64.s | 31 + vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go | 11 + vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go | 21 + vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 16 + .../golang.org/x/sys/cpu/cpu_gccgo_arm64.go | 11 + .../golang.org/x/sys/cpu/cpu_gccgo_s390x.go | 22 + vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c | 43 + vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go | 26 + vendor/golang.org/x/sys/cpu/cpu_linux.go | 15 + vendor/golang.org/x/sys/cpu/cpu_linux_arm.go | 39 + .../golang.org/x/sys/cpu/cpu_linux_arm64.go | 71 + .../golang.org/x/sys/cpu/cpu_linux_mips64x.go | 22 + .../golang.org/x/sys/cpu/cpu_linux_noinit.go | 9 + .../golang.org/x/sys/cpu/cpu_linux_ppc64x.go | 33 + .../golang.org/x/sys/cpu/cpu_linux_s390x.go | 161 + vendor/golang.org/x/sys/cpu/cpu_mips64x.go | 9 + vendor/golang.org/x/sys/cpu/cpu_mipsx.go | 9 + .../golang.org/x/sys/cpu/cpu_other_arm64.go | 9 + vendor/golang.org/x/sys/cpu/cpu_riscv64.go | 9 + vendor/golang.org/x/sys/cpu/cpu_s390x.s | 57 + vendor/golang.org/x/sys/cpu/cpu_wasm.go | 13 + vendor/golang.org/x/sys/cpu/cpu_x86.go | 59 + vendor/golang.org/x/sys/cpu/cpu_x86.s | 27 + vendor/golang.org/x/sys/cpu/hwcap_linux.go | 56 + .../x/sys/cpu/syscall_aix_ppc64_gc.go | 36 + vendor/golang.org/x/sys/unix/.gitignore | 2 + vendor/golang.org/x/sys/unix/README.md | 184 + .../golang.org/x/sys/unix/affinity_linux.go | 86 + vendor/golang.org/x/sys/unix/aliases.go | 14 + vendor/golang.org/x/sys/unix/asm_aix_ppc64.s | 17 + vendor/golang.org/x/sys/unix/asm_darwin_386.s | 29 + .../golang.org/x/sys/unix/asm_darwin_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_darwin_arm.s | 30 + .../golang.org/x/sys/unix/asm_darwin_arm64.s | 30 + .../x/sys/unix/asm_dragonfly_amd64.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_386.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_amd64.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_arm.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_arm64.s | 29 + vendor/golang.org/x/sys/unix/asm_linux_386.s | 65 + .../golang.org/x/sys/unix/asm_linux_amd64.s | 57 + vendor/golang.org/x/sys/unix/asm_linux_arm.s | 56 + .../golang.org/x/sys/unix/asm_linux_arm64.s | 52 + .../golang.org/x/sys/unix/asm_linux_mips64x.s | 56 + .../golang.org/x/sys/unix/asm_linux_mipsx.s | 54 + .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 44 + .../golang.org/x/sys/unix/asm_linux_riscv64.s | 47 + .../golang.org/x/sys/unix/asm_linux_s390x.s | 56 + vendor/golang.org/x/sys/unix/asm_netbsd_386.s | 29 + .../golang.org/x/sys/unix/asm_netbsd_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_netbsd_arm.s | 29 + .../golang.org/x/sys/unix/asm_netbsd_arm64.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_386.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_amd64.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_arm.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_arm64.s | 29 + .../golang.org/x/sys/unix/asm_solaris_amd64.s | 17 + .../golang.org/x/sys/unix/bluetooth_linux.go | 36 + vendor/golang.org/x/sys/unix/cap_freebsd.go | 195 + vendor/golang.org/x/sys/unix/constants.go | 13 + vendor/golang.org/x/sys/unix/dev_aix_ppc.go | 27 + vendor/golang.org/x/sys/unix/dev_aix_ppc64.go | 29 + vendor/golang.org/x/sys/unix/dev_darwin.go | 24 + vendor/golang.org/x/sys/unix/dev_dragonfly.go | 30 + vendor/golang.org/x/sys/unix/dev_freebsd.go | 30 + vendor/golang.org/x/sys/unix/dev_linux.go | 42 + vendor/golang.org/x/sys/unix/dev_netbsd.go | 29 + vendor/golang.org/x/sys/unix/dev_openbsd.go | 29 + vendor/golang.org/x/sys/unix/dirent.go | 102 + vendor/golang.org/x/sys/unix/endian_big.go | 9 + vendor/golang.org/x/sys/unix/endian_little.go | 9 + vendor/golang.org/x/sys/unix/env_unix.go | 31 + .../x/sys/unix/errors_freebsd_386.go | 233 + .../x/sys/unix/errors_freebsd_amd64.go | 233 + .../x/sys/unix/errors_freebsd_arm.go | 226 + .../x/sys/unix/errors_freebsd_arm64.go | 17 + vendor/golang.org/x/sys/unix/fcntl.go | 36 + vendor/golang.org/x/sys/unix/fcntl_darwin.go | 18 + .../x/sys/unix/fcntl_linux_32bit.go | 13 + vendor/golang.org/x/sys/unix/fdset.go | 29 + vendor/golang.org/x/sys/unix/gccgo.go | 62 + vendor/golang.org/x/sys/unix/gccgo_c.c | 39 + .../x/sys/unix/gccgo_linux_amd64.go | 20 + vendor/golang.org/x/sys/unix/ioctl.go | 65 + vendor/golang.org/x/sys/unix/mkall.sh | 240 + vendor/golang.org/x/sys/unix/mkerrors.sh | 702 ++ vendor/golang.org/x/sys/unix/pagesize_unix.go | 15 + .../golang.org/x/sys/unix/pledge_openbsd.go | 163 + vendor/golang.org/x/sys/unix/race.go | 30 + vendor/golang.org/x/sys/unix/race0.go | 25 + .../x/sys/unix/readdirent_getdents.go | 12 + .../x/sys/unix/readdirent_getdirentries.go | 19 + .../x/sys/unix/sockcmsg_dragonfly.go | 16 + .../golang.org/x/sys/unix/sockcmsg_linux.go | 36 + vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 92 + .../x/sys/unix/sockcmsg_unix_other.go | 38 + vendor/golang.org/x/sys/unix/str.go | 26 + vendor/golang.org/x/sys/unix/syscall.go | 53 + vendor/golang.org/x/sys/unix/syscall_aix.go | 536 ++ .../golang.org/x/sys/unix/syscall_aix_ppc.go | 54 + .../x/sys/unix/syscall_aix_ppc64.go | 85 + vendor/golang.org/x/sys/unix/syscall_bsd.go | 631 ++ .../x/sys/unix/syscall_darwin.1_12.go | 29 + .../x/sys/unix/syscall_darwin.1_13.go | 101 + .../golang.org/x/sys/unix/syscall_darwin.go | 667 ++ .../x/sys/unix/syscall_darwin_386.1_11.go | 9 + .../x/sys/unix/syscall_darwin_386.go | 68 + .../x/sys/unix/syscall_darwin_amd64.1_11.go | 9 + .../x/sys/unix/syscall_darwin_amd64.go | 68 + .../x/sys/unix/syscall_darwin_arm.1_11.go | 11 + .../x/sys/unix/syscall_darwin_arm.go | 68 + .../x/sys/unix/syscall_darwin_arm64.1_11.go | 11 + .../x/sys/unix/syscall_darwin_arm64.go | 70 + .../x/sys/unix/syscall_darwin_libSystem.go | 33 + .../x/sys/unix/syscall_dragonfly.go | 539 ++ .../x/sys/unix/syscall_dragonfly_amd64.go | 56 + .../golang.org/x/sys/unix/syscall_freebsd.go | 874 +++ .../x/sys/unix/syscall_freebsd_386.go | 66 + .../x/sys/unix/syscall_freebsd_amd64.go | 66 + .../x/sys/unix/syscall_freebsd_arm.go | 62 + .../x/sys/unix/syscall_freebsd_arm64.go | 62 + .../golang.org/x/sys/unix/syscall_illumos.go | 57 + vendor/golang.org/x/sys/unix/syscall_linux.go | 2191 ++++++ .../x/sys/unix/syscall_linux_386.go | 390 + .../x/sys/unix/syscall_linux_amd64.go | 194 + .../x/sys/unix/syscall_linux_amd64_gc.go | 13 + .../x/sys/unix/syscall_linux_arm.go | 291 + .../x/sys/unix/syscall_linux_arm64.go | 227 + .../golang.org/x/sys/unix/syscall_linux_gc.go | 14 + .../x/sys/unix/syscall_linux_gc_386.go | 16 + .../x/sys/unix/syscall_linux_gccgo_386.go | 30 + .../x/sys/unix/syscall_linux_gccgo_arm.go | 20 + .../x/sys/unix/syscall_linux_mips64x.go | 230 + .../x/sys/unix/syscall_linux_mipsx.go | 238 + .../x/sys/unix/syscall_linux_ppc64x.go | 156 + .../x/sys/unix/syscall_linux_riscv64.go | 230 + .../x/sys/unix/syscall_linux_s390x.go | 342 + .../x/sys/unix/syscall_linux_sparc64.go | 151 + .../golang.org/x/sys/unix/syscall_netbsd.go | 614 ++ .../x/sys/unix/syscall_netbsd_386.go | 37 + .../x/sys/unix/syscall_netbsd_amd64.go | 37 + .../x/sys/unix/syscall_netbsd_arm.go | 37 + .../x/sys/unix/syscall_netbsd_arm64.go | 37 + .../golang.org/x/sys/unix/syscall_openbsd.go | 401 + .../x/sys/unix/syscall_openbsd_386.go | 41 + .../x/sys/unix/syscall_openbsd_amd64.go | 41 + .../x/sys/unix/syscall_openbsd_arm.go | 41 + .../x/sys/unix/syscall_openbsd_arm64.go | 41 + .../golang.org/x/sys/unix/syscall_solaris.go | 724 ++ .../x/sys/unix/syscall_solaris_amd64.go | 27 + vendor/golang.org/x/sys/unix/syscall_unix.go | 431 ++ .../golang.org/x/sys/unix/syscall_unix_gc.go | 15 + .../x/sys/unix/syscall_unix_gc_ppc64x.go | 24 + vendor/golang.org/x/sys/unix/timestruct.go | 82 + .../golang.org/x/sys/unix/unveil_openbsd.go | 42 + vendor/golang.org/x/sys/unix/xattr_bsd.go | 240 + .../golang.org/x/sys/unix/zerrors_aix_ppc.go | 1384 ++++ .../x/sys/unix/zerrors_aix_ppc64.go | 1385 ++++ .../x/sys/unix/zerrors_darwin_386.go | 1784 +++++ .../x/sys/unix/zerrors_darwin_amd64.go | 1784 +++++ .../x/sys/unix/zerrors_darwin_arm.go | 1784 +++++ .../x/sys/unix/zerrors_darwin_arm64.go | 1784 +++++ .../x/sys/unix/zerrors_dragonfly_amd64.go | 1651 ++++ .../x/sys/unix/zerrors_freebsd_386.go | 1930 +++++ .../x/sys/unix/zerrors_freebsd_amd64.go | 1929 +++++ .../x/sys/unix/zerrors_freebsd_arm.go | 1819 +++++ .../x/sys/unix/zerrors_freebsd_arm64.go | 1930 +++++ vendor/golang.org/x/sys/unix/zerrors_linux.go | 2469 ++++++ .../x/sys/unix/zerrors_linux_386.go | 784 ++ .../x/sys/unix/zerrors_linux_amd64.go | 784 ++ .../x/sys/unix/zerrors_linux_arm.go | 790 ++ .../x/sys/unix/zerrors_linux_arm64.go | 777 ++ .../x/sys/unix/zerrors_linux_mips.go | 791 ++ .../x/sys/unix/zerrors_linux_mips64.go | 791 ++ .../x/sys/unix/zerrors_linux_mips64le.go | 791 ++ .../x/sys/unix/zerrors_linux_mipsle.go | 791 ++ .../x/sys/unix/zerrors_linux_ppc64.go | 847 ++ .../x/sys/unix/zerrors_linux_ppc64le.go | 847 ++ .../x/sys/unix/zerrors_linux_riscv64.go | 771 ++ .../x/sys/unix/zerrors_linux_s390x.go | 844 ++ .../x/sys/unix/zerrors_linux_sparc64.go | 841 ++ .../x/sys/unix/zerrors_netbsd_386.go | 1773 +++++ .../x/sys/unix/zerrors_netbsd_amd64.go | 1763 +++++ .../x/sys/unix/zerrors_netbsd_arm.go | 1752 +++++ .../x/sys/unix/zerrors_netbsd_arm64.go | 1763 +++++ .../x/sys/unix/zerrors_openbsd_386.go | 1657 ++++ .../x/sys/unix/zerrors_openbsd_amd64.go | 1767 +++++ .../x/sys/unix/zerrors_openbsd_arm.go | 1659 ++++ .../x/sys/unix/zerrors_openbsd_arm64.go | 1790 +++++ .../x/sys/unix/zerrors_solaris_amd64.go | 1533 ++++ .../x/sys/unix/zptrace_armnn_linux.go | 41 + .../x/sys/unix/zptrace_linux_arm64.go | 17 + .../x/sys/unix/zptrace_mipsnn_linux.go | 50 + .../x/sys/unix/zptrace_mipsnnle_linux.go | 50 + .../x/sys/unix/zptrace_x86_linux.go | 80 + .../golang.org/x/sys/unix/zsyscall_aix_ppc.go | 1484 ++++ .../x/sys/unix/zsyscall_aix_ppc64.go | 1442 ++++ .../x/sys/unix/zsyscall_aix_ppc64_gc.go | 1192 +++ .../x/sys/unix/zsyscall_aix_ppc64_gccgo.go | 1070 +++ .../x/sys/unix/zsyscall_darwin_386.1_11.go | 1811 +++++ .../x/sys/unix/zsyscall_darwin_386.1_13.go | 41 + .../x/sys/unix/zsyscall_darwin_386.1_13.s | 12 + .../x/sys/unix/zsyscall_darwin_386.go | 2499 ++++++ .../x/sys/unix/zsyscall_darwin_386.s | 284 + .../x/sys/unix/zsyscall_darwin_amd64.1_11.go | 1811 +++++ .../x/sys/unix/zsyscall_darwin_amd64.1_13.go | 41 + .../x/sys/unix/zsyscall_darwin_amd64.1_13.s | 12 + .../x/sys/unix/zsyscall_darwin_amd64.go | 2499 ++++++ .../x/sys/unix/zsyscall_darwin_amd64.s | 284 + .../x/sys/unix/zsyscall_darwin_arm.1_11.go | 1784 +++++ .../x/sys/unix/zsyscall_darwin_arm.1_13.go | 41 + .../x/sys/unix/zsyscall_darwin_arm.1_13.s | 12 + .../x/sys/unix/zsyscall_darwin_arm.go | 2484 ++++++ .../x/sys/unix/zsyscall_darwin_arm.s | 282 + .../x/sys/unix/zsyscall_darwin_arm64.1_11.go | 1784 +++++ .../x/sys/unix/zsyscall_darwin_arm64.1_13.go | 41 + .../x/sys/unix/zsyscall_darwin_arm64.1_13.s | 12 + .../x/sys/unix/zsyscall_darwin_arm64.go | 2484 ++++++ .../x/sys/unix/zsyscall_darwin_arm64.s | 282 + .../x/sys/unix/zsyscall_dragonfly_amd64.go | 1666 ++++ .../x/sys/unix/zsyscall_freebsd_386.go | 2015 +++++ .../x/sys/unix/zsyscall_freebsd_amd64.go | 2015 +++++ .../x/sys/unix/zsyscall_freebsd_arm.go | 2015 +++++ .../x/sys/unix/zsyscall_freebsd_arm64.go | 2015 +++++ .../x/sys/unix/zsyscall_illumos_amd64.go | 87 + .../golang.org/x/sys/unix/zsyscall_linux.go | 1825 +++++ .../x/sys/unix/zsyscall_linux_386.go | 578 ++ .../x/sys/unix/zsyscall_linux_amd64.go | 745 ++ .../x/sys/unix/zsyscall_linux_arm.go | 715 ++ .../x/sys/unix/zsyscall_linux_arm64.go | 602 ++ .../x/sys/unix/zsyscall_linux_mips.go | 758 ++ .../x/sys/unix/zsyscall_linux_mips64.go | 729 ++ .../x/sys/unix/zsyscall_linux_mips64le.go | 729 ++ .../x/sys/unix/zsyscall_linux_mipsle.go | 758 ++ .../x/sys/unix/zsyscall_linux_ppc64.go | 807 ++ .../x/sys/unix/zsyscall_linux_ppc64le.go | 807 ++ .../x/sys/unix/zsyscall_linux_riscv64.go | 582 ++ .../x/sys/unix/zsyscall_linux_s390x.go | 577 ++ .../x/sys/unix/zsyscall_linux_sparc64.go | 740 ++ .../x/sys/unix/zsyscall_netbsd_386.go | 1851 +++++ .../x/sys/unix/zsyscall_netbsd_amd64.go | 1851 +++++ .../x/sys/unix/zsyscall_netbsd_arm.go | 1851 +++++ .../x/sys/unix/zsyscall_netbsd_arm64.go | 1851 +++++ .../x/sys/unix/zsyscall_openbsd_386.go | 1692 ++++ .../x/sys/unix/zsyscall_openbsd_amd64.go | 1692 ++++ .../x/sys/unix/zsyscall_openbsd_arm.go | 1692 ++++ .../x/sys/unix/zsyscall_openbsd_arm64.go | 1692 ++++ .../x/sys/unix/zsyscall_solaris_amd64.go | 1954 +++++ .../x/sys/unix/zsysctl_openbsd_386.go | 272 + .../x/sys/unix/zsysctl_openbsd_amd64.go | 270 + .../x/sys/unix/zsysctl_openbsd_arm.go | 272 + .../x/sys/unix/zsysctl_openbsd_arm64.go | 275 + .../x/sys/unix/zsysnum_darwin_386.go | 436 ++ .../x/sys/unix/zsysnum_darwin_amd64.go | 438 ++ .../x/sys/unix/zsysnum_darwin_arm.go | 436 ++ .../x/sys/unix/zsysnum_darwin_arm64.go | 436 ++ .../x/sys/unix/zsysnum_dragonfly_amd64.go | 315 + .../x/sys/unix/zsysnum_freebsd_386.go | 396 + .../x/sys/unix/zsysnum_freebsd_amd64.go | 396 + .../x/sys/unix/zsysnum_freebsd_arm.go | 396 + .../x/sys/unix/zsysnum_freebsd_arm64.go | 396 + .../x/sys/unix/zsysnum_linux_386.go | 436 ++ .../x/sys/unix/zsysnum_linux_amd64.go | 358 + .../x/sys/unix/zsysnum_linux_arm.go | 400 + .../x/sys/unix/zsysnum_linux_arm64.go | 303 + .../x/sys/unix/zsysnum_linux_mips.go | 421 + .../x/sys/unix/zsysnum_linux_mips64.go | 351 + .../x/sys/unix/zsysnum_linux_mips64le.go | 351 + .../x/sys/unix/zsysnum_linux_mipsle.go | 421 + .../x/sys/unix/zsysnum_linux_ppc64.go | 400 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 400 + .../x/sys/unix/zsysnum_linux_riscv64.go | 302 + .../x/sys/unix/zsysnum_linux_s390x.go | 365 + .../x/sys/unix/zsysnum_linux_sparc64.go | 379 + .../x/sys/unix/zsysnum_netbsd_386.go | 274 + .../x/sys/unix/zsysnum_netbsd_amd64.go | 274 + .../x/sys/unix/zsysnum_netbsd_arm.go | 274 + .../x/sys/unix/zsysnum_netbsd_arm64.go | 274 + .../x/sys/unix/zsysnum_openbsd_386.go | 218 + .../x/sys/unix/zsysnum_openbsd_amd64.go | 218 + .../x/sys/unix/zsysnum_openbsd_arm.go | 218 + .../x/sys/unix/zsysnum_openbsd_arm64.go | 217 + .../golang.org/x/sys/unix/ztypes_aix_ppc.go | 352 + .../golang.org/x/sys/unix/ztypes_aix_ppc64.go | 356 + .../x/sys/unix/ztypes_darwin_386.go | 499 ++ .../x/sys/unix/ztypes_darwin_amd64.go | 509 ++ .../x/sys/unix/ztypes_darwin_arm.go | 500 ++ .../x/sys/unix/ztypes_darwin_arm64.go | 509 ++ .../x/sys/unix/ztypes_dragonfly_amd64.go | 479 ++ .../x/sys/unix/ztypes_freebsd_386.go | 709 ++ .../x/sys/unix/ztypes_freebsd_amd64.go | 712 ++ .../x/sys/unix/ztypes_freebsd_arm.go | 693 ++ .../x/sys/unix/ztypes_freebsd_arm64.go | 690 ++ vendor/golang.org/x/sys/unix/ztypes_linux.go | 2340 ++++++ .../golang.org/x/sys/unix/ztypes_linux_386.go | 599 ++ .../x/sys/unix/ztypes_linux_amd64.go | 614 ++ .../golang.org/x/sys/unix/ztypes_linux_arm.go | 591 ++ .../x/sys/unix/ztypes_linux_arm64.go | 593 ++ .../x/sys/unix/ztypes_linux_mips.go | 597 ++ .../x/sys/unix/ztypes_linux_mips64.go | 596 ++ .../x/sys/unix/ztypes_linux_mips64le.go | 596 ++ .../x/sys/unix/ztypes_linux_mipsle.go | 597 ++ .../x/sys/unix/ztypes_linux_ppc64.go | 603 ++ .../x/sys/unix/ztypes_linux_ppc64le.go | 603 ++ .../x/sys/unix/ztypes_linux_riscv64.go | 621 ++ .../x/sys/unix/ztypes_linux_s390x.go | 617 ++ .../x/sys/unix/ztypes_linux_sparc64.go | 598 ++ .../x/sys/unix/ztypes_netbsd_386.go | 498 ++ .../x/sys/unix/ztypes_netbsd_amd64.go | 506 ++ .../x/sys/unix/ztypes_netbsd_arm.go | 503 ++ .../x/sys/unix/ztypes_netbsd_arm64.go | 506 ++ .../x/sys/unix/ztypes_openbsd_386.go | 571 ++ .../x/sys/unix/ztypes_openbsd_amd64.go | 571 ++ .../x/sys/unix/ztypes_openbsd_arm.go | 572 ++ .../x/sys/unix/ztypes_openbsd_arm64.go | 565 ++ .../x/sys/unix/ztypes_solaris_amd64.go | 449 ++ vendor/golang.org/x/sys/windows/aliases.go | 13 + .../golang.org/x/sys/windows/dll_windows.go | 386 + vendor/golang.org/x/sys/windows/empty.s | 8 + .../golang.org/x/sys/windows/env_windows.go | 61 + vendor/golang.org/x/sys/windows/eventlog.go | 20 + .../golang.org/x/sys/windows/exec_windows.go | 97 + .../x/sys/windows/memory_windows.go | 26 + vendor/golang.org/x/sys/windows/mkerrors.bash | 63 + .../x/sys/windows/mkknownfolderids.bash | 27 + vendor/golang.org/x/sys/windows/mksyscall.go | 9 + vendor/golang.org/x/sys/windows/race.go | 30 + vendor/golang.org/x/sys/windows/race0.go | 25 + .../x/sys/windows/security_windows.go | 1396 ++++ vendor/golang.org/x/sys/windows/service.go | 229 + vendor/golang.org/x/sys/windows/str.go | 22 + vendor/golang.org/x/sys/windows/syscall.go | 74 + .../x/sys/windows/syscall_windows.go | 1454 ++++ .../golang.org/x/sys/windows/types_windows.go | 1786 +++++ .../x/sys/windows/types_windows_386.go | 22 + .../x/sys/windows/types_windows_amd64.go | 22 + .../x/sys/windows/types_windows_arm.go | 22 + .../x/sys/windows/zerrors_windows.go | 6853 +++++++++++++++++ .../x/sys/windows/zknownfolderids_windows.go | 149 + .../x/sys/windows/zsyscall_windows.go | 4051 ++++++++++ vendor/google.golang.org/protobuf/AUTHORS | 3 + .../google.golang.org/protobuf/CONTRIBUTORS | 3 + vendor/google.golang.org/protobuf/LICENSE | 27 + vendor/google.golang.org/protobuf/PATENTS | 22 + .../protobuf/encoding/prototext/decode.go | 791 ++ .../protobuf/encoding/prototext/doc.go | 7 + .../protobuf/encoding/prototext/encode.go | 433 ++ .../protobuf/encoding/protowire/wire.go | 538 ++ .../protobuf/internal/descfmt/stringer.go | 316 + .../protobuf/internal/descopts/options.go | 29 + .../protobuf/internal/detrand/rand.go | 61 + .../internal/encoding/defval/default.go | 213 + .../encoding/messageset/messageset.go | 258 + .../protobuf/internal/encoding/tag/tag.go | 207 + .../protobuf/internal/encoding/text/decode.go | 665 ++ .../internal/encoding/text/decode_number.go | 190 + .../internal/encoding/text/decode_string.go | 161 + .../internal/encoding/text/decode_token.go | 373 + .../protobuf/internal/encoding/text/doc.go | 29 + .../protobuf/internal/encoding/text/encode.go | 267 + .../protobuf/internal/errors/errors.go | 89 + .../protobuf/internal/errors/is_go112.go | 39 + .../protobuf/internal/errors/is_go113.go | 12 + .../protobuf/internal/fieldsort/fieldsort.go | 40 + .../protobuf/internal/filedesc/build.go | 155 + .../protobuf/internal/filedesc/desc.go | 614 ++ .../protobuf/internal/filedesc/desc_init.go | 471 ++ .../protobuf/internal/filedesc/desc_lazy.go | 704 ++ .../protobuf/internal/filedesc/desc_list.go | 282 + .../internal/filedesc/desc_list_gen.go | 345 + .../protobuf/internal/filedesc/placeholder.go | 107 + .../protobuf/internal/filetype/build.go | 297 + .../protobuf/internal/flags/flags.go | 24 + .../internal/flags/proto_legacy_disable.go | 9 + .../internal/flags/proto_legacy_enable.go | 9 + .../protobuf/internal/genid/any_gen.go | 34 + .../protobuf/internal/genid/api_gen.go | 106 + .../protobuf/internal/genid/descriptor_gen.go | 829 ++ .../protobuf/internal/genid/doc.go | 11 + .../protobuf/internal/genid/duration_gen.go | 34 + .../protobuf/internal/genid/empty_gen.go | 19 + .../protobuf/internal/genid/field_mask_gen.go | 31 + .../protobuf/internal/genid/goname.go | 25 + .../protobuf/internal/genid/map_entry.go | 16 + .../internal/genid/source_context_gen.go | 31 + .../protobuf/internal/genid/struct_gen.go | 116 + .../protobuf/internal/genid/timestamp_gen.go | 34 + .../protobuf/internal/genid/type_gen.go | 184 + .../protobuf/internal/genid/wrappers.go | 13 + .../protobuf/internal/genid/wrappers_gen.go | 175 + .../protobuf/internal/impl/api_export.go | 177 + .../protobuf/internal/impl/checkinit.go | 141 + .../protobuf/internal/impl/codec_extension.go | 223 + .../protobuf/internal/impl/codec_field.go | 828 ++ .../protobuf/internal/impl/codec_gen.go | 5637 ++++++++++++++ .../protobuf/internal/impl/codec_map.go | 389 + .../protobuf/internal/impl/codec_map_go111.go | 37 + .../protobuf/internal/impl/codec_map_go112.go | 11 + .../protobuf/internal/impl/codec_message.go | 159 + .../internal/impl/codec_messageset.go | 120 + .../protobuf/internal/impl/codec_reflect.go | 209 + .../protobuf/internal/impl/codec_tables.go | 557 ++ .../protobuf/internal/impl/codec_unsafe.go | 17 + .../protobuf/internal/impl/convert.go | 467 ++ .../protobuf/internal/impl/convert_list.go | 141 + .../protobuf/internal/impl/convert_map.go | 121 + .../protobuf/internal/impl/decode.go | 274 + .../protobuf/internal/impl/encode.go | 199 + .../protobuf/internal/impl/enum.go | 21 + .../protobuf/internal/impl/extension.go | 156 + .../protobuf/internal/impl/legacy_enum.go | 219 + .../protobuf/internal/impl/legacy_export.go | 92 + .../internal/impl/legacy_extension.go | 175 + .../protobuf/internal/impl/legacy_file.go | 81 + .../protobuf/internal/impl/legacy_message.go | 502 ++ .../protobuf/internal/impl/merge.go | 176 + .../protobuf/internal/impl/merge_gen.go | 209 + .../protobuf/internal/impl/message.go | 215 + .../protobuf/internal/impl/message_reflect.go | 364 + .../internal/impl/message_reflect_field.go | 466 ++ .../internal/impl/message_reflect_gen.go | 249 + .../protobuf/internal/impl/pointer_reflect.go | 177 + .../protobuf/internal/impl/pointer_unsafe.go | 173 + .../protobuf/internal/impl/validate.go | 576 ++ .../protobuf/internal/impl/weak.go | 74 + .../protobuf/internal/mapsort/mapsort.go | 43 + .../protobuf/internal/pragma/pragma.go | 29 + .../protobuf/internal/set/ints.go | 58 + .../protobuf/internal/strs/strings.go | 196 + .../protobuf/internal/strs/strings_pure.go | 27 + .../protobuf/internal/strs/strings_unsafe.go | 94 + .../protobuf/internal/version/version.go | 79 + .../protobuf/proto/checkinit.go | 71 + .../protobuf/proto/decode.go | 274 + .../protobuf/proto/decode_gen.go | 603 ++ .../google.golang.org/protobuf/proto/doc.go | 94 + .../protobuf/proto/encode.go | 346 + .../protobuf/proto/encode_gen.go | 97 + .../google.golang.org/protobuf/proto/equal.go | 154 + .../protobuf/proto/extension.go | 92 + .../google.golang.org/protobuf/proto/merge.go | 139 + .../protobuf/proto/messageset.go | 88 + .../google.golang.org/protobuf/proto/proto.go | 34 + .../protobuf/proto/proto_methods.go | 19 + .../protobuf/proto/proto_reflect.go | 19 + .../google.golang.org/protobuf/proto/reset.go | 43 + .../google.golang.org/protobuf/proto/size.go | 97 + .../protobuf/proto/size_gen.go | 55 + .../protobuf/proto/wrappers.go | 29 + .../protobuf/reflect/protoreflect/methods.go | 77 + .../protobuf/reflect/protoreflect/proto.go | 504 ++ .../protobuf/reflect/protoreflect/source.go | 52 + .../protobuf/reflect/protoreflect/type.go | 631 ++ .../protobuf/reflect/protoreflect/value.go | 285 + .../reflect/protoreflect/value_pure.go | 59 + .../reflect/protoreflect/value_union.go | 411 + .../reflect/protoreflect/value_unsafe.go | 98 + .../reflect/protoregistry/registry.go | 800 ++ .../protobuf/runtime/protoiface/legacy.go | 15 + .../protobuf/runtime/protoiface/methods.go | 167 + .../protobuf/runtime/protoimpl/impl.go | 44 + .../protobuf/runtime/protoimpl/version.go | 56 + vendor/modules.txt | 132 +- 1167 files changed, 324077 insertions(+), 18203 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 ek_html.go create mode 100644 emergency_kit.go create mode 100644 encrypt.go create mode 100644 encrypt_test.go create mode 100644 hdpublickey_test.go create mode 100644 publickey.go create mode 100644 vendor/github.com/aead/siphash/.gitignore create mode 100644 vendor/github.com/aead/siphash/.travis.yml create mode 100644 vendor/github.com/aead/siphash/LICENSE create mode 100644 vendor/github.com/aead/siphash/README.md create mode 100644 vendor/github.com/aead/siphash/siphash.go create mode 100644 vendor/github.com/aead/siphash/siphash128.go create mode 100644 vendor/github.com/aead/siphash/siphash_386.go create mode 100644 vendor/github.com/aead/siphash/siphash_386.s create mode 100644 vendor/github.com/aead/siphash/siphash_amd64.go create mode 100644 vendor/github.com/aead/siphash/siphash_amd64.s create mode 100644 vendor/github.com/aead/siphash/siphash_generic.go create mode 100644 vendor/github.com/aead/siphash/siphash_ref.go create mode 100644 vendor/github.com/btcsuite/btcd/addrmgr/addrmanager.go create mode 100644 vendor/github.com/btcsuite/btcd/addrmgr/cov_report.sh create mode 100644 vendor/github.com/btcsuite/btcd/addrmgr/doc.go create mode 100644 vendor/github.com/btcsuite/btcd/addrmgr/knownaddress.go create mode 100644 vendor/github.com/btcsuite/btcd/addrmgr/log.go create mode 100644 vendor/github.com/btcsuite/btcd/addrmgr/network.go create mode 100644 vendor/github.com/btcsuite/btcd/addrmgr/test_coverage.txt create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/README.md create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/accept.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/blockindex.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/chain.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/chainio.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/chainview.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/checkpoints.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/compress.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/difficulty.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/doc.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/error.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/log.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/mediantime.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/merkle.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/notifications.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/process.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/scriptval.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/thresholdstate.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/timesorter.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/upgrade.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/utxoviewpoint.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/validate.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/versionbits.go create mode 100644 vendor/github.com/btcsuite/btcd/blockchain/weight.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/CONTRIBUTORS create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/README.md create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/btcdextcmds.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/btcdextresults.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/btcwalletextcmds.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/chainsvrcmds.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/chainsvrresults.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/chainsvrwscmds.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/chainsvrwsntfns.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/chainsvrwsresults.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/cmdinfo.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/cmdparse.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/doc.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/error.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/help.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/helpers.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/jsonrpc.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/jsonrpcerr.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/register.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/walletsvrcmds.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/walletsvrresults.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/walletsvrwscmds.go create mode 100644 vendor/github.com/btcsuite/btcd/btcjson/walletsvrwsntfns.go create mode 100644 vendor/github.com/btcsuite/btcd/database/README.md create mode 100644 vendor/github.com/btcsuite/btcd/database/doc.go create mode 100644 vendor/github.com/btcsuite/btcd/database/driver.go create mode 100644 vendor/github.com/btcsuite/btcd/database/error.go create mode 100644 vendor/github.com/btcsuite/btcd/database/interface.go create mode 100644 vendor/github.com/btcsuite/btcd/database/log.go create mode 100644 vendor/github.com/btcsuite/btcd/peer/README.md create mode 100644 vendor/github.com/btcsuite/btcd/peer/doc.go create mode 100644 vendor/github.com/btcsuite/btcd/peer/log.go create mode 100644 vendor/github.com/btcsuite/btcd/peer/mruinvmap.go create mode 100644 vendor/github.com/btcsuite/btcd/peer/mrunoncemap.go create mode 100644 vendor/github.com/btcsuite/btcd/peer/peer.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/CONTRIBUTORS create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/README.md create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/chain.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/doc.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/extensions.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/infrastructure.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/log.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/mining.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/net.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/notify.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/rawrequest.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/rawtransactions.go create mode 100644 vendor/github.com/btcsuite/btcd/rpcclient/wallet.go create mode 100644 vendor/github.com/btcsuite/btcutil/gcs/README.md create mode 100644 vendor/github.com/btcsuite/btcutil/gcs/builder/builder.go create mode 100644 vendor/github.com/btcsuite/btcutil/gcs/doc.go create mode 100644 vendor/github.com/btcsuite/btcutil/gcs/gcs.go create mode 100644 vendor/github.com/btcsuite/btcutil/go.mod create mode 100644 vendor/github.com/btcsuite/btcutil/go.sum create mode 100644 vendor/github.com/btcsuite/btcwallet/LICENSE create mode 100644 vendor/github.com/btcsuite/btcwallet/chain/bitcoind_client.go create mode 100644 vendor/github.com/btcsuite/btcwallet/chain/bitcoind_conn.go create mode 100644 vendor/github.com/btcsuite/btcwallet/chain/block_filterer.go create mode 100644 vendor/github.com/btcsuite/btcwallet/chain/interface.go create mode 100644 vendor/github.com/btcsuite/btcwallet/chain/log.go create mode 100644 vendor/github.com/btcsuite/btcwallet/chain/neutrino.go create mode 100644 vendor/github.com/btcsuite/btcwallet/chain/queue.go create mode 100644 vendor/github.com/btcsuite/btcwallet/chain/rpc.go create mode 100644 vendor/github.com/btcsuite/btcwallet/internal/legacy/keystore/keystore.go create mode 100644 vendor/github.com/btcsuite/btcwallet/internal/legacy/rename/rename_unix.go create mode 100644 vendor/github.com/btcsuite/btcwallet/internal/legacy/rename/rename_windows.go create mode 100644 vendor/github.com/btcsuite/btcwallet/internal/prompt/prompt.go create mode 100644 vendor/github.com/btcsuite/btcwallet/internal/zero/array.go create mode 100644 vendor/github.com/btcsuite/btcwallet/internal/zero/doc.go create mode 100644 vendor/github.com/btcsuite/btcwallet/internal/zero/slice.go create mode 100644 vendor/github.com/btcsuite/btcwallet/snacl/snacl.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/README.md create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/address.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/cov_report.sh create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/db.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/doc.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/error.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/log.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/manager.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/migrations.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/scoped_manager.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/sync.go create mode 100644 vendor/github.com/btcsuite/btcwallet/waddrmgr/test_coverage.txt create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/README.md create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/chainntfns.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/common.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/createtx.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/disksync.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/doc.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/loader.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/log.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/mock.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/multisig.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/notifications.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/recovery.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/rescan.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txauthor/LICENSE create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txauthor/author.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txauthor/cprng.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txauthor/go.mod create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txauthor/go.sum create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txrules/LICENSE create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txrules/go.mod create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txrules/go.sum create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txrules/rules.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txsizes/LICENSE create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txsizes/go.mod create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txsizes/go.sum create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/txsizes/size.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/unstable.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/utxos.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wallet/wallet.go create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/LICENSE create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/README.md create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/cov_report.sh create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/doc.go create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/error.go create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/go.mod create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/go.sum create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/interface.go create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/migration/log.go create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/migration/manager.go create mode 100644 vendor/github.com/btcsuite/btcwallet/walletdb/test_coverage.txt create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/LICENSE create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/README.md create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/db.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/doc.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/error.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/go.mod create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/go.sum create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/kahnsort.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/log.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/migrations.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/query.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/tx.go create mode 100644 vendor/github.com/btcsuite/btcwallet/wtxmgr/unconfirmed.go create mode 100644 vendor/github.com/btcsuite/go-socks/LICENSE create mode 100644 vendor/github.com/btcsuite/go-socks/socks/addr.go create mode 100644 vendor/github.com/btcsuite/go-socks/socks/conn.go create mode 100644 vendor/github.com/btcsuite/go-socks/socks/dial.go create mode 100644 vendor/github.com/btcsuite/websocket/.gitignore create mode 100644 vendor/github.com/btcsuite/websocket/.travis.yml create mode 100644 vendor/github.com/btcsuite/websocket/AUTHORS create mode 100644 vendor/github.com/btcsuite/websocket/LICENSE create mode 100644 vendor/github.com/btcsuite/websocket/README.md create mode 100644 vendor/github.com/btcsuite/websocket/client.go create mode 100644 vendor/github.com/btcsuite/websocket/conn.go create mode 100644 vendor/github.com/btcsuite/websocket/doc.go create mode 100644 vendor/github.com/btcsuite/websocket/json.go create mode 100644 vendor/github.com/btcsuite/websocket/server.go create mode 100644 vendor/github.com/btcsuite/websocket/util.go create mode 100644 vendor/github.com/go-errors/errors/error_1_13.go create mode 100644 vendor/github.com/go-errors/errors/error_backward.go create mode 100644 vendor/github.com/go-errors/errors/go.mod create mode 100644 vendor/github.com/golang/protobuf/proto/buffer.go delete mode 100644 vendor/github.com/golang/protobuf/proto/clone.go delete mode 100644 vendor/github.com/golang/protobuf/proto/decode.go create mode 100644 vendor/github.com/golang/protobuf/proto/defaults.go delete mode 100644 vendor/github.com/golang/protobuf/proto/encode.go delete mode 100644 vendor/github.com/golang/protobuf/proto/equal.go delete mode 100644 vendor/github.com/golang/protobuf/proto/lib.go delete mode 100644 vendor/github.com/golang/protobuf/proto/message_set.go delete mode 100644 vendor/github.com/golang/protobuf/proto/pointer_reflect.go delete mode 100644 vendor/github.com/golang/protobuf/proto/pointer_unsafe.go create mode 100644 vendor/github.com/golang/protobuf/proto/proto.go create mode 100644 vendor/github.com/golang/protobuf/proto/registry.go delete mode 100644 vendor/github.com/golang/protobuf/proto/table_marshal.go delete mode 100644 vendor/github.com/golang/protobuf/proto/table_merge.go delete mode 100644 vendor/github.com/golang/protobuf/proto/table_unmarshal.go delete mode 100644 vendor/github.com/golang/protobuf/proto/text.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_decode.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_encode.go delete mode 100644 vendor/github.com/golang/protobuf/proto/text_parser.go create mode 100644 vendor/github.com/golang/protobuf/proto/wire.go create mode 100644 vendor/github.com/golang/protobuf/proto/wrappers.go create mode 100644 vendor/github.com/kkdai/bstream/.gitignore create mode 100644 vendor/github.com/kkdai/bstream/.travis.yml create mode 100644 vendor/github.com/kkdai/bstream/LICENSE create mode 100644 vendor/github.com/kkdai/bstream/README.md create mode 100644 vendor/github.com/kkdai/bstream/bstream.go create mode 100644 vendor/github.com/lightninglabs/gozmq/LICENSE create mode 100644 vendor/github.com/lightninglabs/gozmq/README.md create mode 100644 vendor/github.com/lightninglabs/gozmq/go.mod create mode 100644 vendor/github.com/lightninglabs/gozmq/zmq.go create mode 100644 vendor/github.com/lightninglabs/neutrino/.gitignore create mode 100644 vendor/github.com/lightninglabs/neutrino/.travis.yml create mode 100644 vendor/github.com/lightninglabs/neutrino/LICENSE create mode 100644 vendor/github.com/lightninglabs/neutrino/README.md create mode 100644 vendor/github.com/lightninglabs/neutrino/banman/codec.go create mode 100644 vendor/github.com/lightninglabs/neutrino/banman/reason.go create mode 100644 vendor/github.com/lightninglabs/neutrino/banman/store.go create mode 100644 vendor/github.com/lightninglabs/neutrino/banman/util.go create mode 100644 vendor/github.com/lightninglabs/neutrino/batch_spend_reporter.go create mode 100644 vendor/github.com/lightninglabs/neutrino/blockmanager.go create mode 100644 vendor/github.com/lightninglabs/neutrino/blockntfns/log.go create mode 100644 vendor/github.com/lightninglabs/neutrino/blockntfns/manager.go create mode 100644 vendor/github.com/lightninglabs/neutrino/blockntfns/notification.go create mode 100644 vendor/github.com/lightninglabs/neutrino/btcd_checkout.sh create mode 100644 vendor/github.com/lightninglabs/neutrino/cache/cache.go create mode 100644 vendor/github.com/lightninglabs/neutrino/cache/cacheable_block.go create mode 100644 vendor/github.com/lightninglabs/neutrino/cache/cacheable_filter.go create mode 100644 vendor/github.com/lightninglabs/neutrino/cache/lru/lru.go create mode 100644 vendor/github.com/lightninglabs/neutrino/chainsync/filtercontrol.go create mode 100644 vendor/github.com/lightninglabs/neutrino/errors.go create mode 100644 vendor/github.com/lightninglabs/neutrino/filterdb/db.go create mode 100644 vendor/github.com/lightninglabs/neutrino/go.mod create mode 100644 vendor/github.com/lightninglabs/neutrino/go.sum create mode 100644 vendor/github.com/lightninglabs/neutrino/gotest.sh create mode 100644 vendor/github.com/lightninglabs/neutrino/headerfs/file.go create mode 100644 vendor/github.com/lightninglabs/neutrino/headerfs/index.go create mode 100644 vendor/github.com/lightninglabs/neutrino/headerfs/store.go create mode 100644 vendor/github.com/lightninglabs/neutrino/headerfs/truncate.go create mode 100644 vendor/github.com/lightninglabs/neutrino/headerfs/truncate_windows.go create mode 100644 vendor/github.com/lightninglabs/neutrino/headerlist/bounded_header_list.go create mode 100644 vendor/github.com/lightninglabs/neutrino/headerlist/header_list.go create mode 100644 vendor/github.com/lightninglabs/neutrino/headerlogger.go create mode 100644 vendor/github.com/lightninglabs/neutrino/log.go create mode 100644 vendor/github.com/lightninglabs/neutrino/mock_store.go create mode 100644 vendor/github.com/lightninglabs/neutrino/neutrino.go create mode 100644 vendor/github.com/lightninglabs/neutrino/notifications.go create mode 100644 vendor/github.com/lightninglabs/neutrino/pushtx/broadcaster.go create mode 100644 vendor/github.com/lightninglabs/neutrino/pushtx/error.go create mode 100644 vendor/github.com/lightninglabs/neutrino/pushtx/log.go create mode 100644 vendor/github.com/lightninglabs/neutrino/query.go create mode 100644 vendor/github.com/lightninglabs/neutrino/query/interface.go create mode 100644 vendor/github.com/lightninglabs/neutrino/query/log.go create mode 100644 vendor/github.com/lightninglabs/neutrino/query/peer_rank.go create mode 100644 vendor/github.com/lightninglabs/neutrino/query/worker.go create mode 100644 vendor/github.com/lightninglabs/neutrino/query/workmanager.go create mode 100644 vendor/github.com/lightninglabs/neutrino/query/workqueue.go create mode 100644 vendor/github.com/lightninglabs/neutrino/rescan.go create mode 100644 vendor/github.com/lightninglabs/neutrino/utxoscanner.go create mode 100644 vendor/github.com/lightningnetwork/lnd/clock/LICENSE create mode 100644 vendor/github.com/lightningnetwork/lnd/clock/default_clock.go create mode 100644 vendor/github.com/lightningnetwork/lnd/clock/go.mod create mode 100644 vendor/github.com/lightningnetwork/lnd/clock/interface.go create mode 100644 vendor/github.com/lightningnetwork/lnd/clock/test_clock.go create mode 100644 vendor/github.com/lightningnetwork/lnd/input/input.go create mode 100644 vendor/github.com/lightningnetwork/lnd/input/script_utils.go create mode 100644 vendor/github.com/lightningnetwork/lnd/input/signdescriptor.go create mode 100644 vendor/github.com/lightningnetwork/lnd/input/signer.go create mode 100644 vendor/github.com/lightningnetwork/lnd/input/size.go create mode 100644 vendor/github.com/lightningnetwork/lnd/input/test_utils.go create mode 100644 vendor/github.com/lightningnetwork/lnd/input/txout.go create mode 100644 vendor/github.com/lightningnetwork/lnd/input/witnessgen.go create mode 100644 vendor/github.com/lightningnetwork/lnd/keychain/btcwallet.go create mode 100644 vendor/github.com/lightningnetwork/lnd/keychain/derivation.go create mode 100644 vendor/github.com/lightningnetwork/lnd/queue/LICENSE create mode 100644 vendor/github.com/lightningnetwork/lnd/queue/circular_buf.go create mode 100644 vendor/github.com/lightningnetwork/lnd/queue/gc_queue.go create mode 100644 vendor/github.com/lightningnetwork/lnd/queue/go.mod create mode 100644 vendor/github.com/lightningnetwork/lnd/queue/go.sum create mode 100644 vendor/github.com/lightningnetwork/lnd/queue/priority_queue.go create mode 100644 vendor/github.com/lightningnetwork/lnd/queue/queue.go create mode 100644 vendor/github.com/lightningnetwork/lnd/ticker/LICENSE create mode 100644 vendor/github.com/lightningnetwork/lnd/ticker/force.go create mode 100644 vendor/github.com/lightningnetwork/lnd/ticker/go.mod create mode 100644 vendor/github.com/lightningnetwork/lnd/ticker/ticker.go create mode 100644 vendor/github.com/lightningnetwork/lnd/tlv/primitive.go create mode 100644 vendor/github.com/lightningnetwork/lnd/tlv/record.go create mode 100644 vendor/github.com/lightningnetwork/lnd/tlv/stream.go create mode 100644 vendor/github.com/lightningnetwork/lnd/tlv/truncated.go create mode 100644 vendor/github.com/lightningnetwork/lnd/tlv/varint.go create mode 100644 vendor/github.com/lightningnetwork/lnd/tor/add_onion.go create mode 100644 vendor/github.com/miekg/dns/.codecov.yml create mode 100644 vendor/github.com/miekg/dns/CODEOWNERS create mode 100644 vendor/github.com/miekg/dns/Makefile.release create mode 100644 vendor/github.com/miekg/dns/acceptfunc.go create mode 100644 vendor/github.com/miekg/dns/duplicate.go create mode 100644 vendor/github.com/miekg/dns/go.mod create mode 100644 vendor/github.com/miekg/dns/go.sum delete mode 100644 vendor/github.com/miekg/dns/internal/socket/cmsghdr.go delete mode 100644 vendor/github.com/miekg/dns/internal/socket/cmsghdr_linux_64bit.go delete mode 100644 vendor/github.com/miekg/dns/internal/socket/cmsghdr_other.go delete mode 100644 vendor/github.com/miekg/dns/internal/socket/controlmessage.go delete mode 100644 vendor/github.com/miekg/dns/internal/socket/socket.go delete mode 100644 vendor/github.com/miekg/dns/internal/socket/sys.go create mode 100644 vendor/github.com/miekg/dns/listen_go111.go create mode 100644 vendor/github.com/miekg/dns/listen_go_not111.go create mode 100644 vendor/github.com/miekg/dns/msg_truncate.go delete mode 100644 vendor/github.com/miekg/dns/rawmsg.go delete mode 100644 vendor/github.com/miekg/dns/scanner.go create mode 100644 vendor/github.com/miekg/dns/serve_mux.go delete mode 100644 vendor/github.com/miekg/dns/udp_linux.go delete mode 100644 vendor/github.com/miekg/dns/udp_other.go create mode 100644 vendor/github.com/miekg/dns/version.go delete mode 100644 vendor/github.com/miekg/dns/zcompress.go create mode 100644 vendor/github.com/miekg/dns/zduplicate.go create mode 100644 vendor/github.com/pkg/errors/Makefile create mode 100644 vendor/github.com/pkg/errors/go113.go create mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519.go create mode 100644 vendor/golang.org/x/crypto/ed25519/ed25519_go113.go create mode 100644 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go create mode 100644 vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go create mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing.go create mode 100644 vendor/golang.org/x/crypto/internal/subtle/aliasing_appengine.go create mode 100644 vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go create mode 100644 vendor/golang.org/x/crypto/poly1305/bits_compat.go create mode 100644 vendor/golang.org/x/crypto/poly1305/bits_go1.13.go create mode 100644 vendor/golang.org/x/crypto/poly1305/mac_noasm.go create mode 100644 vendor/golang.org/x/crypto/poly1305/poly1305.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_amd64.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_amd64.s create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_generic.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_ppc64le.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_ppc64le.s create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_s390x.go create mode 100644 vendor/golang.org/x/crypto/poly1305/sum_s390x.s create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/terminal.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_aix.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_linux.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_windows.go create mode 100644 vendor/golang.org/x/net/bpf/asm.go create mode 100644 vendor/golang.org/x/net/bpf/constants.go create mode 100644 vendor/golang.org/x/net/bpf/doc.go create mode 100644 vendor/golang.org/x/net/bpf/instructions.go create mode 100644 vendor/golang.org/x/net/bpf/setter.go create mode 100644 vendor/golang.org/x/net/bpf/vm.go create mode 100644 vendor/golang.org/x/net/bpf/vm_instructions.go create mode 100644 vendor/golang.org/x/net/internal/iana/const.go create mode 100644 vendor/golang.org/x/net/internal/socket/cmsghdr.go create mode 100644 vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go rename vendor/{github.com/miekg/dns => golang.org/x/net}/internal/socket/cmsghdr_linux_32bit.go (51%) create mode 100644 vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go create mode 100644 vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go create mode 100644 vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go create mode 100644 vendor/golang.org/x/net/internal/socket/empty.s create mode 100644 vendor/golang.org/x/net/internal/socket/error_unix.go create mode 100644 vendor/golang.org/x/net/internal/socket/error_windows.go create mode 100644 vendor/golang.org/x/net/internal/socket/iovec_32bit.go create mode 100644 vendor/golang.org/x/net/internal/socket/iovec_64bit.go create mode 100644 vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go create mode 100644 vendor/golang.org/x/net/internal/socket/iovec_stub.go create mode 100644 vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go create mode 100644 vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_bsd.go create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_linux.go create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go create mode 100644 vendor/golang.org/x/net/internal/socket/msghdr_stub.go create mode 100644 vendor/golang.org/x/net/internal/socket/norace.go create mode 100644 vendor/golang.org/x/net/internal/socket/race.go create mode 100644 vendor/golang.org/x/net/internal/socket/rawconn.go create mode 100644 vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go create mode 100644 vendor/golang.org/x/net/internal/socket/rawconn_msg.go create mode 100644 vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go create mode 100644 vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go create mode 100644 vendor/golang.org/x/net/internal/socket/socket.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_bsd.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_bsdvar.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_const_unix.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_darwin.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_dragonfly.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_go1_11_darwin.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linkname.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_386.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_386.s create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_amd64.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_arm.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_arm64.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_mips.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_mips64.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_mips64le.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_mipsle.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_ppc64.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_ppc64le.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_riscv64.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_linux_s390x.s create mode 100644 vendor/golang.org/x/net/internal/socket/sys_netbsd.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_posix.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_solaris.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_solaris_amd64.s create mode 100644 vendor/golang.org/x/net/internal/socket/sys_stub.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_unix.go create mode 100644 vendor/golang.org/x/net/internal/socket/sys_windows.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_darwin_386.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_darwin_amd64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_darwin_arm.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_darwin_arm64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_freebsd_386.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_freebsd_amd64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_386.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_riscv64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_openbsd_386.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_openbsd_amd64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm64.go create mode 100644 vendor/golang.org/x/net/internal/socket/zsys_solaris_amd64.go create mode 100644 vendor/golang.org/x/net/ipv4/batch.go create mode 100644 vendor/golang.org/x/net/ipv4/control.go create mode 100644 vendor/golang.org/x/net/ipv4/control_bsd.go create mode 100644 vendor/golang.org/x/net/ipv4/control_pktinfo.go create mode 100644 vendor/golang.org/x/net/ipv4/control_stub.go create mode 100644 vendor/golang.org/x/net/ipv4/control_unix.go create mode 100644 vendor/golang.org/x/net/ipv4/control_windows.go create mode 100644 vendor/golang.org/x/net/ipv4/dgramopt.go create mode 100644 vendor/golang.org/x/net/ipv4/doc.go create mode 100644 vendor/golang.org/x/net/ipv4/endpoint.go create mode 100644 vendor/golang.org/x/net/ipv4/genericopt.go create mode 100644 vendor/golang.org/x/net/ipv4/header.go create mode 100644 vendor/golang.org/x/net/ipv4/helper.go create mode 100644 vendor/golang.org/x/net/ipv4/iana.go create mode 100644 vendor/golang.org/x/net/ipv4/icmp.go create mode 100644 vendor/golang.org/x/net/ipv4/icmp_linux.go create mode 100644 vendor/golang.org/x/net/ipv4/icmp_stub.go create mode 100644 vendor/golang.org/x/net/ipv4/packet.go create mode 100644 vendor/golang.org/x/net/ipv4/payload.go create mode 100644 vendor/golang.org/x/net/ipv4/payload_cmsg.go create mode 100644 vendor/golang.org/x/net/ipv4/payload_nocmsg.go create mode 100644 vendor/golang.org/x/net/ipv4/sockopt.go create mode 100644 vendor/golang.org/x/net/ipv4/sockopt_posix.go create mode 100644 vendor/golang.org/x/net/ipv4/sockopt_stub.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_aix.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_asmreq.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_asmreq_stub.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_asmreqn.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_asmreqn_stub.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_bpf.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_bpf_stub.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_bsd.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_darwin.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_dragonfly.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_freebsd.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_linux.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_solaris.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_ssmreq.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_ssmreq_stub.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_stub.go create mode 100644 vendor/golang.org/x/net/ipv4/sys_windows.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_aix_ppc64.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_darwin.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_dragonfly.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_freebsd_arm64.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_386.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_arm.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_mips.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_mipsle.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_riscv64.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_netbsd.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_openbsd.go create mode 100644 vendor/golang.org/x/net/ipv4/zsys_solaris.go create mode 100644 vendor/golang.org/x/net/ipv6/batch.go create mode 100644 vendor/golang.org/x/net/ipv6/control.go create mode 100644 vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go create mode 100644 vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go create mode 100644 vendor/golang.org/x/net/ipv6/control_stub.go create mode 100644 vendor/golang.org/x/net/ipv6/control_unix.go create mode 100644 vendor/golang.org/x/net/ipv6/control_windows.go create mode 100644 vendor/golang.org/x/net/ipv6/dgramopt.go create mode 100644 vendor/golang.org/x/net/ipv6/doc.go create mode 100644 vendor/golang.org/x/net/ipv6/endpoint.go create mode 100644 vendor/golang.org/x/net/ipv6/genericopt.go create mode 100644 vendor/golang.org/x/net/ipv6/header.go create mode 100644 vendor/golang.org/x/net/ipv6/helper.go create mode 100644 vendor/golang.org/x/net/ipv6/iana.go create mode 100644 vendor/golang.org/x/net/ipv6/icmp.go create mode 100644 vendor/golang.org/x/net/ipv6/icmp_bsd.go create mode 100644 vendor/golang.org/x/net/ipv6/icmp_linux.go create mode 100644 vendor/golang.org/x/net/ipv6/icmp_solaris.go create mode 100644 vendor/golang.org/x/net/ipv6/icmp_stub.go create mode 100644 vendor/golang.org/x/net/ipv6/icmp_windows.go create mode 100644 vendor/golang.org/x/net/ipv6/payload.go create mode 100644 vendor/golang.org/x/net/ipv6/payload_cmsg.go create mode 100644 vendor/golang.org/x/net/ipv6/payload_nocmsg.go create mode 100644 vendor/golang.org/x/net/ipv6/sockopt.go create mode 100644 vendor/golang.org/x/net/ipv6/sockopt_posix.go create mode 100644 vendor/golang.org/x/net/ipv6/sockopt_stub.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_aix.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_asmreq.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_bpf.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_bpf_stub.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_bsd.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_darwin.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_freebsd.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_linux.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_solaris.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_ssmreq.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_stub.go create mode 100644 vendor/golang.org/x/net/ipv6/sys_windows.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_aix_ppc64.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_darwin.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_dragonfly.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_freebsd_arm64.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_386.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_arm.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_mips.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_riscv64.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_netbsd.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_openbsd.go create mode 100644 vendor/golang.org/x/net/ipv6/zsys_solaris.go create mode 100644 vendor/golang.org/x/net/proxy/dial.go create mode 100644 vendor/golang.org/x/sys/AUTHORS create mode 100644 vendor/golang.org/x/sys/CONTRIBUTORS create mode 100644 vendor/golang.org/x/sys/LICENSE create mode 100644 vendor/golang.org/x/sys/PATENTS create mode 100644 vendor/golang.org/x/sys/cpu/asm_aix_ppc64.s create mode 100644 vendor/golang.org/x/sys/cpu/byteorder.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_aix_ppc64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_arm64.s create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gc_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c create mode 100644 vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_mips64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_ppc64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_mips64x.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_mipsx.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_arm64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_riscv64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_s390x.s create mode 100644 vendor/golang.org/x/sys/cpu/cpu_wasm.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_x86.s create mode 100644 vendor/golang.org/x/sys/cpu/hwcap_linux.go create mode 100644 vendor/golang.org/x/sys/cpu/syscall_aix_ppc64_gc.go create mode 100644 vendor/golang.org/x/sys/unix/.gitignore create mode 100644 vendor/golang.org/x/sys/unix/README.md create mode 100644 vendor/golang.org/x/sys/unix/affinity_linux.go create mode 100644 vendor/golang.org/x/sys/unix/aliases.go create mode 100644 vendor/golang.org/x/sys/unix/asm_aix_ppc64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_mips64x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_mipsx.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_riscv64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_s390x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_solaris_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/bluetooth_linux.go create mode 100644 vendor/golang.org/x/sys/unix/cap_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/constants.go create mode 100644 vendor/golang.org/x/sys/unix/dev_aix_ppc.go create mode 100644 vendor/golang.org/x/sys/unix/dev_aix_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/dev_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/dev_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/dev_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/dev_linux.go create mode 100644 vendor/golang.org/x/sys/unix/dev_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/dev_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/dirent.go create mode 100644 vendor/golang.org/x/sys/unix/endian_big.go create mode 100644 vendor/golang.org/x/sys/unix/endian_little.go create mode 100644 vendor/golang.org/x/sys/unix/env_unix.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/fcntl.go create mode 100644 vendor/golang.org/x/sys/unix/fcntl_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go create mode 100644 vendor/golang.org/x/sys/unix/fdset.go create mode 100644 vendor/golang.org/x/sys/unix/gccgo.go create mode 100644 vendor/golang.org/x/sys/unix/gccgo_c.c create mode 100644 vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ioctl.go create mode 100644 vendor/golang.org/x/sys/unix/mkall.sh create mode 100644 vendor/golang.org/x/sys/unix/mkerrors.sh create mode 100644 vendor/golang.org/x/sys/unix/pagesize_unix.go create mode 100644 vendor/golang.org/x/sys/unix/pledge_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/race.go create mode 100644 vendor/golang.org/x/sys/unix/race0.go create mode 100644 vendor/golang.org/x/sys/unix/readdirent_getdents.go create mode 100644 vendor/golang.org/x/sys/unix/readdirent_getdirentries.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_linux.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_unix.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go create mode 100644 vendor/golang.org/x/sys/unix/str.go create mode 100644 vendor/golang.org/x/sys/unix/syscall.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_aix.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_aix_ppc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_aix_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_bsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.1_12.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_illumos.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix_gc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go create mode 100644 vendor/golang.org/x/sys/unix/timestruct.go create mode 100644 vendor/golang.org/x/sys/unix/unveil_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/xattr_bsd.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_aix_ppc.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zptrace_armnn_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptrace_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zptrace_mipsnn_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptrace_mipsnnle_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptrace_x86_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_aix_ppc.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gc.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_aix_ppc64_gccgo.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_13.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_13.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_13.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_13.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_illumos_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_riscv64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_aix_ppc.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_aix_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/windows/aliases.go create mode 100644 vendor/golang.org/x/sys/windows/dll_windows.go create mode 100644 vendor/golang.org/x/sys/windows/empty.s create mode 100644 vendor/golang.org/x/sys/windows/env_windows.go create mode 100644 vendor/golang.org/x/sys/windows/eventlog.go create mode 100644 vendor/golang.org/x/sys/windows/exec_windows.go create mode 100644 vendor/golang.org/x/sys/windows/memory_windows.go create mode 100644 vendor/golang.org/x/sys/windows/mkerrors.bash create mode 100644 vendor/golang.org/x/sys/windows/mkknownfolderids.bash create mode 100644 vendor/golang.org/x/sys/windows/mksyscall.go create mode 100644 vendor/golang.org/x/sys/windows/race.go create mode 100644 vendor/golang.org/x/sys/windows/race0.go create mode 100644 vendor/golang.org/x/sys/windows/security_windows.go create mode 100644 vendor/golang.org/x/sys/windows/service.go create mode 100644 vendor/golang.org/x/sys/windows/str.go create mode 100644 vendor/golang.org/x/sys/windows/syscall.go create mode 100644 vendor/golang.org/x/sys/windows/syscall_windows.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows_386.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows_amd64.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows_arm.go create mode 100644 vendor/golang.org/x/sys/windows/zerrors_windows.go create mode 100644 vendor/golang.org/x/sys/windows/zknownfolderids_windows.go create mode 100644 vendor/golang.org/x/sys/windows/zsyscall_windows.go create mode 100644 vendor/google.golang.org/protobuf/AUTHORS create mode 100644 vendor/google.golang.org/protobuf/CONTRIBUTORS create mode 100644 vendor/google.golang.org/protobuf/LICENSE create mode 100644 vendor/google.golang.org/protobuf/PATENTS create mode 100644 vendor/google.golang.org/protobuf/encoding/prototext/decode.go create mode 100644 vendor/google.golang.org/protobuf/encoding/prototext/doc.go create mode 100644 vendor/google.golang.org/protobuf/encoding/prototext/encode.go create mode 100644 vendor/google.golang.org/protobuf/encoding/protowire/wire.go create mode 100644 vendor/google.golang.org/protobuf/internal/descfmt/stringer.go create mode 100644 vendor/google.golang.org/protobuf/internal/descopts/options.go create mode 100644 vendor/google.golang.org/protobuf/internal/detrand/rand.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/defval/default.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/messageset/messageset.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/text/decode.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/text/decode_number.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/text/decode_string.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/text/decode_token.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/text/doc.go create mode 100644 vendor/google.golang.org/protobuf/internal/encoding/text/encode.go create mode 100644 vendor/google.golang.org/protobuf/internal/errors/errors.go create mode 100644 vendor/google.golang.org/protobuf/internal/errors/is_go112.go create mode 100644 vendor/google.golang.org/protobuf/internal/errors/is_go113.go create mode 100644 vendor/google.golang.org/protobuf/internal/fieldsort/fieldsort.go create mode 100644 vendor/google.golang.org/protobuf/internal/filedesc/build.go create mode 100644 vendor/google.golang.org/protobuf/internal/filedesc/desc.go create mode 100644 vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go create mode 100644 vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go create mode 100644 vendor/google.golang.org/protobuf/internal/filedesc/desc_list.go create mode 100644 vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go create mode 100644 vendor/google.golang.org/protobuf/internal/filetype/build.go create mode 100644 vendor/google.golang.org/protobuf/internal/flags/flags.go create mode 100644 vendor/google.golang.org/protobuf/internal/flags/proto_legacy_disable.go create mode 100644 vendor/google.golang.org/protobuf/internal/flags/proto_legacy_enable.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/any_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/api_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/doc.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/duration_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/empty_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/field_mask_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/goname.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/map_entry.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/source_context_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/struct_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/timestamp_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/type_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/wrappers.go create mode 100644 vendor/google.golang.org/protobuf/internal/genid/wrappers_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/api_export.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/checkinit.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_extension.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_field.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_map.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_message.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_reflect.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_tables.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_unsafe.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/convert.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/convert_list.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/convert_map.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/decode.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/encode.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/enum.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/extension.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/legacy_export.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/legacy_file.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/legacy_message.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/merge.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/merge_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/message.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/message_reflect.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/validate.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/weak.go create mode 100644 vendor/google.golang.org/protobuf/internal/mapsort/mapsort.go create mode 100644 vendor/google.golang.org/protobuf/internal/pragma/pragma.go create mode 100644 vendor/google.golang.org/protobuf/internal/set/ints.go create mode 100644 vendor/google.golang.org/protobuf/internal/strs/strings.go create mode 100644 vendor/google.golang.org/protobuf/internal/strs/strings_pure.go create mode 100644 vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go create mode 100644 vendor/google.golang.org/protobuf/internal/version/version.go create mode 100644 vendor/google.golang.org/protobuf/proto/checkinit.go create mode 100644 vendor/google.golang.org/protobuf/proto/decode.go create mode 100644 vendor/google.golang.org/protobuf/proto/decode_gen.go create mode 100644 vendor/google.golang.org/protobuf/proto/doc.go create mode 100644 vendor/google.golang.org/protobuf/proto/encode.go create mode 100644 vendor/google.golang.org/protobuf/proto/encode_gen.go create mode 100644 vendor/google.golang.org/protobuf/proto/equal.go create mode 100644 vendor/google.golang.org/protobuf/proto/extension.go create mode 100644 vendor/google.golang.org/protobuf/proto/merge.go create mode 100644 vendor/google.golang.org/protobuf/proto/messageset.go create mode 100644 vendor/google.golang.org/protobuf/proto/proto.go create mode 100644 vendor/google.golang.org/protobuf/proto/proto_methods.go create mode 100644 vendor/google.golang.org/protobuf/proto/proto_reflect.go create mode 100644 vendor/google.golang.org/protobuf/proto/reset.go create mode 100644 vendor/google.golang.org/protobuf/proto/size.go create mode 100644 vendor/google.golang.org/protobuf/proto/size_gen.go create mode 100644 vendor/google.golang.org/protobuf/proto/wrappers.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/methods.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/source.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/type.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/value.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe.go create mode 100644 vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go create mode 100644 vendor/google.golang.org/protobuf/runtime/protoiface/legacy.go create mode 100644 vendor/google.golang.org/protobuf/runtime/protoiface/methods.go create mode 100644 vendor/google.golang.org/protobuf/runtime/protoimpl/impl.go create mode 100644 vendor/google.golang.org/protobuf/runtime/protoimpl/version.go diff --git a/.gitignore b/.gitignore index 3b56270..fa7ba6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,3 @@ -# Mac OS X finder -.DS_Store +libwallet/.gitignore# binary +libwallet -# Vim swap files -*~ -.*.sw[a-z] - -# VS code -.vscode - -# Goland -.idea - -# Golang -/bin -/pkg -/src diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c23774c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${fileDirname}", + "env": {}, + "args": [] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a8dc317 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "go.buildFlags": [ + "-v" + ] +} \ No newline at end of file diff --git a/address.go b/address.go index 05183b9..51b1c68 100644 --- a/address.go +++ b/address.go @@ -9,8 +9,8 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcutil" - "github.com/golang/protobuf/proto" "github.com/pkg/errors" + "google.golang.org/protobuf/proto" ) // These constants are here for clients usage. @@ -92,11 +92,9 @@ const ( // GetPaymentURI builds a MuunPaymentURI from text (Bitcoin Uri, Muun Uri or address) and a network func GetPaymentURI(rawInput string, network *Network) (*MuunPaymentURI, error) { - bitcoinUri := buildUriFromString(rawInput) - - components, err := url.Parse(bitcoinUri) - if err != nil { - return nil, err + bitcoinUri, components := buildUriFromString(rawInput, bitcoinScheme) + if components == nil { + return nil, errors.Errorf("failed to parse uri %v", rawInput) } if components.Scheme != "bitcoin" { @@ -224,11 +222,11 @@ func DoPaymentRequestCall(url string, network *Network) (*MuunPaymentURI, error) return &MuunPaymentURI{ Address: address, - Message: *payDetails.Memo, - Amount: strconv.FormatUint(*payDetails.Outputs[0].Amount, 10), + Message: payDetails.Memo, + Amount: strconv.FormatUint(payDetails.Outputs[0].Amount, 10), BIP70Url: url, - CreationTime: strconv.FormatUint(*payDetails.Time, 10), - ExpiresTime: strconv.FormatUint(*payDetails.Expires, 10), + CreationTime: strconv.FormatUint(payDetails.Time, 10), + ExpiresTime: strconv.FormatUint(payDetails.Expires, 10), }, nil } @@ -244,14 +242,19 @@ func getAddressFromScript(script []byte, network *Network) (string, error) { return address.String(), nil } -func buildUriFromString(rawInput string) string { +func buildUriFromString(rawInput string, targetScheme string) (string, *url.URL) { newUri := rawInput - newUri = strings.Replace(newUri, muunScheme, bitcoinScheme, 1) + newUri = strings.Replace(newUri, muunScheme, targetScheme, 1) - if !strings.Contains(newUri, bitcoinScheme) { - newUri = bitcoinScheme + rawInput + if !strings.HasPrefix(strings.ToLower(newUri), targetScheme) { + newUri = targetScheme + rawInput + } + + components, err := url.Parse(newUri) + if err != nil { + return "", nil } - return newUri + return newUri, components } diff --git a/address_test.go b/address_test.go index 0aec6a7..0acf7c7 100644 --- a/address_test.go +++ b/address_test.go @@ -3,6 +3,7 @@ package libwallet import ( "encoding/hex" "reflect" + "strings" "testing" ) @@ -13,11 +14,11 @@ const ( 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) { @@ -89,6 +90,14 @@ func TestGetPaymentURI(t *testing.T) { }, wantErr: true, }, + { + name: "randomText", + args: args{ + address: randomText, + network: *Regtest(), + }, + wantErr: true, + }, { name: "BIP70NonRetroCompatAddress", args: args{ @@ -164,6 +173,28 @@ func TestGetPaymentURI(t *testing.T) { 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 { @@ -186,7 +217,8 @@ func TestGetPaymentURI(t *testing.T) { func Test_normalizeAddress(t *testing.T) { type args struct { - rawAddress string + rawAddress string + targetScheme string } tests := []struct { name string @@ -196,28 +228,39 @@ func Test_normalizeAddress(t *testing.T) { { name: "normalAddress", args: args{ - rawAddress: address, + rawAddress: address, + targetScheme: bitcoinScheme, }, want: bitcoinScheme + address, }, { name: "bitcoinAddress", args: args{ - rawAddress: bitcoinScheme + address, + rawAddress: bitcoinScheme + address, + targetScheme: bitcoinScheme, }, want: bitcoinScheme + address, }, { name: "muunAddress", args: args{ - rawAddress: muunScheme + address, + 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); got != tt.want { + if got, _ := buildUriFromString(tt.args.rawAddress, tt.args.targetScheme); got != tt.want { t.Errorf("buildUriFromString() = %v, want %v", got, tt.want) } }) diff --git a/aes.go b/aes.go index dfa5738..747e81e 100644 --- a/aes.go +++ b/aes.go @@ -8,10 +8,14 @@ import ( "github.com/pkg/errors" ) -func encrypt(key []byte, iv []byte, plaintext []byte) ([]byte, error) { +const aesKeySize = 32 +func encryptAesCbcPkcs7(key []byte, iv []byte, plaintext []byte) ([]byte, error) { plaintext = pkcs7Padding(plaintext) + return encryptAesCbcNoPadding(key, iv, plaintext) +} +func encryptAesCbcNoPadding(key []byte, iv []byte, plaintext []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err @@ -25,8 +29,17 @@ func encrypt(key []byte, iv []byte, plaintext []byte) ([]byte, error) { return ciphertext, nil } -func decrypt(key []byte, iv []byte, cypertext []byte) ([]byte, error) { +func decryptAesCbcPkcs7(key []byte, iv []byte, cypertext []byte) ([]byte, error) { + + paddedPlaintext, err := decryptAesCbcNoPadding(key, iv, cypertext) + if err != nil { + return nil, err + } + return pkcs7UnPadding(paddedPlaintext) +} + +func decryptAesCbcNoPadding(key []byte, iv []byte, cypertext []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err @@ -37,11 +50,6 @@ func decrypt(key []byte, iv []byte, cypertext []byte) ([]byte, error) { mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(plaintext, cypertext) - plaintext, err = pkcs7UnPadding(plaintext) - if err != nil { - return nil, err - } - return plaintext, nil } diff --git a/bip70.pb.go b/bip70.pb.go index c216384..ae930c6 100644 --- a/bip70.pb.go +++ b/bip70.pb.go @@ -1,375 +1,480 @@ +// +// Simple Bitcoin Payment Protocol messages +// +// Use fields 1000+ for extensions; +// to avoid conflicts, register extensions via pull-req at +// https://github.com/bitcoin/bips/blob/master/bip-0070/extensions.mediawiki +// + // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0-devel +// protoc v3.7.0 // source: bip70.proto package libwallet import ( - fmt "fmt" - math "math" + reflect "reflect" + sync "sync" proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 // Generalized form of "send payment to this/these bitcoin addresses" type Output struct { - Amount *uint64 `protobuf:"varint,1,opt,name=amount,def=0" json:"amount,omitempty"` - Script []byte `protobuf:"bytes,2,req,name=script" json:"script,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Output) Reset() { *m = Output{} } -func (m *Output) String() string { return proto.CompactTextString(m) } -func (*Output) ProtoMessage() {} -func (*Output) Descriptor() ([]byte, []int) { - return fileDescriptor_de204c4c8d465ce4, []int{0} + Amount uint64 `protobuf:"varint,1,opt,name=amount,proto3" json:"amount,omitempty"` // amount is integer-number-of-satoshis + Script []byte `protobuf:"bytes,2,opt,name=script,proto3" json:"script,omitempty"` // usually one of the standard Script forms } -func (m *Output) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Output.Unmarshal(m, b) -} -func (m *Output) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Output.Marshal(b, m, deterministic) -} -func (m *Output) XXX_Merge(src proto.Message) { - xxx_messageInfo_Output.Merge(m, src) -} -func (m *Output) XXX_Size() int { - return xxx_messageInfo_Output.Size(m) +func (x *Output) Reset() { + *x = Output{} + if protoimpl.UnsafeEnabled { + mi := &file_bip70_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Output) XXX_DiscardUnknown() { - xxx_messageInfo_Output.DiscardUnknown(m) + +func (x *Output) String() string { + return protoimpl.X.MessageStringOf(x) } -var xxx_messageInfo_Output proto.InternalMessageInfo +func (*Output) ProtoMessage() {} -type PaymentDetails struct { - Network *string `protobuf:"bytes,1,opt,name=network,def=main" json:"network,omitempty"` - Outputs []*Output `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"` - Time *uint64 `protobuf:"varint,3,req,name=time" json:"time,omitempty"` - Expires *uint64 `protobuf:"varint,4,opt,name=expires" json:"expires,omitempty"` - Memo *string `protobuf:"bytes,5,opt,name=memo" json:"memo,omitempty"` - PaymentUrl *string `protobuf:"bytes,6,opt,name=payment_url,json=paymentUrl" json:"payment_url,omitempty"` - MerchantData []byte `protobuf:"bytes,7,opt,name=merchant_data,json=merchantData" json:"merchant_data,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PaymentDetails) Reset() { *m = PaymentDetails{} } -func (m *PaymentDetails) String() string { return proto.CompactTextString(m) } -func (*PaymentDetails) ProtoMessage() {} -func (*PaymentDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_de204c4c8d465ce4, []int{1} +func (x *Output) ProtoReflect() protoreflect.Message { + mi := &file_bip70_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *PaymentDetails) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PaymentDetails.Unmarshal(m, b) -} -func (m *PaymentDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PaymentDetails.Marshal(b, m, deterministic) -} -func (m *PaymentDetails) XXX_Merge(src proto.Message) { - xxx_messageInfo_PaymentDetails.Merge(m, src) -} -func (m *PaymentDetails) XXX_Size() int { - return xxx_messageInfo_PaymentDetails.Size(m) +// Deprecated: Use Output.ProtoReflect.Descriptor instead. +func (*Output) Descriptor() ([]byte, []int) { + return file_bip70_proto_rawDescGZIP(), []int{0} } -func (m *PaymentDetails) XXX_DiscardUnknown() { - xxx_messageInfo_PaymentDetails.DiscardUnknown(m) + +type PaymentDetails struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Network string `protobuf:"bytes,1,opt,name=network,proto3" json:"network,omitempty"` // "main" or "test" + Outputs []*Output `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs,omitempty"` // Where payment should be sent + Time uint64 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` // Timestamp; when payment request created + Expires uint64 `protobuf:"varint,4,opt,name=expires,proto3" json:"expires,omitempty"` // Timestamp; when this request should be considered invalid + Memo string `protobuf:"bytes,5,opt,name=memo,proto3" json:"memo,omitempty"` // Human-readable description of request for the customer + PaymentUrl string `protobuf:"bytes,6,opt,name=payment_url,json=paymentUrl,proto3" json:"payment_url,omitempty"` // URL to send Payment and get PaymentACK + MerchantData []byte `protobuf:"bytes,7,opt,name=merchant_data,json=merchantData,proto3" json:"merchant_data,omitempty"` // Arbitrary data to include in the Payment message +} + +func (x *PaymentDetails) Reset() { + *x = PaymentDetails{} + if protoimpl.UnsafeEnabled { + mi := &file_bip70_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -var xxx_messageInfo_PaymentDetails proto.InternalMessageInfo +func (x *PaymentDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} -const Default_PaymentDetails_Network string = "main" +func (*PaymentDetails) ProtoMessage() {} -func (m *PaymentDetails) GetNetwork() string { - if m != nil && m.Network != nil { - return *m.Network +func (x *PaymentDetails) ProtoReflect() protoreflect.Message { + mi := &file_bip70_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return Default_PaymentDetails_Network + return mi.MessageOf(x) } -func (m *PaymentDetails) GetOutputs() []*Output { - if m != nil { - return m.Outputs - } - return nil +// Deprecated: Use PaymentDetails.ProtoReflect.Descriptor instead. +func (*PaymentDetails) Descriptor() ([]byte, []int) { + return file_bip70_proto_rawDescGZIP(), []int{1} } -func (m *PaymentDetails) GetTime() uint64 { - if m != nil && m.Time != nil { - return *m.Time +type PaymentRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PaymentDetailsVersion uint32 `protobuf:"varint,1,opt,name=payment_details_version,json=paymentDetailsVersion,proto3" json:"payment_details_version,omitempty"` + PkiType string `protobuf:"bytes,2,opt,name=pki_type,json=pkiType,proto3" json:"pki_type,omitempty"` // none / x509+sha256 / x509+sha1 + PkiData []byte `protobuf:"bytes,3,opt,name=pki_data,json=pkiData,proto3" json:"pki_data,omitempty"` // depends on pki_type + SerializedPaymentDetails []byte `protobuf:"bytes,4,opt,name=serialized_payment_details,json=serializedPaymentDetails,proto3" json:"serialized_payment_details,omitempty"` // PaymentDetails + Signature []byte `protobuf:"bytes,5,opt,name=signature,proto3" json:"signature,omitempty"` // pki-dependent signature +} + +func (x *PaymentRequest) Reset() { + *x = PaymentRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_bip70_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return 0 } -func (m *PaymentDetails) GetExpires() uint64 { - if m != nil && m.Expires != nil { - return *m.Expires - } - return 0 +func (x *PaymentRequest) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *PaymentDetails) GetMemo() string { - if m != nil && m.Memo != nil { - return *m.Memo - } - return "" -} +func (*PaymentRequest) ProtoMessage() {} -func (m *PaymentDetails) GetPaymentUrl() string { - if m != nil && m.PaymentUrl != nil { - return *m.PaymentUrl +func (x *PaymentRequest) ProtoReflect() protoreflect.Message { + mi := &file_bip70_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return "" + return mi.MessageOf(x) } -type PaymentRequest struct { - PaymentDetailsVersion *uint32 `protobuf:"varint,1,opt,name=payment_details_version,json=paymentDetailsVersion,def=1" json:"payment_details_version,omitempty"` - PkiType *string `protobuf:"bytes,2,opt,name=pki_type,json=pkiType,def=none" json:"pki_type,omitempty"` - PkiData []byte `protobuf:"bytes,3,opt,name=pki_data,json=pkiData" json:"pki_data,omitempty"` - SerializedPaymentDetails []byte `protobuf:"bytes,4,req,name=serialized_payment_details,json=serializedPaymentDetails" json:"serialized_payment_details,omitempty"` - Signature []byte `protobuf:"bytes,5,opt,name=signature" json:"signature,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PaymentRequest) Reset() { *m = PaymentRequest{} } -func (m *PaymentRequest) String() string { return proto.CompactTextString(m) } -func (*PaymentRequest) ProtoMessage() {} +// Deprecated: Use PaymentRequest.ProtoReflect.Descriptor instead. func (*PaymentRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_de204c4c8d465ce4, []int{2} -} - -func (m *PaymentRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PaymentRequest.Unmarshal(m, b) -} -func (m *PaymentRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PaymentRequest.Marshal(b, m, deterministic) -} -func (m *PaymentRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PaymentRequest.Merge(m, src) -} -func (m *PaymentRequest) XXX_Size() int { - return xxx_messageInfo_PaymentRequest.Size(m) -} -func (m *PaymentRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PaymentRequest.DiscardUnknown(m) + return file_bip70_proto_rawDescGZIP(), []int{2} } -var xxx_messageInfo_PaymentRequest proto.InternalMessageInfo +type X509Certificates struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -const Default_PaymentRequest_PaymentDetailsVersion uint32 = 1 -const Default_PaymentRequest_PkiType string = "none" + Certificate [][]byte `protobuf:"bytes,1,rep,name=certificate,proto3" json:"certificate,omitempty"` // DER-encoded X.509 certificate chain +} -func (m *PaymentRequest) GetPaymentDetailsVersion() uint32 { - if m != nil && m.PaymentDetailsVersion != nil { - return *m.PaymentDetailsVersion +func (x *X509Certificates) Reset() { + *x = X509Certificates{} + if protoimpl.UnsafeEnabled { + mi := &file_bip70_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return Default_PaymentRequest_PaymentDetailsVersion } -func (m *PaymentRequest) GetPkiType() string { - if m != nil && m.PkiType != nil { - return *m.PkiType - } - return Default_PaymentRequest_PkiType +func (x *X509Certificates) String() string { + return protoimpl.X.MessageStringOf(x) } +func (*X509Certificates) ProtoMessage() {} -type X509Certificates struct { - Certificate [][]byte `protobuf:"bytes,1,rep,name=certificate" json:"certificate,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +func (x *X509Certificates) ProtoReflect() protoreflect.Message { + mi := &file_bip70_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *X509Certificates) Reset() { *m = X509Certificates{} } -func (m *X509Certificates) String() string { return proto.CompactTextString(m) } -func (*X509Certificates) ProtoMessage() {} +// Deprecated: Use X509Certificates.ProtoReflect.Descriptor instead. func (*X509Certificates) Descriptor() ([]byte, []int) { - return fileDescriptor_de204c4c8d465ce4, []int{3} + return file_bip70_proto_rawDescGZIP(), []int{3} } -func (m *X509Certificates) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_X509Certificates.Unmarshal(m, b) -} -func (m *X509Certificates) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_X509Certificates.Marshal(b, m, deterministic) -} -func (m *X509Certificates) XXX_Merge(src proto.Message) { - xxx_messageInfo_X509Certificates.Merge(m, src) -} -func (m *X509Certificates) XXX_Size() int { - return xxx_messageInfo_X509Certificates.Size(m) +type Payment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MerchantData []byte `protobuf:"bytes,1,opt,name=merchant_data,json=merchantData,proto3" json:"merchant_data,omitempty"` // From PaymentDetails.merchant_data + Transactions [][]byte `protobuf:"bytes,2,rep,name=transactions,proto3" json:"transactions,omitempty"` // Signed transactions that satisfy PaymentDetails.outputs + RefundTo []*Output `protobuf:"bytes,3,rep,name=refund_to,json=refundTo,proto3" json:"refund_to,omitempty"` // Where to send refunds, if a refund is necessary + Memo string `protobuf:"bytes,4,opt,name=memo,proto3" json:"memo,omitempty"` // Human-readable message for the merchant +} + +func (x *Payment) Reset() { + *x = Payment{} + if protoimpl.UnsafeEnabled { + mi := &file_bip70_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *X509Certificates) XXX_DiscardUnknown() { - xxx_messageInfo_X509Certificates.DiscardUnknown(m) + +func (x *Payment) String() string { + return protoimpl.X.MessageStringOf(x) } -var xxx_messageInfo_X509Certificates proto.InternalMessageInfo +func (*Payment) ProtoMessage() {} -func (m *X509Certificates) GetCertificate() [][]byte { - if m != nil { - return m.Certificate +func (x *Payment) ProtoReflect() protoreflect.Message { + mi := &file_bip70_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return nil + return mi.MessageOf(x) } -type Payment struct { - MerchantData []byte `protobuf:"bytes,1,opt,name=merchant_data,json=merchantData" json:"merchant_data,omitempty"` - Transactions [][]byte `protobuf:"bytes,2,rep,name=transactions" json:"transactions,omitempty"` - RefundTo []*Output `protobuf:"bytes,3,rep,name=refund_to,json=refundTo" json:"refund_to,omitempty"` - Memo *string `protobuf:"bytes,4,opt,name=memo" json:"memo,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Payment) Reset() { *m = Payment{} } -func (m *Payment) String() string { return proto.CompactTextString(m) } -func (*Payment) ProtoMessage() {} +// Deprecated: Use Payment.ProtoReflect.Descriptor instead. func (*Payment) Descriptor() ([]byte, []int) { - return fileDescriptor_de204c4c8d465ce4, []int{4} -} - -func (m *Payment) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Payment.Unmarshal(m, b) -} -func (m *Payment) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Payment.Marshal(b, m, deterministic) -} -func (m *Payment) XXX_Merge(src proto.Message) { - xxx_messageInfo_Payment.Merge(m, src) -} -func (m *Payment) XXX_Size() int { - return xxx_messageInfo_Payment.Size(m) -} -func (m *Payment) XXX_DiscardUnknown() { - xxx_messageInfo_Payment.DiscardUnknown(m) + return file_bip70_proto_rawDescGZIP(), []int{4} } -var xxx_messageInfo_Payment proto.InternalMessageInfo - +type PaymentACK struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Payment) GetTransactions() [][]byte { - if m != nil { - return m.Transactions - } - return nil + Payment *Payment `protobuf:"bytes,1,opt,name=payment,proto3" json:"payment,omitempty"` // Payment message that triggered this ACK + Memo string `protobuf:"bytes,2,opt,name=memo,proto3" json:"memo,omitempty"` // human-readable message for customer } -func (m *Payment) GetRefundTo() []*Output { - if m != nil { - return m.RefundTo +func (x *PaymentACK) Reset() { + *x = PaymentACK{} + if protoimpl.UnsafeEnabled { + mi := &file_bip70_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return nil } -func (m *Payment) GetMemo() string { - if m != nil && m.Memo != nil { - return *m.Memo - } - return "" +func (x *PaymentACK) String() string { + return protoimpl.X.MessageStringOf(x) } -type PaymentACK struct { - Payment *Payment `protobuf:"bytes,1,req,name=payment" json:"payment,omitempty"` - Memo *string `protobuf:"bytes,2,opt,name=memo" json:"memo,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PaymentACK) Reset() { *m = PaymentACK{} } -func (m *PaymentACK) String() string { return proto.CompactTextString(m) } -func (*PaymentACK) ProtoMessage() {} -func (*PaymentACK) Descriptor() ([]byte, []int) { - return fileDescriptor_de204c4c8d465ce4, []int{5} -} +func (*PaymentACK) ProtoMessage() {} -func (m *PaymentACK) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PaymentACK.Unmarshal(m, b) -} -func (m *PaymentACK) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PaymentACK.Marshal(b, m, deterministic) -} -func (m *PaymentACK) XXX_Merge(src proto.Message) { - xxx_messageInfo_PaymentACK.Merge(m, src) -} -func (m *PaymentACK) XXX_Size() int { - return xxx_messageInfo_PaymentACK.Size(m) -} -func (m *PaymentACK) XXX_DiscardUnknown() { - xxx_messageInfo_PaymentACK.DiscardUnknown(m) +func (x *PaymentACK) ProtoReflect() protoreflect.Message { + mi := &file_bip70_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_PaymentACK proto.InternalMessageInfo +// Deprecated: Use PaymentACK.ProtoReflect.Descriptor instead. +func (*PaymentACK) Descriptor() ([]byte, []int) { + return file_bip70_proto_rawDescGZIP(), []int{5} +} + +var File_bip70_proto protoreflect.FileDescriptor + +var file_bip70_proto_rawDesc = []byte{ + 0x0a, 0x0b, 0x62, 0x69, 0x70, 0x37, 0x30, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x6c, + 0x69, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x22, 0x38, 0x0a, 0x06, 0x4f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x22, 0xdf, 0x01, 0x0a, 0x0e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, + 0x2b, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, + 0x6d, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x12, 0x1f, + 0x0a, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x55, 0x72, 0x6c, 0x12, + 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x72, 0x63, 0x68, 0x61, 0x6e, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x63, 0x68, 0x61, 0x6e, 0x74, + 0x44, 0x61, 0x74, 0x61, 0x22, 0xda, 0x01, 0x0a, 0x0e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x61, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x19, 0x0a, 0x08, 0x70, 0x6b, 0x69, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x70, 0x6b, 0x69, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6b, + 0x69, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x6b, + 0x69, 0x44, 0x61, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x18, 0x73, 0x65, 0x72, 0x69, 0x61, + 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x34, 0x0a, 0x10, 0x58, 0x35, 0x30, 0x39, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x72, 0x63, 0x68, 0x61, 0x6e, 0x74, 0x5f, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6d, 0x65, 0x72, 0x63, + 0x68, 0x61, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0c, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x09, + 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x6f, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x4f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x52, 0x08, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x54, 0x6f, 0x12, 0x12, 0x0a, 0x04, + 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, + 0x22, 0x4e, 0x0a, 0x0a, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x41, 0x43, 0x4b, 0x12, 0x2c, + 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, + 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x62, 0x69, 0x70, 0x37, 0x30, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_bip70_proto_rawDescOnce sync.Once + file_bip70_proto_rawDescData = file_bip70_proto_rawDesc +) -func (m *PaymentACK) GetMemo() string { - if m != nil && m.Memo != nil { - return *m.Memo +func file_bip70_proto_rawDescGZIP() []byte { + file_bip70_proto_rawDescOnce.Do(func() { + file_bip70_proto_rawDescData = protoimpl.X.CompressGZIP(file_bip70_proto_rawDescData) + }) + return file_bip70_proto_rawDescData +} + +var file_bip70_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_bip70_proto_goTypes = []interface{}{ + (*Output)(nil), // 0: libwallet.Output + (*PaymentDetails)(nil), // 1: libwallet.PaymentDetails + (*PaymentRequest)(nil), // 2: libwallet.PaymentRequest + (*X509Certificates)(nil), // 3: libwallet.X509Certificates + (*Payment)(nil), // 4: libwallet.Payment + (*PaymentACK)(nil), // 5: libwallet.PaymentACK +} +var file_bip70_proto_depIdxs = []int32{ + 0, // 0: libwallet.PaymentDetails.outputs:type_name -> libwallet.Output + 0, // 1: libwallet.Payment.refund_to:type_name -> libwallet.Output + 4, // 2: libwallet.PaymentACK.payment:type_name -> libwallet.Payment + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_bip70_proto_init() } +func file_bip70_proto_init() { + if File_bip70_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_bip70_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Output); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bip70_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PaymentDetails); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bip70_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PaymentRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bip70_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*X509Certificates); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bip70_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Payment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bip70_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PaymentACK); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } - return "" -} - -func init() { - proto.RegisterType((*Output)(nil), "payments.Output") - proto.RegisterType((*PaymentDetails)(nil), "payments.PaymentDetails") - proto.RegisterType((*PaymentRequest)(nil), "payments.PaymentRequest") - proto.RegisterType((*X509Certificates)(nil), "payments.X509Certificates") - proto.RegisterType((*Payment)(nil), "payments.Payment") - proto.RegisterType((*PaymentACK)(nil), "payments.PaymentACK") -} - -func init() { proto.RegisterFile("bip70.proto", fileDescriptor_de204c4c8d465ce4) } - -var fileDescriptor_de204c4c8d465ce4 = []byte{ - // 499 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x53, 0x5f, 0x6f, 0xd3, 0x3e, - 0x14, 0x55, 0xd2, 0xfc, 0x9a, 0xf6, 0x36, 0xfb, 0x69, 0x58, 0x02, 0x3c, 0x84, 0xb6, 0x28, 0xbc, - 0x44, 0x20, 0xaa, 0x32, 0x81, 0xd0, 0x0a, 0x2f, 0x6c, 0x7b, 0x43, 0x88, 0xc9, 0x1a, 0x88, 0xb7, - 0xc8, 0x4b, 0xbd, 0x61, 0x35, 0xb1, 0x8d, 0x7d, 0x03, 0x94, 0xef, 0xc1, 0x27, 0x84, 0x0f, 0x82, - 0xf2, 0xaf, 0x61, 0x9b, 0x78, 0xb3, 0xcf, 0x3d, 0x39, 0xf7, 0xdc, 0x7b, 0x1c, 0x98, 0x5d, 0x48, - 0xf3, 0x72, 0x31, 0x37, 0x56, 0xa3, 0x26, 0x13, 0xc3, 0x37, 0xa5, 0x50, 0xe8, 0x92, 0x57, 0x30, - 0x7e, 0x5f, 0xa1, 0xa9, 0x90, 0xec, 0xc1, 0x98, 0x97, 0xba, 0x52, 0x48, 0xbd, 0xd8, 0x4b, 0x83, - 0xa5, 0xb7, 0x60, 0x1d, 0x40, 0xee, 0xc1, 0xd8, 0xe5, 0x56, 0x1a, 0xa4, 0x7e, 0xec, 0xa7, 0x11, - 0xeb, 0x6e, 0xc9, 0x6f, 0x0f, 0xfe, 0x3f, 0x6b, 0x95, 0x4e, 0x05, 0x72, 0x59, 0x38, 0xb2, 0x0f, - 0xa1, 0x12, 0xf8, 0x4d, 0xdb, 0x75, 0x23, 0x33, 0x5d, 0x06, 0x25, 0x97, 0x8a, 0xf5, 0x20, 0x79, - 0x0c, 0xa1, 0x6e, 0xfa, 0x39, 0xea, 0xc7, 0xa3, 0x74, 0x76, 0xb8, 0x3b, 0xef, 0xbd, 0xcc, 0x5b, - 0x23, 0xac, 0x27, 0x10, 0x02, 0x01, 0xca, 0x52, 0xd0, 0x51, 0xec, 0xa7, 0x01, 0x6b, 0xce, 0x84, - 0x42, 0x28, 0xbe, 0x1b, 0x69, 0x85, 0xa3, 0x41, 0x6d, 0x93, 0xf5, 0xd7, 0x9a, 0x5d, 0x8a, 0x52, - 0xd3, 0xff, 0xea, 0xb6, 0xac, 0x39, 0x93, 0x03, 0x98, 0x75, 0xea, 0x59, 0x65, 0x0b, 0x3a, 0x6e, - 0x4a, 0xd0, 0x41, 0x1f, 0x6c, 0x41, 0x1e, 0xc1, 0x4e, 0x29, 0x6c, 0xfe, 0x99, 0x2b, 0xcc, 0x56, - 0x1c, 0x39, 0x0d, 0x63, 0x2f, 0x8d, 0x58, 0xd4, 0x83, 0xa7, 0x1c, 0x79, 0xf2, 0x6b, 0x18, 0x93, - 0x89, 0x2f, 0x95, 0x70, 0x48, 0x8e, 0xe0, 0x7e, 0x2f, 0xbc, 0x6a, 0x27, 0xcf, 0xbe, 0x0a, 0xeb, - 0xa4, 0x56, 0xcd, 0xd8, 0x3b, 0x4b, 0xef, 0x19, 0xbb, 0x6b, 0xae, 0xad, 0xe6, 0x63, 0x5b, 0x27, - 0x07, 0x30, 0x31, 0x6b, 0x99, 0xe1, 0xc6, 0x08, 0xea, 0xb7, 0x2b, 0x52, 0x5a, 0x09, 0x16, 0x9a, - 0xb5, 0x3c, 0xdf, 0x18, 0x41, 0xf6, 0x5a, 0x42, 0x63, 0x67, 0xd4, 0xd8, 0xa9, 0x4b, 0xb5, 0x13, - 0xf2, 0x1a, 0x1e, 0x38, 0x61, 0x25, 0x2f, 0xe4, 0x0f, 0xb1, 0xca, 0x6e, 0x38, 0xa0, 0x41, 0x13, - 0x0e, 0x1d, 0x18, 0x37, 0xb2, 0x79, 0x08, 0x53, 0x27, 0xaf, 0x14, 0xc7, 0xca, 0x8a, 0x66, 0x4d, - 0x11, 0x1b, 0x80, 0xe4, 0x39, 0xec, 0x7e, 0x7a, 0xb1, 0x38, 0x3a, 0x11, 0x16, 0xe5, 0xa5, 0xcc, - 0x39, 0x0a, 0x47, 0x62, 0x98, 0xe5, 0xc3, 0x9d, 0x7a, 0xf1, 0x28, 0x8d, 0xd8, 0xdf, 0x50, 0xf2, - 0xd3, 0x83, 0xb0, 0x6b, 0x73, 0x7b, 0x99, 0xde, 0xed, 0x65, 0x92, 0x04, 0x22, 0xb4, 0x5c, 0x39, - 0x9e, 0xa3, 0xd4, 0xaa, 0x7d, 0x05, 0x11, 0xbb, 0x86, 0x91, 0xa7, 0x30, 0xb5, 0xe2, 0xb2, 0x52, - 0xab, 0x0c, 0x35, 0x1d, 0xfd, 0xe3, 0x99, 0x4c, 0x5a, 0xca, 0xb9, 0xde, 0x26, 0x1f, 0x0c, 0xc9, - 0x27, 0xef, 0x00, 0x3a, 0x5b, 0x6f, 0x4e, 0xde, 0x92, 0x27, 0x10, 0x76, 0x9f, 0x53, 0x2f, 0xf6, - 0xd3, 0xd9, 0xe1, 0x9d, 0x41, 0xae, 0x4f, 0xb6, 0x67, 0x6c, 0xe5, 0xfc, 0x41, 0xee, 0x38, 0x85, - 0x7d, 0x6d, 0xaf, 0xe6, 0x17, 0x12, 0x73, 0x2d, 0x55, 0xfb, 0x17, 0xe5, 0xba, 0x70, 0x5b, 0x99, - 0xe3, 0xf1, 0x59, 0x8d, 0xb9, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x27, 0x08, 0xfa, 0xe5, 0x68, - 0x03, 0x00, 0x00, + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_bip70_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_bip70_proto_goTypes, + DependencyIndexes: file_bip70_proto_depIdxs, + MessageInfos: file_bip70_proto_msgTypes, + }.Build() + File_bip70_proto = out.File + file_bip70_proto_rawDesc = nil + file_bip70_proto_goTypes = nil + file_bip70_proto_depIdxs = nil } diff --git a/bip70.proto b/bip70.proto index fcc4007..4c7437d 100644 --- a/bip70.proto +++ b/bip70.proto @@ -7,38 +7,40 @@ // syntax = "proto3"; +package libwallet; +option go_package = "/bip70"; // Generalized form of "send payment to this/these bitcoin addresses" message Output { - optional uint64 amount = 1 [default = 0]; // amount is integer-number-of-satoshis - required bytes script = 2; // usually one of the standard Script forms + uint64 amount = 1; // amount is integer-number-of-satoshis + bytes script = 2; // usually one of the standard Script forms } message PaymentDetails { - optional string network = 1 [default = "main"]; // "main" or "test" + string network = 1; // "main" or "test" repeated Output outputs = 2; // Where payment should be sent - required uint64 time = 3; // Timestamp; when payment request created - optional uint64 expires = 4; // Timestamp; when this request should be considered invalid - optional string memo = 5; // Human-readable description of request for the customer - optional string payment_url = 6; // URL to send Payment and get PaymentACK - optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message + uint64 time = 3; // Timestamp; when payment request created + uint64 expires = 4; // Timestamp; when this request should be considered invalid + string memo = 5; // Human-readable description of request for the customer + string payment_url = 6; // URL to send Payment and get PaymentACK + bytes merchant_data = 7; // Arbitrary data to include in the Payment message } message PaymentRequest { - optional uint32 payment_details_version = 1 [default = 1]; - optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1 - optional bytes pki_data = 3; // depends on pki_type - required bytes serialized_payment_details = 4; // PaymentDetails - optional bytes signature = 5; // pki-dependent signature + uint32 payment_details_version = 1; + string pki_type = 2; // none / x509+sha256 / x509+sha1 + bytes pki_data = 3; // depends on pki_type + bytes serialized_payment_details = 4; // PaymentDetails + bytes signature = 5; // pki-dependent signature } message X509Certificates { repeated bytes certificate = 1; // DER-encoded X.509 certificate chain } message Payment { - optional bytes merchant_data = 1; // From PaymentDetails.merchant_data + bytes merchant_data = 1; // From PaymentDetails.merchant_data repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary - optional string memo = 4; // Human-readable message for the merchant + string memo = 4; // Human-readable message for the merchant } message PaymentACK { - required Payment payment = 1; // Payment message that triggered this ACK - optional string memo = 2; // human-readable message for customer + Payment payment = 1; // Payment message that triggered this ACK + string memo = 2; // human-readable message for customer } diff --git a/challenge_keys.go b/challenge_keys.go index db00be6..97e3cba 100644 --- a/challenge_keys.go +++ b/challenge_keys.go @@ -2,8 +2,6 @@ package libwallet import ( "bytes" - "crypto/aes" - "crypto/cipher" "crypto/sha256" "encoding/binary" "encoding/hex" @@ -65,7 +63,7 @@ func (k *ChallengePrivateKey) DecryptKey(encryptedKey string, network *Network) } birthdayBytes := make([]byte, 2) - rawPubEph := make([]byte, 33) + rawPubEph := make([]byte, serializedPublicKeyLength) ciphertext := make([]byte, 64) recoveryCodeSalt := make([]byte, 8) @@ -76,7 +74,7 @@ func (k *ChallengePrivateKey) DecryptKey(encryptedKey string, network *Network) birthday := binary.BigEndian.Uint16(birthdayBytes) n, err = reader.Read(rawPubEph) - if err != nil || n != 33 { + if err != nil || n != serializedPublicKeyLength { return nil, errors.Errorf("decrypting key: failed to read pubeph") } @@ -90,25 +88,11 @@ func (k *ChallengePrivateKey) DecryptKey(encryptedKey string, network *Network) return nil, errors.Errorf("decrypting key: failed to read recoveryCodeSalt") } - pubEph, err := btcec.ParsePubKey(rawPubEph, btcec.S256()) + plaintext, err := decryptWithPrivKey(k.key, rawPubEph, ciphertext) if err != nil { - return nil, errors.Wrapf(err, "decrypting key: failed to parse pub eph") + return nil, err } - sharedSecret, _ := pubEph.ScalarMult(pubEph.X, pubEph.Y, k.key.D.Bytes()) - - iv := rawPubEph[len(rawPubEph)-aes.BlockSize:] - - block, err := aes.NewCipher(paddedSerializeBigInt(32, sharedSecret)) - if err != nil { - return nil, errors.Wrapf(err, "challenge_key: failed to generate encryption key") - } - - plaintext := make([]byte, len(ciphertext)) - - mode := cipher.NewCBCDecrypter(block, iv) - mode.CryptBlocks(plaintext, ciphertext) - rawPrivKey := plaintext[0:32] rawChainCode := plaintext[32:] diff --git a/challenge_keys_test.go b/challenge_keys_test.go index dff085c..83baad0 100644 --- a/challenge_keys_test.go +++ b/challenge_keys_test.go @@ -3,6 +3,8 @@ package libwallet import ( "reflect" "testing" + + "github.com/btcsuite/btcutil/base58" ) func TestNewChallengePrivateKey(t *testing.T) { @@ -29,11 +31,11 @@ func TestNewChallengePrivateKey(t *testing.T) { func TestChallengeKeyCrypto(t *testing.T) { const birthday = 376 - network := Mainnet() + network := Regtest() salt := randomBytes(8) privKey, _ := NewHDPrivateKey(randomBytes(32), network) - challengePrivKey := NewChallengePrivateKey([]byte("viva peron"), salt) + challengePrivKey := NewChallengePrivateKey([]byte("a very good password"), salt) encryptedKey, err := challengePrivKey.PubKey().EncryptKey(privKey, salt, birthday) if err != nil { @@ -51,4 +53,39 @@ func TestChallengeKeyCrypto(t *testing.T) { if birthday != decryptedKey.Birthday { t.Fatalf("birthdays dont match: expected %v got %v", birthday, decryptedKey.Birthday) } -} \ No newline at end of file +} + +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.DecryptKey(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) + } +} diff --git a/challenge_public_key.go b/challenge_public_key.go index bf578b3..fee0c31 100644 --- a/challenge_public_key.go +++ b/challenge_public_key.go @@ -2,8 +2,6 @@ package libwallet import ( "bytes" - "crypto/aes" - "crypto/cipher" "encoding/binary" "github.com/btcsuite/btcd/btcec" @@ -28,10 +26,10 @@ func NewChallengePublicKeyFromSerialized(serializedKey []byte) (*ChallengePublic func (k *ChallengePublicKey) EncryptKey(privKey *HDPrivateKey, recoveryCodeSalt []byte, birthday int) (string, error) { const ( - chainCodeStart = 13 + chainCodeStart = 13 chainCodeLength = 32 - privKeyStart = 46 - privKeyLength = 32 + privKeyStart = 46 + privKeyLength = 32 ) rawHDKey := base58.Decode(privKey.String()) @@ -42,35 +40,21 @@ func (k *ChallengePublicKey) EncryptKey(privKey *HDPrivateKey, recoveryCodeSalt return "", errors.Errorf("failed to encrypt key: expected payload of 64 bytes, found %v", len(plaintext)) } - privEph, err := btcec.NewPrivateKey(btcec.S256()) + pubEph, ciphertext, err := encryptWithPubKey(k.pubKey, plaintext) if err != nil { - return "", errors.Wrapf(err, "failed to encrypt key") + return "", err } - sharedSecret, _ := k.pubKey.ScalarMult(k.pubKey.X, k.pubKey.Y, privEph.D.Bytes()) - serializedPubkey := privEph.PubKey().SerializeCompressed() - iv := serializedPubkey[len(serializedPubkey)-aes.BlockSize:] - - block, err := aes.NewCipher(paddedSerializeBigInt(32, sharedSecret)) - if err != nil { - return "", errors.Wrapf(err, "challenge_public_key: failed to generate encryption key") - } - - ciphertext := make([]byte, len(plaintext)) - - mode := cipher.NewCBCEncrypter(block, iv) - mode.CryptBlocks(ciphertext, plaintext) - birthdayBytes := make([]byte, 2) binary.BigEndian.PutUint16(birthdayBytes, uint16(birthday)) - result := make([]byte, 0, 1+2+33+len(ciphertext)+len(recoveryCodeSalt)) + result := make([]byte, 0, 1+2+serializedPublicKeyLength+len(ciphertext)+len(recoveryCodeSalt)) buf := bytes.NewBuffer(result) buf.WriteByte(2) buf.Write(birthdayBytes) - buf.Write(privEph.PubKey().SerializeCompressed()) + buf.Write(pubEph.SerializeCompressed()) buf.Write(ciphertext) buf.Write(recoveryCodeSalt) return base58.Encode(buf.Bytes()), nil -} \ No newline at end of file +} diff --git a/ek_html.go b/ek_html.go new file mode 100644 index 0000000..6eccebc --- /dev/null +++ b/ek_html.go @@ -0,0 +1,289 @@ +package libwallet + +func getEmergencyKitHTML() string { + return ` + + + + + + Emergency Kit + + + + + + + +
+
+

Emergency Kit

+ Created on {{.CurrentDate}} +
+ +
+

Verification code

+ {{.VerificationCode}} +
+
+ +
+

About this document

+ +

Here you'll find the encrypted information you need to transfer your money out of your Muun wallet without + requiring collaboration from anyone, including Muun's own software and servers.

+ +

This includes all your private keys (securely encrypted with your Recovery Code) and some additional data related + to your wallet.

+ +

With this document and your recovery code at hand, you have complete ownership of your money. Nobody else has + all the pieces. This is why Bitcoin was created: to give people full control of the money they rightly own.

+
+ +
+

Recovering your money

+ +

To move forward with the transfer of funds, we recommend using our + open-source Recovery Tool. It's available for the whole world to + download and examine, and it will always be.

+ +

We created it to assist you with the process, but nothing stops you from doing it manually if you're so + inclined.

+ +

Go to github.com/muun/recovery and follow the instructions to easily transfer your money to a Bitcoin + address of your choosing.

+
+ +
+

Recovery information

+ +

This is what you'll need for the transfer, plus your recovery code. If these random-seeming codes look daunting, + don't worry: the recovery tool will take care of everything.

+
+ +
+

First Encrypted Private Key

+
{{.FirstEncryptedKey}}
+ +

Second Encrypted Private Key

+
{{.SecondEncryptedKey}}
+ +

Output descriptors

+
+ sh(wsh(multi(2, first key/1'/1'/0/*, second key/1'/1'/0/*)))
+ sh(wsh(multi(2, first key/1'/1'/1/*, second key/1'/1'/1/*)))
+ sh(wsh(multi(2, first key/1'/1'/2/*/*, second key/1'/1'/2/*/*)))
+ wsh(multi(2, first key/1'/1'/0/*, second key/1'/1'/0/*))
+ wsh(multi(2, first key/1'/1'/1/*, second key/1'/1'/1/*))
+ wsh(multi(2, first key/1'/1'/2/*/*, second key/1'/1'/2/*/*)) +
+
+ +
+

Some questions you might have

+ +

Can I print this document?

+ +

You can, but we recommend storing it online in a service such as Google Drive, iCloud, OneDrive or Dropbox. + These providers have earned their users' trust by being always available and safeguarding data with strong + security practices. They are also free.

+ +

If you decide to print it, be sure to keep it safely away from where you store your recovery code. Remember: + a person with both pieces can take control of your funds.

+ +

What if I lose my emergency kit?

+ +

Don't panic. Your money is not lost. It's all there, in the Bitcoin blockchain, waiting for you. Use our Android + or iOS applications and go to the Security Center to create a new kit.

+ +

What if somebody sees this document?

+

+ As long as you keep your recovery code hidden, this document is harmless. All the data it contains is safely + encrypted, and only your recovery code can decrypt it to a usable form.

+ +

Still, we recommend that you keep it where only you can see it. If you really fear losing it or want to share it + for some other reason, only do so with people that enjoy your absolute trust.

+ +

Why don't I have a mnemonic phrase?

+ +

If you've been involved with Bitcoin for some time, you've probably seen mnemonics and been told to rely on them. + As of this writing, many wallets still use the technique.

+ +

There's nothing inherently wrong with mnemonics, but they have been rendered obsolete. The twelve words are + simply not enough to encode all the information a modern Bitcoin wallet requires to operate, and the problem will + only get worse as technology advances. Already there are improvements taking shape that would make mnemonic + recovery not only harder, but impossible.

+ +

For this reason, we decided to guarantee full ownership using a safer, more flexible and future-proof technique. + This way, we'll be able to keep up with technological improvements and continue to provide + state-of-the-art software.

+ +

I have other questions

+ +

We'll be glad to answer them. Contact us at support@muun.com + to let us know.

+
+ + + + ` +} diff --git a/emergency_kit.go b/emergency_kit.go new file mode 100644 index 0000000..2754d18 --- /dev/null +++ b/emergency_kit.go @@ -0,0 +1,82 @@ +package libwallet + +import ( + "bytes" + "crypto/rand" + "html/template" + "io" + "time" + + "github.com/pkg/errors" +) + +// EKInput input struct to fill the PDF +type EKInput struct { + FirstEncryptedKey string + SecondEncryptedKey string +} + +// EKTemplate full struct to fill the PDF +type EKTemplate struct { + FirstEncryptedKey string + SecondEncryptedKey string + VerificationCode string + CurrentDate string +} + +// EKOutput with the html as string and the verification code +type EKOutput struct { + HTML string + VerificationCode string +} + +// GenerateEmergencyKitHTML returns the html as a string along with the verification code +func GenerateEmergencyKitHTML(ekParams *EKInput) (*EKOutput, error) { + + html := getEmergencyKitHTML() + htmlBuf := new(bytes.Buffer) + + tmpl, err := template.New("EmergencyKit").Parse(html) + if err != nil { + return nil, errors.Wrapf(err, "Failed to create new template from html") + } + + verificationCode := getRandomVerificationCode() + currentDate := time.Now() + + fullTemplate := EKTemplate{ + FirstEncryptedKey: ekParams.FirstEncryptedKey, + SecondEncryptedKey: ekParams.SecondEncryptedKey, + VerificationCode: verificationCode, + // Careful: do not change these format values. See the doc more info: https://golang.org/pkg/time/#pkg-constants + CurrentDate: currentDate.Format("2006/01/02"), // Format date to YYYY/MM/DD + } + + err = tmpl.Execute(htmlBuf, fullTemplate) + if err != nil { + return nil, errors.Wrapf(err, "Failed to fill PDF with custom data") + } + + return &EKOutput{ + htmlBuf.String(), + verificationCode, + }, nil +} + +func getRandomVerificationCode() string { + const length = 6 + + charset := [...]byte{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'} + result := make([]byte, length) + + n, err := io.ReadAtLeast(rand.Reader, result, length) + if n != length { + panic(err) + } + + for i := 0; i < len(result); i++ { + result[i] = charset[int(result[i])%len(charset)] + } + + return string(result) +} diff --git a/encodings_test.go b/encodings_test.go index 3802cc5..46d4c1d 100644 --- a/encodings_test.go +++ b/encodings_test.go @@ -43,4 +43,4 @@ func Test_paddedSerializeBigInt(t *testing.T) { } }) } -} \ No newline at end of file +} diff --git a/encrypt.go b/encrypt.go new file mode 100644 index 0000000..337d794 --- /dev/null +++ b/encrypt.go @@ -0,0 +1,400 @@ +package libwallet + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/sha256" + "encoding/binary" + "io" + "math" + "math/big" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcutil/base58" + "github.com/pkg/errors" +) + +const serializedPublicKeyLength = btcec.PubKeyBytesLenCompressed +const PKEncryptionVersion = 1 + +// maxDerivationPathLen is a safety limit to avoid stupid size allocations +const maxDerivationPathLen = 1000 + +// maxSignatureLen is a safety limit to avoid giant allocations +const maxSignatureLen = 200 + +// minNonceLen is the safe minimum we'll set for the nonce. This is the default for golang, but it's not exposed. +const minNonceLen = 12 + +type Encrypter interface { + // Encrypt the payload and return a string with the necesary information for decryption + Encrypt(payload []byte) (string, error) +} + +type Decrypter interface { + // Decrypt a payload generated by Encrypter + Decrypt(payload string) ([]byte, error) +} + +type hdPubKeyEncrypter struct { + receiverKey *HDPublicKey + senderKey *HDPrivateKey +} + +func addVariableBytes(writer io.Writer, data []byte) error { + if len(data) > math.MaxUint16 { + return errors.Errorf("data length can't exceeed %v", math.MaxUint16) + } + + dataLen := uint16(len(data)) + err := binary.Write(writer, binary.BigEndian, &dataLen) + if err != nil { + return errors.Wrapf(err, "failed to write var bytes len") + } + + n, err := writer.Write(data) + if err != nil || n != len(data) { + return errors.Errorf("failed to write var bytes") + } + + return nil +} + +func (e *hdPubKeyEncrypter) Encrypt(payload []byte) (string, error) { + // Uses AES128-GCM with associated data. ECDHE is used for key exchange and ECDSA for authentication. + // The goal is to be able to send an arbitrary message to a 3rd party or our future selves via + // an intermediary which has knowledge of public keys for all parties involved. + // + // Conceptually, what we do is: + // 1. Sign the payload using the senders private key so the receiver can check it's authentic + // The signature also covers the receivers public key to avoid payload reuse by the intermediary + // 2. Establish an encryption key via ECDH given the receivers pub key + // 3. Encrypt the payload and signature using AES with a new random nonce + // 4. Add the metadata the receiver will need to decode the message: + // * The derivation path for his pub key + // * The ephemeral key used for ECDH + // * The version code of this scheme + // 5. HMAC the encrypted payload and the metadata so the receiver can check it hasn't been tampered + // 6. Add the nonce to the payload so the receiver can actually decrypt the message. + // The nonce can't be covered by the HMAC since it's used to generate it. + // 7. Profit! + // + // The implementation actually use an AES128-GCM with is an AEAD, so the encryption and HMAC all happen + // at the same time. + + signingKey, err := e.senderKey.key.ECPrivKey() + if err != nil { + return "", errors.Wrapf(err, "Encrypt: failed to extract signing key") + } + + encryptionKey, err := e.receiverKey.key.ECPubKey() + if err != nil { + return "", errors.Wrapf(err, "Encrypt: failed to extract pub key") + } + + // Sign "payload || encryptionKey" to protect against payload reuse by 3rd parties + signaturePayload := make([]byte, 0, len(payload)+serializedPublicKeyLength) + signaturePayload = append(signaturePayload, payload...) + signaturePayload = append(signaturePayload, encryptionKey.SerializeCompressed()...) + hash := sha256.Sum256(signaturePayload) + senderSignature, err := btcec.SignCompact(btcec.S256(), signingKey, hash[:], false) + if err != nil { + return "", errors.Wrapf(err, "Encrypt: failed to sign payload") + } + + // plaintext is "senderSignature || payload" + plaintext := bytes.NewBuffer(make([]byte, 0, 2+len(payload)+2+len(senderSignature))) + err = addVariableBytes(plaintext, senderSignature) + if err != nil { + return "", errors.Wrapf(err, "Encrypter: failed to add senderSignature") + } + + err = addVariableBytes(plaintext, payload) + if err != nil { + return "", errors.Wrapf(err, "Encrypter: failed to add payload") + } + + pubEph, sharedSecret, err := generateSharedEncryptionSecretForAES(encryptionKey) + if err != nil { + return "", errors.Wrapf(err, "Encrypt: failed to generate shared encryption key") + } + + blockCipher, err := aes.NewCipher(sharedSecret) + if err != nil { + return "", errors.Wrapf(err, "Encrypt: new aes failed") + } + + gcm, err := cipher.NewGCM(blockCipher) + if err != nil { + return "", errors.Wrapf(err, "Encrypt: new gcm failed") + } + + nonce := randomBytes(gcm.NonceSize()) + + // additionalData is "version || pubEph || receiverKeyPath || nonceLen" + additionalDataLen := 1 + serializedPublicKeyLength + 2 + len(e.receiverKey.Path) + 2 + result := bytes.NewBuffer(make([]byte, 0, additionalDataLen)) + result.WriteByte(PKEncryptionVersion) + result.Write(pubEph.SerializeCompressed()) + + err = addVariableBytes(result, []byte(e.receiverKey.Path)) + if err != nil { + return "", errors.Wrapf(err, "Encrypt: failed to add receiver path") + } + + nonceLen := uint16(len(nonce)) + err = binary.Write(result, binary.BigEndian, &nonceLen) + if err != nil { + return "", errors.Wrapf(err, "Encrypt: failed to add nonce len") + } + + ciphertext := gcm.Seal(nil, nonce, plaintext.Bytes(), result.Bytes()) + + // result is "additionalData || nonce || ciphertext" + n, err := result.Write(nonce) + if err != nil || n != len(nonce) { + return "", errors.Errorf("Encrypt: failed to add nonce") + } + + n, err = result.Write(ciphertext) + if err != nil || n != len(ciphertext) { + return "", errors.Errorf("Encrypt: failed to add ciphertext") + } + + return base58.Encode(result.Bytes()), nil +} + +// hdPrivKeyDecrypter holds the keys for validation and decryption of messages using Muun's scheme +type hdPrivKeyDecrypter struct { + receiverKey *HDPrivateKey + + // senderKey optionally holds the pub key used by sender + // If the sender is the same as the receiver, set this to nil and set fromSelf to true. + // If the sender is unknown, set this to nil. If so, the authenticity of the message won't be validated. + senderKey *PublicKey + + // fromSelf is true if this message is from yourself + fromSelf bool +} + +func extractVariableBytes(reader *bytes.Reader, limit int) ([]byte, error) { + var len uint16 + err := binary.Read(reader, binary.BigEndian, &len) + if err != nil || int(len) > limit || int(len) > reader.Len() { + return nil, errors.Errorf("failed to read byte array len") + } + + result := make([]byte, len) + n, err := reader.Read(result) + if err != nil || n != int(len) { + return nil, errors.Errorf("failed to extract byte array") + } + + return result, nil +} + +func extractVariableString(reader *bytes.Reader, limit int) (string, error) { + bytes, err := extractVariableBytes(reader, limit) + return string(bytes), err +} + +func (d *hdPrivKeyDecrypter) Decrypt(payload string) ([]byte, error) { + // Uses AES128-GCM with associated data. ECDHE is used for key exchange and ECDSA for authentication. + // See Encrypt further up for an in depth dive into the scheme used + + decoded := base58.Decode(payload) + reader := bytes.NewReader(decoded) + version, err := reader.ReadByte() + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to read version byte") + } + if version != PKEncryptionVersion { + return nil, errors.Errorf("Decrypt: found key version %v, expected %v", + version, PKEncryptionVersion) + } + + rawPubEph := make([]byte, serializedPublicKeyLength) + n, err := reader.Read(rawPubEph) + if err != nil || n != serializedPublicKeyLength { + return nil, errors.Errorf("Decrypt: failed to read pubeph") + } + + receiverPath, err := extractVariableString(reader, maxDerivationPathLen) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to extract receiver path") + } + + // additionalDataSize is Whatever I've read so far plus two bytes for the nonce len + additionalDataSize := len(decoded) - reader.Len() + 2 + + minCiphertextLen := 2 // an empty sig with no plaintext + nonce, err := extractVariableBytes(reader, reader.Len()-minCiphertextLen) + if err != nil || len(nonce) < minNonceLen { + return nil, errors.Errorf("Decrypt: failed to read nonce") + } + + // What's left is the ciphertext + ciphertext := make([]byte, reader.Len()) + _, err = reader.Read(ciphertext) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to read ciphertext") + } + + receiverKey, err := d.receiverKey.DeriveTo(receiverPath) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to derive receiver key to path %v", receiverPath) + } + + encryptionKey, err := receiverKey.key.ECPrivKey() + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to extract encryption key") + } + + var verificationKey *btcec.PublicKey + if d.fromSelf { + // Use the derived receiver key if the sender key is not provided + verificationKey, err = receiverKey.PublicKey().key.ECPubKey() + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to extract verification key") + } + } else if d.senderKey != nil { + verificationKey = d.senderKey.key + } + + sharedSecret, err := recoverSharedEncryptionSecretForAES(encryptionKey, rawPubEph) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to recover shared secret") + } + + blockCipher, err := aes.NewCipher(sharedSecret) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: new aes failed") + } + + gcm, err := cipher.NewGCMWithNonceSize(blockCipher, len(nonce)) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: new gcm failed") + } + + plaintext, err := gcm.Open(nil, nonce, ciphertext, decoded[:additionalDataSize]) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: AEAD failed") + } + + plaintextReader := bytes.NewReader(plaintext) + + sig, err := extractVariableBytes(plaintextReader, maxSignatureLen) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to read sig") + } + + data, err := extractVariableBytes(plaintextReader, plaintextReader.Len()) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to extract user data") + } + + signatureData := make([]byte, 0, len(sig)+serializedPublicKeyLength) + signatureData = append(signatureData, data...) + signatureData = append(signatureData, encryptionKey.PubKey().SerializeCompressed()...) + hash := sha256.Sum256(signatureData) + signatureKey, _, err := btcec.RecoverCompact(btcec.S256(), sig, hash[:]) + if err != nil { + return nil, errors.Wrapf(err, "Decrypt: failed to verify signature") + } + if verificationKey != nil && !signatureKey.IsEqual(verificationKey) { + return nil, errors.Errorf("Decrypt: signing key mismatch") + } + + return data, nil +} + +// Assert hdPubKeyEncrypter fulfills Encrypter interface +var _ Encrypter = (*hdPubKeyEncrypter)(nil) + +// Assert hdPrivKeyDecrypter fulfills Decrypter interface +var _ Decrypter = (*hdPrivKeyDecrypter)(nil) + +// encryptWithPubKey encrypts a message using a pubKey +// It uses ECDHE/AES/CBC leaving padding up to the caller. +func encryptWithPubKey(pubKey *btcec.PublicKey, plaintext []byte) (*btcec.PublicKey, []byte, error) { + // Use deprecated ECDH for compat + pubEph, sharedSecret, err := generateSharedEncryptionSecret(pubKey) + if err != nil { + return nil, nil, err + } + serializedPubkey := pubEph.SerializeCompressed() + iv := serializedPubkey[len(serializedPubkey)-aes.BlockSize:] + + ciphertext, err := encryptAesCbcNoPadding(paddedSerializeBigInt(aesKeySize, sharedSecret), iv, plaintext) + if err != nil { + return nil, nil, errors.Wrapf(err, "encryptWithPubKey: encrypt failed") + } + + return pubEph, ciphertext, nil +} + +// generateSharedEncryptionSecret performs a ECDH with pubKey +// Deprecated: this function is unsafe and generateSharedEncryptionSecretForAES should be used +func generateSharedEncryptionSecret(pubKey *btcec.PublicKey) (*btcec.PublicKey, *big.Int, error) { + privEph, err := btcec.NewPrivateKey(btcec.S256()) + if err != nil { + return nil, nil, errors.Wrapf(err, "generateSharedEncryptionSecretForAES: failed to generate key") + } + + sharedSecret, _ := pubKey.ScalarMult(pubKey.X, pubKey.Y, privEph.D.Bytes()) + + return privEph.PubKey(), sharedSecret, nil +} + +// generateSharedEncryptionSecret performs a ECDH with pubKey and produces a secret usable with AES +func generateSharedEncryptionSecretForAES(pubKey *btcec.PublicKey) (*btcec.PublicKey, []byte, error) { + privEph, sharedSecret, err := generateSharedEncryptionSecret(pubKey) + if err != nil { + return nil, nil, err + } + + hash := sha256.Sum256(paddedSerializeBigInt(aesKeySize, sharedSecret)) + return privEph, hash[:], nil +} + +// decryptWithPrivKey decrypts a message encrypted to a pubKey using the corresponding privKey +// It uses ECDHE/AES/CBC leaving padding up to the caller. +func decryptWithPrivKey(privKey *btcec.PrivateKey, rawPubEph []byte, ciphertext []byte) ([]byte, error) { + // Use deprecated ECDH for compat + sharedSecret, err := recoverSharedEncryptionSecret(privKey, rawPubEph) + if err != nil { + return nil, err + } + + iv := rawPubEph[len(rawPubEph)-aes.BlockSize:] + + plaintext, err := decryptAesCbcNoPadding(paddedSerializeBigInt(aesKeySize, sharedSecret), iv, ciphertext) + if err != nil { + return nil, errors.Wrapf(err, "decryptWithPrivKey: failed to decrypt") + } + + return plaintext, nil +} + +// recoverSharedEncryptionSecret performs an ECDH to recover the encryption secret meant for privKey from rawPubEph +// Deprecated: this function is unsafe and recoverSharedEncryptionSecretForAES should be used +func recoverSharedEncryptionSecret(privKey *btcec.PrivateKey, rawPubEph []byte) (*big.Int, error) { + pubEph, err := btcec.ParsePubKey(rawPubEph, btcec.S256()) + if err != nil { + return nil, errors.Wrapf(err, "recoverSharedEncryptionSecretForAES: failed to parse pub eph") + } + + sharedSecret, _ := pubEph.ScalarMult(pubEph.X, pubEph.Y, privKey.D.Bytes()) + return sharedSecret, nil +} + +func recoverSharedEncryptionSecretForAES(privKey *btcec.PrivateKey, rawPubEph []byte) ([]byte, error) { + sharedSecret, err := recoverSharedEncryptionSecret(privKey, rawPubEph) + if err != nil { + return nil, err + } + + hash := sha256.Sum256(paddedSerializeBigInt(aesKeySize, sharedSecret)) + return hash[:], nil +} diff --git a/encrypt_test.go b/encrypt_test.go new file mode 100644 index 0000000..d421d42 --- /dev/null +++ b/encrypt_test.go @@ -0,0 +1,230 @@ +package libwallet + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/sha256" + "encoding/hex" + "strings" + "testing" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcutil/base58" +) + +func TestPublicKeyEncryption(t *testing.T) { + + network := Mainnet() + senderKey, _ := NewHDPrivateKey(randomBytes(32), network) + receiverKey, _ := NewHDPrivateKey(randomBytes(32), network) + + payload := randomBytes(178) + + ciphertext, err := senderKey.EncrypterTo(receiverKey.PublicKey()).Encrypt(payload) + if err != nil { + t.Fatal(err) + } + + ecKey, _ := senderKey.PublicKey().key.ECPubKey() + publicKey := &PublicKey{ecKey} + plaintext, err := receiverKey.DecrypterFrom(publicKey).Decrypt(ciphertext) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(plaintext, payload) { + t.Fatalf("decrypted payload differed from original\ndecrypted %v\noriginal %v", + hex.EncodeToString(plaintext), + hex.EncodeToString(payload)) + } + + // If we don't know who the sender was + plaintext, err = receiverKey.DecrypterFrom(nil).Decrypt(ciphertext) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(plaintext, payload) { + t.Fatalf("decrypted payload differed from original\ndecrypted %v\noriginal %v", + hex.EncodeToString(plaintext), + hex.EncodeToString(payload)) + } + + badKey, _ := NewHDPrivateKey(randomBytes(32), network) + badEcKey, _ := badKey.PublicKey().key.ECPubKey() + badPubKey := &PublicKey{badEcKey} + _, err = receiverKey.DecrypterFrom(badPubKey).Decrypt(ciphertext) + if err == nil { + t.Fatal("Expected decryption from bad sender key to fail") + } + + derivedSenderKey, _ := senderKey.DerivedAt(10, false) + ciphertext, err = derivedSenderKey.Encrypter().Encrypt(payload) + if err != nil { + t.Fatal(err) + } + + plaintext, err = senderKey.Decrypter().Decrypt(ciphertext) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(plaintext, payload) { + t.Fatalf("decrypted payload differed from original\ndecrypted %v\noriginal %v", + hex.EncodeToString(plaintext), + hex.EncodeToString(payload)) + } +} + +func TestPublicKeyEncryptionV1(t *testing.T) { + const ( + priv = "xprv9s21ZrQH143K2DAjx7FiAo2GQAQ5g7GrPYkTB2RaCd2Ei5ZH7f9cbREHiZTCc1FPn9HKuviUHk8sf5cW3dhYjz6W6XPjXNHu5mLpT5oRH1j" + ciphertext = "AMWm2L3YjA7myBTQQgiZi9F5g1NzaaupkPq1y7csUkf7WLXwnPYjkmy5KjVkyTKjaSXPwjx2zmX9Augzwwh89AsWYTv7KfJTXTj3Lx2mNZgmxJ7eezaJyRHv4koQaEmRykSoVE4esjWK779Sac28kCstkqDMPDYeNud5H4ApetF4BvhvPJyMaVn4RHYSAGzBzMcBV7WxYoRveKHqU9LbAfhCndPtRSVZyTVXY8iE3EvQJFeZVyYdovPK67aHsXWRdi8QCinMQSG21TMmhs7GQAh6iB26X2ABcVFJRGeEKE2coAsfuAHzcAMZ3CdzGgVAm7rrQw13W3XpxwwjWVatH9Jm9H4TrnnnLxRCsBoSKDvA1hmH8a2UG9iMxkhsBVMPzNRMy4Bg4MHk8WyRo3bwCLSVJUFFEciQ3mUneHprezzbVZio" + plaintextHex = "ca4dabb05a47d3ab306c1fad895d97b06dc30564191e610f9b254b1a1d0a536b6eca2b83d0d17d67aaad2a958fe6a6557ad5b26f44e12e7662f47a4e4fd6f482b68a83cd140ad4ded43b90a2c2cf349af84d828b1f961901616b4c4cb01f761bd277ad0d3d90506065aef76b930a962fcb90f2f009898c0d55cd07b5e01c355a9067937185fa9237d03e5ed4243e1bf0f8a959c72a83cbb1729b679cbd660052dd2dd3096b0f19e9275ac459b94d02a95642" + ) + + privKey, _ := NewHDPrivateKeyFromString(priv, "m", Mainnet()) + plaintext, _ := hex.DecodeString(plaintextHex) + + decrypted, err := privKey.Decrypter().Decrypt(ciphertext) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(plaintext, decrypted) { + t.Fatalf("decrypted payload differed from original\ndecrypted %v\noriginal %v", + hex.EncodeToString(decrypted), + hex.EncodeToString(plaintext)) + } + + _, err = privKey.Encrypter().Encrypt(decrypted) + if err != nil { + t.Fatal(err) + } + + // Since we use a random key every time, comparing cipher texts makes no sense +} + +func TestPublicKeyDecryptV1(t *testing.T) { + + const ( + privHex = "xprv9s21ZrQH143K36uECEJcmTnxSXfHjT9jdb7FpMoUJpENDxeRgpscDF3g2w4ySH6G9uVsGKK7e6WgGp7Vc9VVnwC2oWdrr7a3taWiKW8jKnD" + path = "m" + pathLen = 1 + ) + payload := []byte("Asado Viernes") + + privKey, _ := NewHDPrivateKeyFromString(privHex, path, Mainnet()) + encrypted, _ := privKey.Encrypter().Encrypt(payload) + + decrypted, err := privKey.Decrypter().Decrypt(encrypted) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(payload, decrypted) { + t.Fatalf("decrypted payload differed from original\ndecrypted %v\noriginal %v", + string(decrypted), + string(payload)) + } + + alterAndCheck := func(msg string, alter func(data []byte)) { + encryptedData := base58.Decode(encrypted) + alter(encryptedData) + + _, err = privKey.Decrypter().Decrypt(base58.Encode(encryptedData)) + if err == nil { + t.Errorf("Got nil error for altered payload: %v", msg) + } + + t.Logf("Got error for altered payload %v: %v", msg, err) + } + + alterAndCheck("big nonce size", func(data []byte) { + // Override the nonce size + data[1+serializedPublicKeyLength+2+pathLen+2+pathLen] = 255 + }) + + alterAndCheck("bigger nonce size", func(data []byte) { + // Override the nonce size + data[1+serializedPublicKeyLength+2+pathLen+2+pathLen+1] = 14 + }) + + alterAndCheck("smaller nonce size", func(data []byte) { + // Override the nonce size + data[1+serializedPublicKeyLength+2+pathLen+2+pathLen+1] = 1 + }) + + alterAndCheck("big derivation path len", func(data []byte) { + // Override derivation path length + data[1+serializedPublicKeyLength] = 255 + }) + + alterAndCheck("bigger derivation path len", func(data []byte) { + // Override derivation path length + data[1+serializedPublicKeyLength+1] = 4 + }) + + alterAndCheck("smaller derivation path len", func(data []byte) { + // Override derivation path length + data[1+serializedPublicKeyLength+1] = 0 + }) + + alterAndCheck("nonce", func(data []byte) { + // Invert last byte of the nonce + data[1+serializedPublicKeyLength+2+pathLen+2+11] = + ^data[1+serializedPublicKeyLength+2+pathLen+2+11] + }) + + alterAndCheck("tamper ciphertext", func(data []byte) { + // Invert last byte of the ciphertext + data[len(data)-1] = ^data[len(data)-1] + }) + + tamperCiphertextWithAEAD := func() { + data := base58.Decode(encrypted) + + additionalData := data[0 : 1+serializedPublicKeyLength+2+pathLen+2] + nonce := data[len(data)-12:] + encryptionKey, _ := privKey.key.ECPrivKey() + secret, _ := recoverSharedEncryptionSecretForAES(encryptionKey, data[1:serializedPublicKeyLength+1]) + + block, _ := aes.NewCipher(secret) + gcm, _ := cipher.NewGCM(block) + + fakeHdPrivKey, _ := NewHDPrivateKey(randomBytes(32), Mainnet()) + + fakePayload := []byte(strings.ToLower(string(payload))) + fakePrivKey, _ := fakeHdPrivKey.key.ECPrivKey() + + hash := sha256.Sum256(fakePayload) + fakeSig, _ := btcec.SignCompact(btcec.S256(), fakePrivKey, hash[:], false) + + plaintext := bytes.NewBuffer(nil) + addVariableBytes(plaintext, fakeSig) + plaintext.Write(fakePayload) + + ciphertext := gcm.Seal(nil, nonce, plaintext.Bytes(), additionalData) + + offset := len(additionalData) + for _, b := range ciphertext { + data[offset] = b + offset++ + } + + for _, b := range nonce { + data[offset] = b + offset++ + } + + _, err = privKey.Decrypter().Decrypt(base58.Encode(data)) + if err == nil { + t.Errorf("Got nil error for altered payload: tamper chiphertex recalculating AEAD") + } + + t.Logf("Got error for altered payload tamper chiphertex recalculating AEAD: %v", err) + } + + tamperCiphertextWithAEAD() +} diff --git a/go.mod b/go.mod index 3d63b63..66ddf4d 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,17 @@ module github.com/muun/libwallet -go 1.12 +go 1.14 require ( - github.com/btcsuite/btcd v0.20.1-beta - github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d - github.com/go-errors/errors v1.0.1 - github.com/golang/protobuf v1.3.2 - github.com/lightningnetwork/lnd v0.8.0-beta - github.com/pkg/errors v0.8.1 - golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 + github.com/btcsuite/btcd v0.20.1-beta.0.20200515232429-9f0179fd2c46 + github.com/btcsuite/btcutil v1.0.2 + github.com/go-errors/errors v1.1.1 + github.com/golang/protobuf v1.4.1 + github.com/lightningnetwork/lnd v0.10.4-beta + github.com/miekg/dns v1.1.29 // indirect + github.com/pkg/errors v0.9.1 + golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 + golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect + golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect + google.golang.org/protobuf v1.25.0 ) diff --git a/go.sum b/go.sum index 48ae349..6356a68 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,16 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= git.schwanenlied.me/yawning/bsaes.git v0.0.0-20180720073208-c0276d75487e/go.mod h1:BWqTsj8PgcPriQJGl7el20J/7TuT1d/hSyFDXMEpoEo= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ= github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82/go.mod h1:GbuBk21JqF+driLX3XtJYNZjGa45YDoa9IqCTzNSfEc= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= @@ -15,40 +18,71 @@ github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcug github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.20.1-beta.0.20200513120220-b470eee47728/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.20.1-beta.0.20200515232429-9f0179fd2c46 h1:QyTpiR5nQe94vza2qkvf7Ns8XX2Rjh/vdIhO3RzGj4o= +github.com/btcsuite/btcd v0.20.1-beta.0.20200515232429-9f0179fd2c46/go.mod h1:Yktc19YNjh/Iz2//CX0vfRTS4IJKM/RKO5YZ9Fn+Pgo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil/psbt v1.0.2/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= github.com/btcsuite/btcwallet v0.10.0/go.mod h1:4TqBEuceheGNdeLNrelliLHJzmXauMM2vtWfuy1pFiM= +github.com/btcsuite/btcwallet v0.11.1-0.20200612012534-48addcd5591a h1:AZ1Mf0gd9mgJqrTTIFUc17ep9EKUbQusVAIzJ6X+x3Q= +github.com/btcsuite/btcwallet v0.11.1-0.20200612012534-48addcd5591a/go.mod h1:9+AH3V5mcTtNXTKe+fe63fDLKGOwQbZqmvOVUef+JFE= +github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0 h1:KGHMW5sd7yDdDMkCZ/JpP0KltolFsQcB973brBnfj4c= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= +github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA= +github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0 h1:6DxkcoMnCPY4E9cUDPB5tbuuf40SmmMkSQkoE8vCT+s= github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= github.com/btcsuite/btcwallet/walletdb v1.0.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= github.com/btcsuite/btcwallet/walletdb v1.1.0/go.mod h1:bZTy9RyYZh9fLnSua+/CD48TJtYJSHjjYcSaszuxCCk= +github.com/btcsuite/btcwallet/walletdb v1.2.0/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= +github.com/btcsuite/btcwallet/walletdb v1.3.1/go.mod h1:9cwc1Yyg4uvd4ZdfdoMnALji+V9gfWSMfxEdLdR5Vwc= +github.com/btcsuite/btcwallet/walletdb v1.3.2/go.mod h1:GZCMPNpUu5KE3ASoVd+k06p/1OW8OwNGCCaNWRto2cQ= +github.com/btcsuite/btcwallet/walletdb v1.3.3 h1:u6e7vRIKBF++cJy+hOHaMGg+88ZTwvpaY27AFvtB668= +github.com/btcsuite/btcwallet/walletdb v1.3.3/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= github.com/btcsuite/btcwallet/wtxmgr v1.0.0/go.mod h1:vc4gBprll6BP0UJ+AIGDaySoc7MdAmZf8kelfNb8CFY= +github.com/btcsuite/btcwallet/wtxmgr v1.2.0 h1:ZUYPsSv8GjF9KK7lboB2OVHF0uYEcHxgrCfFWqPd9NA= +github.com/btcsuite/btcwallet/wtxmgr v1.2.0/go.mod h1:h8hkcKUE3X7lMPzTUoGnNiw5g7VhGrKEW3KpR2r0VnY= github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941/go.mod h1:QcFA8DZHtuIAdYKCq/BzELOaznRsCvwf4zTPmaYwaig= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.0.2 h1:xMxH9j2fNg/L4hLn/4y3M0IUsn0M6Wbu/Uh9QlOfBh4= +github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= +github.com/go-errors/errors v1.1.1 h1:ljK/pL5ltg3qoN+OtN6yCv9HWSfMwxSx90GJCZQxYNg= +github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -56,15 +90,32 @@ github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200j github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v0.0.0-20170724004829-f2862b476edc/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.8.6/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -78,6 +129,7 @@ github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CIm github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec h1:n1NeQ3SgUHyISrjFFoO5dR748Is8dBL9qpaTNfphQrs= github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -85,18 +137,37 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lightninglabs/gozmq v0.0.0-20190710231225-cea2a031735d/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= github.com/lightninglabs/neutrino v0.10.0/go.mod h1:C3KhCMk1Mcx3j8v0qRVWM1Ow6rIJSvSPnUAq00ZNAfk= +github.com/lightninglabs/neutrino v0.11.0/go.mod h1:CuhF0iuzg9Sp2HO6ZgXgayviFTn1QHdSTJlMncK80wg= +github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200 h1:j4iZ1XlUAPQmW6oSzMcJGILYsRHNs+4O3Gk+2Ms5Dww= +github.com/lightninglabs/neutrino v0.11.1-0.20200316235139-bffc52e8f200/go.mod h1:MlZmoKa7CJP3eR1s5yB7Rm5aSyadpKkxqAwLQmog7N0= +github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d/go.mod h1:KDb67YMzoh4eudnzClmvs2FbiLG9vxISmLApUkCa4uI= github.com/lightningnetwork/lightning-onion v0.0.0-20190909101754-850081b08b6a/go.mod h1:rigfi6Af/KqsF7Za0hOgcyq2PNH4AN70AaMRxcJkff4= +github.com/lightningnetwork/lightning-onion v1.0.1/go.mod h1:rigfi6Af/KqsF7Za0hOgcyq2PNH4AN70AaMRxcJkff4= github.com/lightningnetwork/lnd v0.8.0-beta h1:HmmhSRTq48qobqQF8YLqNa8eKU8dDBNbWWpr2VzycJM= github.com/lightningnetwork/lnd v0.8.0-beta/go.mod h1:nq06y2BDv7vwWeMmwgB7P3pT7/Uj7sGf5FzHISVD6t4= +github.com/lightningnetwork/lnd v0.10.4-beta h1:Af2zOCPePeaU8Tkl8IqtTjr4BP3zYfi+hAtQYcCMM58= +github.com/lightningnetwork/lnd v0.10.4-beta/go.mod h1:4d02pduRVtZwgTJ+EimKJTsEAY0jDwi0SPE9h5aRneM= +github.com/lightningnetwork/lnd/cert v1.0.2/go.mod h1:fmtemlSMf5t4hsQmcprSoOykypAPp+9c+0d0iqTScMo= +github.com/lightningnetwork/lnd/clock v1.0.1 h1:QQod8+m3KgqHdvVMV+2DRNNZS1GRFir8mHZYA+Z2hFo= +github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms= +github.com/lightningnetwork/lnd/queue v1.0.4 h1:8Dq3vxAFSACPy+pKN88oPFhuCpCoAAChPBwa4BJxH4k= +github.com/lightningnetwork/lnd/queue v1.0.4/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= +github.com/lightningnetwork/lnd/ticker v1.0.0 h1:S1b60TEGoTtCe2A0yeB+ecoj/kkS4qpwh6l+AkQEZwU= github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 h1:PRMAcldsl4mXKJeRNB/KVNz6TlbS6hk2Rs42PqgU3Ws= github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg= +github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -104,47 +175,74 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -154,15 +252,45 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY= +golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -171,7 +299,11 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/macaroon-bakery.v2 v2.0.1/go.mod h1:B4/T17l+ZWGwxFSZQmlBwp25x+og7OkhETfr3S9MbIA= gopkg.in/macaroon.v2 v2.0.0/go.mod h1:+I6LnTMkm/uV5ew/0nsulNjL16SK4+C8yDmRUzHR17I= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/hdprivatekey.go b/hdprivatekey.go index bfe8292..2a8a31b 100644 --- a/hdprivatekey.go +++ b/hdprivatekey.go @@ -134,3 +134,19 @@ func (p *HDPrivateKey) Sign(data []byte) ([]byte, error) { return sig.Serialize(), nil } + +func (p *HDPrivateKey) Decrypter() Decrypter { + return &hdPrivKeyDecrypter{p, nil, true} +} + +func (p *HDPrivateKey) DecrypterFrom(senderKey *PublicKey) Decrypter { + return &hdPrivKeyDecrypter{p, senderKey, false} +} + +func (p *HDPrivateKey) Encrypter() Encrypter { + return &hdPubKeyEncrypter{p.PublicKey(), p} +} + +func (p *HDPrivateKey) EncrypterTo(receiver *HDPublicKey) Encrypter { + return &hdPubKeyEncrypter{receiver, p} +} diff --git a/hdpublickey.go b/hdpublickey.go index dd18749..4ecfe0d 100644 --- a/hdpublickey.go +++ b/hdpublickey.go @@ -41,6 +41,10 @@ func (p *HDPublicKey) String() string { // index should be uint32 but for java compat we use int64 func (p *HDPublicKey) DerivedAt(index int64) (*HDPublicKey, error) { + if index&hdkeychain.HardenedKeyStart != 0 { + return nil, errors.Errorf("can't derive a hardened pub key (index %v)", index) + } + child, err := p.key.Child(uint32(index)) if err != nil { return nil, err diff --git a/hdpublickey_test.go b/hdpublickey_test.go new file mode 100644 index 0000000..332aeb7 --- /dev/null +++ b/hdpublickey_test.go @@ -0,0 +1,22 @@ +package libwallet + +import ( + "math" + "testing" + + "github.com/btcsuite/btcutil/hdkeychain" +) + +func TestHDPublicKey_DerivedAt(t *testing.T) { + priv, _ := NewHDPrivateKey(randomBytes(32), Mainnet()) + + _, err := priv.PublicKey().DerivedAt(math.MaxUint32) + if err == nil { + t.Errorf("derived a hardened pub key") + } + + _, err = priv.PublicKey().DerivedAt(math.MaxUint32 ^ hdkeychain.HardenedKeyStart) + if err != nil { + t.Errorf("failed to derive unhardened pub key due to %v", err) + } +} diff --git a/invoice.go b/invoice.go index ed477d7..9e448c9 100644 --- a/invoice.go +++ b/invoice.go @@ -2,7 +2,6 @@ package libwallet import ( fmt "fmt" - "strings" "github.com/lightningnetwork/lnd/zpay32" "github.com/pkg/errors" @@ -18,16 +17,29 @@ type Invoice struct { PaymentHash []byte Expiry int64 Description string + Sats int64 } const lightningScheme = "lightning:" // ParseInvoice parses an Invoice from an invoice string and a network -func ParseInvoice(invoice string, network *Network) (*Invoice, error) { +func ParseInvoice(rawInput string, network *Network) (*Invoice, error) { - if strings.HasPrefix(strings.ToLower(invoice), lightningScheme) { - // Remove lightning scheme from rawInvoice - invoice = invoice[len(lightningScheme):] + _, components := buildUriFromString(rawInput, lightningScheme) + if components == nil { + return nil, errors.Errorf("failed to parse uri %v", rawInput) + } + + if components.Scheme != "lightning" { + return nil, errors.Errorf("invalid scheme %v", components.Scheme) + } + + invoice := components.Opaque + + // When URIs are scheme:// the address comes in host + // this happens in iOS that mostly ignores scheme: format + if len(invoice) == 0 { + invoice = components.Host } parsedInvoice, err := zpay32.Decode(invoice, network.network) @@ -50,8 +62,11 @@ func ParseInvoice(invoice string, network *Network) (*Invoice, error) { } var milliSats string + var sats int64 if parsedInvoice.MilliSat != nil { - milliSats = fmt.Sprintf("%v", uint64(*parsedInvoice.MilliSat)) + milliSat := uint64(*parsedInvoice.MilliSat) + milliSats = fmt.Sprintf("%v", milliSat) + sats = int64(milliSat / 1000) } return &Invoice{ @@ -63,5 +78,6 @@ func ParseInvoice(invoice string, network *Network) (*Invoice, error) { PaymentHash: parsedInvoice.PaymentHash[:], Expiry: parsedInvoice.Timestamp.Unix() + int64(parsedInvoice.Expiry().Seconds()), Description: description, + Sats: sats, }, nil } diff --git a/invoice_test.go b/invoice_test.go index 2a8031b..75a45b5 100644 --- a/invoice_test.go +++ b/invoice_test.go @@ -106,6 +106,7 @@ func TestParseInvoice(t *testing.T) { FallbackAddress: nil, Network: network, MilliSat: "1000000", + Sats: 1000, Destination: invoiceDestination, PaymentHash: invoiceWithAmountPaymentHash, Description: "", @@ -161,6 +162,38 @@ func TestParseInvoice(t *testing.T) { }, wantErr: true, }, + { + name: "simple invoice with muun scheme", + args: args{ + invoice: muunScheme + invoice, + network: network, + }, + want: &Invoice{ + RawInvoice: invoice, + FallbackAddress: nil, + Network: network, + MilliSat: "", + Destination: invoiceDestination, + PaymentHash: invoicePaymentHash, + Description: "", + }, + }, + { + name: "simple invoice with muun:// scheme", + args: args{ + invoice: muunScheme + "//" + invoice, + network: network, + }, + want: &Invoice{ + RawInvoice: invoice, + FallbackAddress: nil, + Network: network, + MilliSat: "", + Destination: invoiceDestination, + PaymentHash: invoicePaymentHash, + Description: "", + }, + }, } for _, tt := range tests { diff --git a/keycrypter.go b/keycrypter.go index ac38abd..1021ab7 100644 --- a/keycrypter.go +++ b/keycrypter.go @@ -42,7 +42,7 @@ func KeyEncrypt(key *HDPrivateKey, passphrase string) (string, error) { scryptBlockSize, scryptParallelizationFactor) - encrypted, err := encrypt(inputSecret, iv, privateKeyBytes) + encrypted, err := encryptAesCbcPkcs7(inputSecret, iv, privateKeyBytes) if err != nil { return "", err } @@ -118,7 +118,7 @@ func KeyDecrypt(value, passphrase string, network *Network) (*DecryptedKey, erro blockSize, parallelizationFactor) - decryptedBytes, err := decrypt(inputSecret, iv, payload) + decryptedBytes, err := decryptAesCbcPkcs7(inputSecret, iv, payload) if err != nil { return nil, errors.New("KeyCrypter: failed to decrypt pk: " + err.Error()) } diff --git a/partiallysignedtransaction_test.go b/partiallysignedtransaction_test.go index e418f1b..31dc0da 100644 --- a/partiallysignedtransaction_test.go +++ b/partiallysignedtransaction_test.go @@ -3,7 +3,6 @@ package libwallet import ( "bytes" "encoding/hex" - fmt "fmt" "testing" "github.com/btcsuite/btcd/txscript" @@ -446,18 +445,10 @@ func TestPartiallySignedTransaction_SignSubmarineSwapV2(t *testing.T) { verifyInput(t, signedTx, hexTx2, txIndex2, 0) } -func TestBlo(t *testing.T) { - hexBlob := "2103285ec73aa7b8e86a37a2919c3cba5da7862d64523c16c1868fbbdde0e5c7b5e57c21028b7c740b590012eaffef072675baaa95aee39508fd049ed1cd698ee26ce33f02ac637c76a914477f2112346a2b3a5969001d322f13e1a96da7bb876375677cac6867029000b275ad76a914a5d78a66701ac212735adeb31112c948b7b9ed7e88ac68" - data, _ := hex.DecodeString(hexBlob) - - str, _ := txscript.DisasmString(data) - fmt.Println(str) -} - func TestPartiallySignedTransaction_Verify(t *testing.T) { const ( - hexTx1 = "0100000002a51cc04ab631dee48c989a7cd55c4abc451aa958b09d4579cc9852c52baa57ae0100000000ffffffffdf39591fa749826f87a3d7e5fd5f0468d338c3d81dd3b2c953534b0210f98c560000000000ffffffff02a8d6c20400000000220020452f4ae303ec79acd2bce8f7ddb6469f1060d9146003ea34887e5bbdf021c787000e2707000000002200202ccf0ca2c9b5077ce8345785af26a39277003886fb358877e4083a3fcc5cd66700000000" + hexTx1 = "0100000002a51cc04ab631dee48c989a7cd55c4abc451aa958b09d4579cc9852c52baa57ae0100000000ffffffffdf39591fa749826f87a3d7e5fd5f0468d338c3d81dd3b2c953534b0210f98c560000000000ffffffff02a8d6c20400000000220020452f4ae303ec79acd2bce8f7ddb6469f1060d9146003ea34887e5bbdf021c787000e2707000000002200202ccf0ca2c9b5077ce8345785af26a39277003886fb358877e4083a3fcc5cd66700000000" txIndex1 = 1 txAmount1 = 100000000 @@ -473,11 +464,11 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { txAddress2 = "bcrt1q9n8segkfk5rhe6p527z67f4rjfmsqwyxlv6csalypqarlnzu6ens8cm8ye" txAddressVersion2 = addressV4 - changeAddress1 = "bcrt1qg5h54ccra3u6e54uarmamdjxnugxpkg5vqp75dyg0edmmuppc7rsdfcvcp" - changePath1 = "m/schema:1'/recovery:1'/change:0/1" - changeVersion1 = addressV4 + changeAddress1 = "bcrt1qg5h54ccra3u6e54uarmamdjxnugxpkg5vqp75dyg0edmmuppc7rsdfcvcp" + changePath1 = "m/schema:1'/recovery:1'/change:0/1" + changeVersion1 = addressV4 - hexTx2 = "01000000010ead2fa0d6866d0414aba97fd8f1b242fdc3d4c8e7771e40969402319b6e876b0000000000ffffffff02922988040000000017a914d1ac5d61107d2bef187d1aef5cfd3536f4fd5dbe87d6b2050100000000220020bac6de765432ee16e10ce268341062f8f5a417b15a7f6ee8fe903e6d7470f0f700000000" + hexTx2 = "01000000010ead2fa0d6866d0414aba97fd8f1b242fdc3d4c8e7771e40969402319b6e876b0000000000ffffffff02922988040000000017a914d1ac5d61107d2bef187d1aef5cfd3536f4fd5dbe87d6b2050100000000220020bac6de765432ee16e10ce268341062f8f5a417b15a7f6ee8fe903e6d7470f0f700000000" txIndex3 = 0 txAmount3 = 93266680 @@ -486,12 +477,12 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { txAddress3 = "bcrt1q9yzsghvmmn7wv3esylrvn3c469s4ce4thk7qmxdly4tzk4f8vvjsqv0crh" txAddressVersion3 = addressV4 - changeAddress2 = "bcrt1qg5h54ccra3u6e54uarmamdjxnugxpkg5vqp75dyg0edmmuppc7rsdfcvcp" - changePath2 = "m/schema:1'/recovery:1'/change:0/1" - changeVersion2 = addressV4 + changeAddress2 = "bcrt1qg5h54ccra3u6e54uarmamdjxnugxpkg5vqp75dyg0edmmuppc7rsdfcvcp" + changePath2 = "m/schema:1'/recovery:1'/change:0/1" + changeVersion2 = addressV4 - encodedUserKey = "tpubDAKxNPypXDF3GNCpXFUh6sCdxz7DY9eKMgFxYBgyRSiYWXrBLgdtkPuMbQQzrsYLVyPPSHmNcduLRRd9TSMaYrGLryp8KNkkYBm6eka1Bem" - encodedMuunKey = "tpubDBZaivUL3Hv8r25JDupShPuWVkGcwM7NgbMBwkhQLfWu18iBbyQCbRdyg1wRMjoWdZN7Afg3F25zs4c8E6Q4VJrGqAw51DJeqacTFABV9u8" + encodedUserKey = "tpubDAKxNPypXDF3GNCpXFUh6sCdxz7DY9eKMgFxYBgyRSiYWXrBLgdtkPuMbQQzrsYLVyPPSHmNcduLRRd9TSMaYrGLryp8KNkkYBm6eka1Bem" + encodedMuunKey = "tpubDBZaivUL3Hv8r25JDupShPuWVkGcwM7NgbMBwkhQLfWu18iBbyQCbRdyg1wRMjoWdZN7Afg3F25zs4c8E6Q4VJrGqAw51DJeqacTFABV9u8" basePath = "m/schema:1'/recovery:1'" ) @@ -540,7 +531,7 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { { name: "2 inputs, one change", fields: fields{ - tx: parseTx(hexTx1), + tx: parseTx(hexTx1), inputs: []Input{&firstInput, &secondInput}, Expectations: &SigningExpectations{ destination: "bcrt1q9n8segkfk5rhe6p527z67f4rjfmsqwyxlv6csalypqarlnzu6ens8cm8ye", @@ -554,7 +545,7 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { { name: "lied about destination amount", fields: fields{ - tx: parseTx(hexTx1), + tx: parseTx(hexTx1), inputs: []Input{&firstInput, &secondInput}, Expectations: &SigningExpectations{ destination: "bcrt1q9n8segkfk5rhe6p527z67f4rjfmsqwyxlv6csalypqarlnzu6ens8cm8ye", @@ -563,13 +554,13 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { fee: 122200, }, }, - args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, + args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, wantErr: true, }, { name: "lied about change", fields: fields{ - tx: parseTx(hexTx1), + tx: parseTx(hexTx1), inputs: []Input{&firstInput, &secondInput}, Expectations: &SigningExpectations{ destination: "bcrt1q9n8segkfk5rhe6p527z67f4rjfmsqwyxlv6csalypqarlnzu6ens8cm8ye", @@ -578,13 +569,13 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { fee: 122200, }, }, - args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, + args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, wantErr: true, }, { name: "lied about destination", fields: fields{ - tx: parseTx(hexTx1), + tx: parseTx(hexTx1), inputs: []Input{&firstInput, &secondInput}, Expectations: &SigningExpectations{ destination: "2N2giv9tsN3pV7Rkm89SReRBgdqKNBESVBk", @@ -593,13 +584,13 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { fee: 122200, }, }, - args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, + args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, wantErr: true, }, { name: "lied about fee", fields: fields{ - tx: parseTx(hexTx1), + tx: parseTx(hexTx1), inputs: []Input{&firstInput, &secondInput}, Expectations: &SigningExpectations{ destination: "bcrt1q9n8segkfk5rhe6p527z67f4rjfmsqwyxlv6csalypqarlnzu6ens8cm8ye", @@ -608,13 +599,13 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { fee: 12200, }, }, - args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, + args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, wantErr: true, }, { name: "wasnt expecting change", fields: fields{ - tx: parseTx(hexTx1), + tx: parseTx(hexTx1), inputs: []Input{&firstInput, &secondInput}, Expectations: &SigningExpectations{ destination: "bcrt1q9n8segkfk5rhe6p527z67f4rjfmsqwyxlv6csalypqarlnzu6ens8cm8ye", @@ -623,13 +614,13 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { fee: 122200, }, }, - args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, + args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, wantErr: true, }, { name: "lying change", fields: fields{ - tx: parseTx(hexTx2), + tx: parseTx(hexTx2), inputs: []Input{&thirdInput}, Expectations: &SigningExpectations{ destination: "bcrt1qhtrduaj5xthpdcgvuf5rgyrzlr66g9a3tflka687jqlx6ars7rms0flpmy", @@ -638,7 +629,7 @@ func TestPartiallySignedTransaction_Verify(t *testing.T) { fee: 83600, }, }, - args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, + args: args{userPublicKey: userPublicKey, muunPublickKey: muunPublicKey}, wantErr: true, }, } @@ -666,4 +657,4 @@ func parseTx(hexTx string) *wire.MsgTx { tx.BtcDecode(bytes.NewBuffer(rawTx), 0, wire.WitnessEncoding) return tx -} \ No newline at end of file +} diff --git a/publickey.go b/publickey.go new file mode 100644 index 0000000..33451ad --- /dev/null +++ b/publickey.go @@ -0,0 +1,19 @@ +package libwallet + +import ( + "github.com/btcsuite/btcd/btcec" + "github.com/pkg/errors" +) + +type PublicKey struct { + key *btcec.PublicKey +} + +func NewPublicKeyFromBytes(bytes []byte) (*PublicKey, error) { + key, err := btcec.ParsePubKey(bytes, btcec.S256()) + if err != nil { + return nil, errors.Wrapf(err, "NewPublicKeyFromBytes: failed to parse pub key") + } + + return &PublicKey{key}, nil +} diff --git a/ripemd160.go b/ripemd160.go index 5abe7e8..40351cc 100644 --- a/ripemd160.go +++ b/ripemd160.go @@ -1,7 +1,7 @@ package libwallet import ( - hash "golang.org/x/crypto/ripemd160" //lint:ignore SA1019 using deprecated hash function for compatibility + hash "golang.org/x/crypto/ripemd160" //lint:ignore SA1019 using deprecated hash function for compatibility ) func ripemd160(data []byte) []byte { diff --git a/vendor/github.com/aead/siphash/.gitignore b/vendor/github.com/aead/siphash/.gitignore new file mode 100644 index 0000000..9d3d843 --- /dev/null +++ b/vendor/github.com/aead/siphash/.gitignore @@ -0,0 +1,25 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test +.vscode + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/aead/siphash/.travis.yml b/vendor/github.com/aead/siphash/.travis.yml new file mode 100644 index 0000000..4576e93 --- /dev/null +++ b/vendor/github.com/aead/siphash/.travis.yml @@ -0,0 +1,15 @@ +language: go + +go: + - "1.6.x" + - "1.7.x" + - "1.8.x" + - "1.9.x" + - "1.10.x" + +env: + - TRAVIS_GOARCH=amd64 + - TRAVIS_GOARCH=386 + +before_install: + - export GOARCH=$TRAVIS_GOARCH \ No newline at end of file diff --git a/vendor/github.com/aead/siphash/LICENSE b/vendor/github.com/aead/siphash/LICENSE new file mode 100644 index 0000000..b6a9210 --- /dev/null +++ b/vendor/github.com/aead/siphash/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Andreas Auernhammer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/aead/siphash/README.md b/vendor/github.com/aead/siphash/README.md new file mode 100644 index 0000000..e308419 --- /dev/null +++ b/vendor/github.com/aead/siphash/README.md @@ -0,0 +1,55 @@ +[![Godoc Reference](https://godoc.org/github.com/aead/siphash?status.svg)](https://godoc.org/github.com/aead/siphash) +[![Build Status](https://travis-ci.org/aead/siphash.svg?branch=master)](https://travis-ci.org/aead/siphash) + +## The SipHash pseudo-random function + +SipHash is a family of pseudo-random functions (a.k.a. keyed hash functions) optimized for speed on short messages. +SipHash computes a 64-bit or 128 bit message authentication code from a variable-length message and 128-bit secret key. +This implementation uses the recommended parameters c=2 and d=4. + +### Installation +Install in your GOPATH: `go get -u github.com/aead/siphash` + +### Performance +**AMD64** +Hardware: Intel i7-6500U 2.50GHz x 2 +System: Linux Ubuntu 16.04 - kernel: 4.4.0-67-generic +Go version: 1.8.0 +``` +name speed cpb +Write_8-4 688MB/s ± 0% 3.47 +Write_1K-4 2.09GB/s ± 5% 1.11 +Sum64_8-4 244MB/s ± 1% 9.77 +Sum64_1K-4 2.06GB/s ± 0% 1.13 +Sum128_8-4 189MB/s ± 0% 12.62 +Sum128_1K-4 2.03GB/s ± 0% 1.15 +``` + +**386** +Hardware: Intel i7-6500U 2.50GHz x 2 - SSE2 SIMD +System: Linux Ubuntu 16.04 - kernel: 4.4.0-67-generic +Go version: 1.8.0 +``` +name speed cpb +Write_8-4 434MB/s ± 2% 5.44 +Write_1K-4 1.24GB/s ± 1% 1.88 +Sum64_8-4 92.6MB/s ± 4% 25.92 +Sum64_1K-4 1.15GB/s ± 1% 2.03 +Sum128_8-4 61.5MB/s ± 5% 39.09 +Sum128_1K-4 1.10GB/s ± 0% 2.12 +``` + +**ARM** +Hardware: ARM-Cortex-A7 (ARMv7) 1GHz (912MHz) x 2 +System: Linux Ubuntu 14.04.1 - kernel: 3.4.112-sun7i +Go version: 1.7.4 + +``` +name speed cpb +Write_8-2 43.4MB/s ± 2% 21.97 +Write_1K-2 125MB/s ± 1% 7.63 +Sum64_8-2 6.51MB/s ± 1% 146.49 +Sum64_1K-2 111MB/s ± 1% 8.59 +Sum128_8-2 3.82MB/s ± 2% 249.65 +Sum128_1K-2 101MB/s ± 1% 9.44 +``` diff --git a/vendor/github.com/aead/siphash/siphash.go b/vendor/github.com/aead/siphash/siphash.go new file mode 100644 index 0000000..3aade42 --- /dev/null +++ b/vendor/github.com/aead/siphash/siphash.go @@ -0,0 +1,157 @@ +// Copyright (c) 2016 Andreas Auernhammer. All rights reserved. +// Use of this source code is governed by a license that can be +// found in the LICENSE file. + +// Package siphash implements the SipHash-64 and SipHash-128 +// pseudo-random-functions - with the recommended parameters: +// c = 2 and d = 4. +// SipHash computes a message authentication code (MAC) from a +// variable-length message and a 128 bit secret key. SipHash +// was designed to be efficient, even for short inputs, with +// performance comparable to non-cryptographic hash functions. +// +// +// Security +// +// SipHash cannot be used as a cryptographic hash function. +// Neither SipHash-64 nor SipHash-128 are strong collision +// resistant. +// +// +// Recommendations +// +// SipHash was designed to defend hash flooding DoS attacks. +// SipHash-64 can be used as hashing scheme within hash maps +// or other key-value data structures. +// SipHash-128 can be used to compute a 128 bit authentication +// tag for messages. +package siphash // import "github.com/aead/siphash" + +import ( + "encoding/binary" + "hash" + "strconv" +) + +const ( + // KeySize is the size of the SipHash secret key in bytes. + KeySize = 16 + // BlockSize is the block size of SipHash in bytes. + BlockSize = 8 +) + +const ( + c0 = 0x736f6d6570736575 + c1 = 0x646f72616e646f6d + c2 = 0x6c7967656e657261 + c3 = 0x7465646279746573 +) + +type KeySizeError uint + +func (k KeySizeError) Error() string { + return "siphash: invalid key size " + strconv.Itoa(int(k)) +} + +// Sum64 returns the 64 bit authenticator for msg using a 128 bit secret key. +func Sum64(msg []byte, key *[KeySize]byte) uint64 { + k0 := binary.LittleEndian.Uint64(key[0:]) + k1 := binary.LittleEndian.Uint64(key[8:]) + + var hVal [4]uint64 + hVal[0] = k0 ^ c0 + hVal[1] = k1 ^ c1 + hVal[2] = k0 ^ c2 + hVal[3] = k1 ^ c3 + + n := len(msg) + ctr := byte(n) + + if n >= BlockSize { + n &= (^(BlockSize - 1)) + core(&hVal, msg[:n]) + msg = msg[n:] + } + + var block [BlockSize]byte + copy(block[:], msg) + block[7] = ctr + + return finalize64(&hVal, &block) +} + +// New64 returns a hash.Hash64 computing the SipHash-64 checksum. +// This function returns a non-nil error if len(key) != 16. +func New64(key []byte) (hash.Hash64, error) { + if k := len(key); k != KeySize { + return nil, KeySizeError(k) + } + h := new(digest64) + h.key[0] = binary.LittleEndian.Uint64(key) + h.key[1] = binary.LittleEndian.Uint64(key[8:]) + h.Reset() + return h, nil +} + +type digest64 struct { + hVal [4]uint64 + key [2]uint64 + block [BlockSize]byte + off int + ctr byte +} + +func (d *digest64) BlockSize() int { return BlockSize } + +func (d *digest64) Size() int { return 8 } + +func (d *digest64) Reset() { + d.hVal[0] = d.key[0] ^ c0 + d.hVal[1] = d.key[1] ^ c1 + d.hVal[2] = d.key[0] ^ c2 + d.hVal[3] = d.key[1] ^ c3 + + d.off = 0 + d.ctr = 0 +} + +func (d *digest64) Write(p []byte) (n int, err error) { + n = len(p) + d.ctr += byte(n) + + if d.off > 0 { + dif := BlockSize - d.off + if n < dif { + d.off += copy(d.block[d.off:], p) + return + } + copy(d.block[d.off:], p[:dif]) + core(&(d.hVal), d.block[:]) + p = p[dif:] + d.off = 0 + } + if nn := len(p) &^ (BlockSize - 1); nn >= BlockSize { + core(&(d.hVal), p[:nn]) + p = p[nn:] + } + if len(p) > 0 { + d.off = copy(d.block[:], p) + } + return n, nil +} + +func (d *digest64) Sum64() uint64 { + hVal := d.hVal + block := d.block + for i := d.off; i < BlockSize-1; i++ { + block[i] = 0 + } + block[7] = d.ctr + return finalize64(&hVal, &block) +} + +func (d *digest64) Sum(sum []byte) []byte { + var out [8]byte + binary.LittleEndian.PutUint64(out[:], d.Sum64()) + return append(sum, out[:]...) +} diff --git a/vendor/github.com/aead/siphash/siphash128.go b/vendor/github.com/aead/siphash/siphash128.go new file mode 100644 index 0000000..1dc623f --- /dev/null +++ b/vendor/github.com/aead/siphash/siphash128.go @@ -0,0 +1,106 @@ +// Copyright (c) 2017 Andreas Auernhammer. All rights reserved. +// Use of this source code is governed by a license that can be +// found in the LICENSE file. + +package siphash + +import ( + "encoding/binary" + "hash" +) + +// Sum128 returns the 128 bit authenticator for msg using a 128 bit secret key. +func Sum128(msg []byte, key *[KeySize]byte) [16]byte { + k0 := binary.LittleEndian.Uint64(key[0:]) + k1 := binary.LittleEndian.Uint64(key[8:]) + + var hVal [4]uint64 + hVal[0] = k0 ^ c0 + hVal[1] = k1 ^ c1 ^ 0xee + hVal[2] = k0 ^ c2 + hVal[3] = k1 ^ c3 + + n := len(msg) + ctr := byte(n) + + if n >= BlockSize { + n &= (^(BlockSize - 1)) + core(&hVal, msg[:n]) + msg = msg[n:] + } + + var block [BlockSize]byte + copy(block[:], msg) + block[7] = ctr + + var out [16]byte + finalize128(&out, &hVal, &block) + return out +} + +// New128 returns a hash.Hash computing the SipHash-128 checksum. +// This function returns a non-nil error if len(key) != 16. +func New128(key []byte) (hash.Hash, error) { + if k := len(key); k != KeySize { + return nil, KeySizeError(k) + } + h := new(digest128) + h.key[0] = binary.LittleEndian.Uint64(key) + h.key[1] = binary.LittleEndian.Uint64(key[8:]) + h.Reset() + return h, nil +} + +type digest128 digest64 + +func (d *digest128) BlockSize() int { return BlockSize } + +func (d *digest128) Size() int { return 16 } + +func (d *digest128) Reset() { + d.hVal[0] = d.key[0] ^ c0 + d.hVal[1] = d.key[1] ^ c1 ^ 0xee + d.hVal[2] = d.key[0] ^ c2 + d.hVal[3] = d.key[1] ^ c3 + + d.off = 0 + d.ctr = 0 +} + +func (d *digest128) Write(p []byte) (n int, err error) { + n = len(p) + d.ctr += byte(n) + + if d.off > 0 { + dif := BlockSize - d.off + if n < dif { + d.off += copy(d.block[d.off:], p) + return + } + copy(d.block[d.off:], p[:dif]) + core(&(d.hVal), d.block[:]) + p = p[dif:] + d.off = 0 + } + if nn := len(p) &^ (BlockSize - 1); nn >= BlockSize { + core(&(d.hVal), p[:nn]) + p = p[nn:] + } + if len(p) > 0 { + d.off = copy(d.block[:], p) + } + return n, nil +} + +func (d *digest128) Sum(sum []byte) []byte { + hVal := d.hVal + block := d.block + for i := d.off; i < BlockSize-1; i++ { + block[i] = 0 + } + block[7] = d.ctr + + var out [16]byte + finalize128(&out, &hVal, &block) + return append(sum, out[:]...) +} diff --git a/vendor/github.com/aead/siphash/siphash_386.go b/vendor/github.com/aead/siphash/siphash_386.go new file mode 100644 index 0000000..544ae03 --- /dev/null +++ b/vendor/github.com/aead/siphash/siphash_386.go @@ -0,0 +1,31 @@ +// Copyright (c) 2017 Andreas Auernhammer. All rights reserved. +// Use of this source code is governed by a license that can be +// found in the LICENSE file. + +// +build 386, !gccgo, !appengine + +package siphash + +var useSSE2 = supportsSSE2() + +//go:noescape +func supportsSSE2() bool + +//go:noescape +func coreSSE2(hVal *[4]uint64, msg []byte) + +func core(hVal *[4]uint64, msg []byte) { + if useSSE2 { + coreSSE2(hVal, msg) + } else { + genericCore(hVal, msg) + } +} + +func finalize64(hVal *[4]uint64, block *[BlockSize]byte) uint64 { + return genericFinalize64(hVal, block) +} + +func finalize128(tag *[16]byte, hVal *[4]uint64, block *[BlockSize]byte) { + genericFinalize128(tag, hVal, block) +} diff --git a/vendor/github.com/aead/siphash/siphash_386.s b/vendor/github.com/aead/siphash/siphash_386.s new file mode 100644 index 0000000..ea008a3 --- /dev/null +++ b/vendor/github.com/aead/siphash/siphash_386.s @@ -0,0 +1,65 @@ +// Copyright (c) 2017 Andreas Auernhammer. All rights reserved. +// Use of this source code is governed by a license that can be +// found in the LICENSE file. + +// +build 386, !gccgo, !appengine + +#define ROTL(n, t, v) \ + MOVO v, t; \ + PSLLQ $n, t; \ + PSRLQ $(64-n), v; \ + PXOR t, v + +#define ROUND(v0, v1, v2, v3, t0, t1) \ + PADDQ v1, v0; \ + PADDQ v3, v2; \ + ROTL(13, t0, v1); \ + ROTL(16, t1, v3); \ + PXOR v0, v1; \ + PXOR v2, v3; \ + PSHUFD $0xE1, v0, v0; \ + PADDQ v1, v2; \ + PADDQ v3, v0; \ + ROTL(17, t0, v1); \ + ROTL(21, t1, v3); \ + PXOR v2, v1; \ + PXOR v0, v3; \ + PSHUFD $0xE1, v2, v2 + +// coreSSE2(hVal *[4]uint64, msg []byte) +TEXT ·coreSSE2(SB), 4, $0-16 + MOVL hVal+0(FP), AX + MOVL msg_base+4(FP), SI + MOVL msg_len+8(FP), BX + MOVQ 0(AX), X0 + MOVQ 8(AX), X1 + MOVQ 16(AX), X2 + MOVQ 24(AX), X3 + PXOR X6, X6 + ANDL $-8, BX + +loop: + MOVQ 0(SI), X6 + PXOR X6, X3 + ROUND(X0, X1, X2, X3, X4, X5) + ROUND(X0, X1, X2, X3, X4, X5) + PXOR X6, X0 + + LEAL 8(SI), SI + SUBL $8, BX + JNZ loop + + MOVQ X0, 0(AX) + MOVQ X1, 8(AX) + MOVQ X2, 16(AX) + MOVQ X3, 24(AX) + RET + +// func supportsSSE2() bool +TEXT ·supportsSSE2(SB), 4, $0-1 + MOVL $1, AX + CPUID + SHRL $26, DX + ANDL $1, DX // DX != 0 if support SSE2 + MOVB DX, ret+0(FP) + RET diff --git a/vendor/github.com/aead/siphash/siphash_amd64.go b/vendor/github.com/aead/siphash/siphash_amd64.go new file mode 100644 index 0000000..c18c870 --- /dev/null +++ b/vendor/github.com/aead/siphash/siphash_amd64.go @@ -0,0 +1,18 @@ +// Copyright (c) 2016 Andreas Auernhammer. All rights reserved. +// Use of this source code is governed by a license that can be +// found in the LICENSE file. + +// +build amd64, !gccgo, !appengine + +package siphash + +//go:noescape +func core(hVal *[4]uint64, msg []byte) + +func finalize64(hVal *[4]uint64, block *[BlockSize]byte) uint64 { + return genericFinalize64(hVal, block) +} + +func finalize128(tag *[16]byte, hVal *[4]uint64, block *[BlockSize]byte) { + genericFinalize128(tag, hVal, block) +} diff --git a/vendor/github.com/aead/siphash/siphash_amd64.s b/vendor/github.com/aead/siphash/siphash_amd64.s new file mode 100644 index 0000000..9aa6905 --- /dev/null +++ b/vendor/github.com/aead/siphash/siphash_amd64.s @@ -0,0 +1,49 @@ +// Copyright (c) 2016 Andreas Auernhammer. All rights reserved. +// Use of this source code is governed by a license that can be +// found in the LICENSE file. + +// +build amd64, !gccgo, !appengine + +#define ROUND(v0, v1, v2, v3) \ + ADDQ v1, v0; \ + ADDQ v3, v2; \ + ROLQ $13, v1; \ + ROLQ $16, v3; \ + XORQ v0, v1; \ + XORQ v2, v3; \ + ROLQ $32, v0; \ + ADDQ v1, v2; \ + ADDQ v3, v0; \ + ROLQ $17, v1; \ + ROLQ $21, v3; \ + XORQ v2, v1; \ + XORQ v0, v3; \ + ROLQ $32, v2 + +// core(hVal *[4]uint64, msg []byte) +TEXT ·core(SB), 4, $0-32 + MOVQ hVal+0(FP), AX + MOVQ msg_base+8(FP), SI + MOVQ msg_len+16(FP), BX + MOVQ 0(AX), R9 + MOVQ 8(AX), R10 + MOVQ 16(AX), R11 + MOVQ 24(AX), R12 + ANDQ $-8, BX + +loop: + MOVQ 0(SI), DX + XORQ DX, R12 + ROUND(R9, R10, R11, R12) + ROUND(R9, R10, R11, R12) + XORQ DX, R9 + + LEAQ 8(SI), SI + SUBQ $8, BX + JNZ loop + + MOVQ R9, 0(AX) + MOVQ R10, 8(AX) + MOVQ R11, 16(AX) + MOVQ R12, 24(AX) + RET diff --git a/vendor/github.com/aead/siphash/siphash_generic.go b/vendor/github.com/aead/siphash/siphash_generic.go new file mode 100644 index 0000000..139a33f --- /dev/null +++ b/vendor/github.com/aead/siphash/siphash_generic.go @@ -0,0 +1,188 @@ +// Copyright (c) 2017 Andreas Auernhammer. All rights reserved. +// Use of this source code is governed by a license that can be +// found in the LICENSE file. + +package siphash + +import "encoding/binary" + +func genericCore(hVal *[4]uint64, msg []byte) { + v0, v1, v2, v3 := hVal[0], hVal[1], hVal[2], hVal[3] + + for len(msg) > 0 { + m := binary.LittleEndian.Uint64(msg) + msg = msg[BlockSize:] + + v3 ^= m + + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + + v0 ^= m + } + + hVal[0], hVal[1], hVal[2], hVal[3] = v0, v1, v2, v3 +} + +func genericFinalize64(hVal *[4]uint64, block *[BlockSize]byte) uint64 { + v0, v1, v2, v3 := hVal[0], hVal[1], hVal[2], hVal[3] + + m := binary.LittleEndian.Uint64(block[:]) + v3 ^= m + + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + + v0 ^= m + + v2 ^= 0xff + for i := 0; i < 4; i++ { + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + } + return v0 ^ v1 ^ v2 ^ v3 +} + +func genericFinalize128(tag *[16]byte, hVal *[4]uint64, block *[BlockSize]byte) { + v0, v1, v2, v3 := hVal[0], hVal[1], hVal[2], hVal[3] + + m := binary.LittleEndian.Uint64(block[:]) + + v3 ^= m + + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + + v0 ^= m + + v2 ^= 0xee + for i := 0; i < 4; i++ { + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + } + binary.LittleEndian.PutUint64(tag[:], v0^v1^v2^v3) + + v1 ^= 0xdd + for i := 0; i < 4; i++ { + v0 += v1 + v1 = v1<<13 | v1>>(64-13) + v1 ^= v0 + v0 = v0<<32 | v0>>(64-32) + v2 += v3 + v3 = v3<<16 | v3>>(64-16) + v3 ^= v2 + v0 += v3 + v3 = v3<<21 | v3>>(64-21) + v3 ^= v0 + v2 += v1 + v1 = v1<<17 | v1>>(64-17) + v1 ^= v2 + v2 = v2<<32 | v2>>(64-32) + } + binary.LittleEndian.PutUint64(tag[8:], v0^v1^v2^v3) +} diff --git a/vendor/github.com/aead/siphash/siphash_ref.go b/vendor/github.com/aead/siphash/siphash_ref.go new file mode 100644 index 0000000..3627bb9 --- /dev/null +++ b/vendor/github.com/aead/siphash/siphash_ref.go @@ -0,0 +1,19 @@ +// Copyright (c) 2016 Andreas Auernhammer. All rights reserved. +// Use of this source code is governed by a license that can be +// found in the LICENSE file. + +// +build !amd64,!386 gccgo appengine nacl + +package siphash + +func core(hVal *[4]uint64, msg []byte) { + genericCore(hVal, msg) +} + +func finalize64(hVal *[4]uint64, block *[BlockSize]byte) uint64 { + return genericFinalize64(hVal, block) +} + +func finalize128(tag *[16]byte, hVal *[4]uint64, block *[BlockSize]byte) { + genericFinalize128(tag, hVal, block) +} diff --git a/vendor/github.com/btcsuite/btcd/addrmgr/addrmanager.go b/vendor/github.com/btcsuite/btcd/addrmgr/addrmanager.go new file mode 100644 index 0000000..a8a8fb3 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/addrmgr/addrmanager.go @@ -0,0 +1,1151 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2015-2018 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package addrmgr + +import ( + "container/list" + crand "crypto/rand" // for seeding + "encoding/base32" + "encoding/binary" + "encoding/json" + "fmt" + "io" + "math/rand" + "net" + "os" + "path/filepath" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +// AddrManager provides a concurrency safe address manager for caching potential +// peers on the bitcoin network. +type AddrManager struct { + mtx sync.Mutex + peersFile string + lookupFunc func(string) ([]net.IP, error) + rand *rand.Rand + key [32]byte + addrIndex map[string]*KnownAddress // address key to ka for all addrs. + addrNew [newBucketCount]map[string]*KnownAddress + addrTried [triedBucketCount]*list.List + started int32 + shutdown int32 + wg sync.WaitGroup + quit chan struct{} + nTried int + nNew int + lamtx sync.Mutex + localAddresses map[string]*localAddress + version int +} + +type serializedKnownAddress struct { + Addr string + Src string + Attempts int + TimeStamp int64 + LastAttempt int64 + LastSuccess int64 + Services wire.ServiceFlag + SrcServices wire.ServiceFlag + // no refcount or tried, that is available from context. +} + +type serializedAddrManager struct { + Version int + Key [32]byte + Addresses []*serializedKnownAddress + NewBuckets [newBucketCount][]string // string is NetAddressKey + TriedBuckets [triedBucketCount][]string +} + +type localAddress struct { + na *wire.NetAddress + score AddressPriority +} + +// AddressPriority type is used to describe the hierarchy of local address +// discovery methods. +type AddressPriority int + +const ( + // InterfacePrio signifies the address is on a local interface + InterfacePrio AddressPriority = iota + + // BoundPrio signifies the address has been explicitly bounded to. + BoundPrio + + // UpnpPrio signifies the address was obtained from UPnP. + UpnpPrio + + // HTTPPrio signifies the address was obtained from an external HTTP service. + HTTPPrio + + // ManualPrio signifies the address was provided by --externalip. + ManualPrio +) + +const ( + // needAddressThreshold is the number of addresses under which the + // address manager will claim to need more addresses. + needAddressThreshold = 1000 + + // dumpAddressInterval is the interval used to dump the address + // cache to disk for future use. + dumpAddressInterval = time.Minute * 10 + + // triedBucketSize is the maximum number of addresses in each + // tried address bucket. + triedBucketSize = 256 + + // triedBucketCount is the number of buckets we split tried + // addresses over. + triedBucketCount = 64 + + // newBucketSize is the maximum number of addresses in each new address + // bucket. + newBucketSize = 64 + + // newBucketCount is the number of buckets that we spread new addresses + // over. + newBucketCount = 1024 + + // triedBucketsPerGroup is the number of tried buckets over which an + // address group will be spread. + triedBucketsPerGroup = 8 + + // newBucketsPerGroup is the number of new buckets over which an + // source address group will be spread. + newBucketsPerGroup = 64 + + // newBucketsPerAddress is the number of buckets a frequently seen new + // address may end up in. + newBucketsPerAddress = 8 + + // numMissingDays is the number of days before which we assume an + // address has vanished if we have not seen it announced in that long. + numMissingDays = 30 + + // numRetries is the number of tried without a single success before + // we assume an address is bad. + numRetries = 3 + + // maxFailures is the maximum number of failures we will accept without + // a success before considering an address bad. + maxFailures = 10 + + // minBadDays is the number of days since the last success before we + // will consider evicting an address. + minBadDays = 7 + + // getAddrMax is the most addresses that we will send in response + // to a getAddr (in practise the most addresses we will return from a + // call to AddressCache()). + getAddrMax = 2500 + + // getAddrPercent is the percentage of total addresses known that we + // will share with a call to AddressCache. + getAddrPercent = 23 + + // serialisationVersion is the current version of the on-disk format. + serialisationVersion = 2 +) + +// updateAddress is a helper function to either update an address already known +// to the address manager, or to add the address if not already known. +func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddress) { + // Filter out non-routable addresses. Note that non-routable + // also includes invalid and local addresses. + if !IsRoutable(netAddr) { + return + } + + addr := NetAddressKey(netAddr) + ka := a.find(netAddr) + if ka != nil { + // TODO: only update addresses periodically. + // Update the last seen time and services. + // note that to prevent causing excess garbage on getaddr + // messages the netaddresses in addrmaanger are *immutable*, + // if we need to change them then we replace the pointer with a + // new copy so that we don't have to copy every na for getaddr. + if netAddr.Timestamp.After(ka.na.Timestamp) || + (ka.na.Services&netAddr.Services) != + netAddr.Services { + + naCopy := *ka.na + naCopy.Timestamp = netAddr.Timestamp + naCopy.AddService(netAddr.Services) + ka.na = &naCopy + } + + // If already in tried, we have nothing to do here. + if ka.tried { + return + } + + // Already at our max? + if ka.refs == newBucketsPerAddress { + return + } + + // The more entries we have, the less likely we are to add more. + // likelihood is 2N. + factor := int32(2 * ka.refs) + if a.rand.Int31n(factor) != 0 { + return + } + } else { + // Make a copy of the net address to avoid races since it is + // updated elsewhere in the addrmanager code and would otherwise + // change the actual netaddress on the peer. + netAddrCopy := *netAddr + ka = &KnownAddress{na: &netAddrCopy, srcAddr: srcAddr} + a.addrIndex[addr] = ka + a.nNew++ + // XXX time penalty? + } + + bucket := a.getNewBucket(netAddr, srcAddr) + + // Already exists? + if _, ok := a.addrNew[bucket][addr]; ok { + return + } + + // Enforce max addresses. + if len(a.addrNew[bucket]) > newBucketSize { + log.Tracef("new bucket is full, expiring old") + a.expireNew(bucket) + } + + // Add to new bucket. + ka.refs++ + a.addrNew[bucket][addr] = ka + + log.Tracef("Added new address %s for a total of %d addresses", addr, + a.nTried+a.nNew) +} + +// expireNew makes space in the new buckets by expiring the really bad entries. +// If no bad entries are available we look at a few and remove the oldest. +func (a *AddrManager) expireNew(bucket int) { + // First see if there are any entries that are so bad we can just throw + // them away. otherwise we throw away the oldest entry in the cache. + // Bitcoind here chooses four random and just throws the oldest of + // those away, but we keep track of oldest in the initial traversal and + // use that information instead. + var oldest *KnownAddress + for k, v := range a.addrNew[bucket] { + if v.isBad() { + log.Tracef("expiring bad address %v", k) + delete(a.addrNew[bucket], k) + v.refs-- + if v.refs == 0 { + a.nNew-- + delete(a.addrIndex, k) + } + continue + } + if oldest == nil { + oldest = v + } else if !v.na.Timestamp.After(oldest.na.Timestamp) { + oldest = v + } + } + + if oldest != nil { + key := NetAddressKey(oldest.na) + log.Tracef("expiring oldest address %v", key) + + delete(a.addrNew[bucket], key) + oldest.refs-- + if oldest.refs == 0 { + a.nNew-- + delete(a.addrIndex, key) + } + } +} + +// pickTried selects an address from the tried bucket to be evicted. +// We just choose the eldest. Bitcoind selects 4 random entries and throws away +// the older of them. +func (a *AddrManager) pickTried(bucket int) *list.Element { + var oldest *KnownAddress + var oldestElem *list.Element + for e := a.addrTried[bucket].Front(); e != nil; e = e.Next() { + ka := e.Value.(*KnownAddress) + if oldest == nil || oldest.na.Timestamp.After(ka.na.Timestamp) { + oldestElem = e + oldest = ka + } + + } + return oldestElem +} + +func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddress) int { + // bitcoind: + // doublesha256(key + sourcegroup + int64(doublesha256(key + group + sourcegroup))%bucket_per_source_group) % num_new_buckets + + data1 := []byte{} + data1 = append(data1, a.key[:]...) + data1 = append(data1, []byte(GroupKey(netAddr))...) + data1 = append(data1, []byte(GroupKey(srcAddr))...) + hash1 := chainhash.DoubleHashB(data1) + hash64 := binary.LittleEndian.Uint64(hash1) + hash64 %= newBucketsPerGroup + var hashbuf [8]byte + binary.LittleEndian.PutUint64(hashbuf[:], hash64) + data2 := []byte{} + data2 = append(data2, a.key[:]...) + data2 = append(data2, GroupKey(srcAddr)...) + data2 = append(data2, hashbuf[:]...) + + hash2 := chainhash.DoubleHashB(data2) + return int(binary.LittleEndian.Uint64(hash2) % newBucketCount) +} + +func (a *AddrManager) getTriedBucket(netAddr *wire.NetAddress) int { + // bitcoind hashes this as: + // doublesha256(key + group + truncate_to_64bits(doublesha256(key)) % buckets_per_group) % num_buckets + data1 := []byte{} + data1 = append(data1, a.key[:]...) + data1 = append(data1, []byte(NetAddressKey(netAddr))...) + hash1 := chainhash.DoubleHashB(data1) + hash64 := binary.LittleEndian.Uint64(hash1) + hash64 %= triedBucketsPerGroup + var hashbuf [8]byte + binary.LittleEndian.PutUint64(hashbuf[:], hash64) + data2 := []byte{} + data2 = append(data2, a.key[:]...) + data2 = append(data2, GroupKey(netAddr)...) + data2 = append(data2, hashbuf[:]...) + + hash2 := chainhash.DoubleHashB(data2) + return int(binary.LittleEndian.Uint64(hash2) % triedBucketCount) +} + +// addressHandler is the main handler for the address manager. It must be run +// as a goroutine. +func (a *AddrManager) addressHandler() { + dumpAddressTicker := time.NewTicker(dumpAddressInterval) + defer dumpAddressTicker.Stop() +out: + for { + select { + case <-dumpAddressTicker.C: + a.savePeers() + + case <-a.quit: + break out + } + } + a.savePeers() + a.wg.Done() + log.Trace("Address handler done") +} + +// savePeers saves all the known addresses to a file so they can be read back +// in at next run. +func (a *AddrManager) savePeers() { + a.mtx.Lock() + defer a.mtx.Unlock() + + // First we make a serialisable datastructure so we can encode it to + // json. + sam := new(serializedAddrManager) + sam.Version = a.version + copy(sam.Key[:], a.key[:]) + + sam.Addresses = make([]*serializedKnownAddress, len(a.addrIndex)) + i := 0 + for k, v := range a.addrIndex { + ska := new(serializedKnownAddress) + ska.Addr = k + ska.TimeStamp = v.na.Timestamp.Unix() + ska.Src = NetAddressKey(v.srcAddr) + ska.Attempts = v.attempts + ska.LastAttempt = v.lastattempt.Unix() + ska.LastSuccess = v.lastsuccess.Unix() + if a.version > 1 { + ska.Services = v.na.Services + ska.SrcServices = v.srcAddr.Services + } + // Tried and refs are implicit in the rest of the structure + // and will be worked out from context on unserialisation. + sam.Addresses[i] = ska + i++ + } + for i := range a.addrNew { + sam.NewBuckets[i] = make([]string, len(a.addrNew[i])) + j := 0 + for k := range a.addrNew[i] { + sam.NewBuckets[i][j] = k + j++ + } + } + for i := range a.addrTried { + sam.TriedBuckets[i] = make([]string, a.addrTried[i].Len()) + j := 0 + for e := a.addrTried[i].Front(); e != nil; e = e.Next() { + ka := e.Value.(*KnownAddress) + sam.TriedBuckets[i][j] = NetAddressKey(ka.na) + j++ + } + } + + w, err := os.Create(a.peersFile) + if err != nil { + log.Errorf("Error opening file %s: %v", a.peersFile, err) + return + } + enc := json.NewEncoder(w) + defer w.Close() + if err := enc.Encode(&sam); err != nil { + log.Errorf("Failed to encode file %s: %v", a.peersFile, err) + return + } +} + +// loadPeers loads the known address from the saved file. If empty, missing, or +// malformed file, just don't load anything and start fresh +func (a *AddrManager) loadPeers() { + a.mtx.Lock() + defer a.mtx.Unlock() + + err := a.deserializePeers(a.peersFile) + if err != nil { + log.Errorf("Failed to parse file %s: %v", a.peersFile, err) + // if it is invalid we nuke the old one unconditionally. + err = os.Remove(a.peersFile) + if err != nil { + log.Warnf("Failed to remove corrupt peers file %s: %v", + a.peersFile, err) + } + a.reset() + return + } + log.Infof("Loaded %d addresses from file '%s'", a.numAddresses(), a.peersFile) +} + +func (a *AddrManager) deserializePeers(filePath string) error { + + _, err := os.Stat(filePath) + if os.IsNotExist(err) { + return nil + } + r, err := os.Open(filePath) + if err != nil { + return fmt.Errorf("%s error opening file: %v", filePath, err) + } + defer r.Close() + + var sam serializedAddrManager + dec := json.NewDecoder(r) + err = dec.Decode(&sam) + if err != nil { + return fmt.Errorf("error reading %s: %v", filePath, err) + } + + // Since decoding JSON is backwards compatible (i.e., only decodes + // fields it understands), we'll only return an error upon seeing a + // version past our latest supported version. + if sam.Version > serialisationVersion { + return fmt.Errorf("unknown version %v in serialized "+ + "addrmanager", sam.Version) + } + + copy(a.key[:], sam.Key[:]) + + for _, v := range sam.Addresses { + ka := new(KnownAddress) + + // The first version of the serialized address manager was not + // aware of the service bits associated with this address, so + // we'll assign a default of SFNodeNetwork to it. + if sam.Version == 1 { + v.Services = wire.SFNodeNetwork + } + ka.na, err = a.DeserializeNetAddress(v.Addr, v.Services) + if err != nil { + return fmt.Errorf("failed to deserialize netaddress "+ + "%s: %v", v.Addr, err) + } + + // The first version of the serialized address manager was not + // aware of the service bits associated with the source address, + // so we'll assign a default of SFNodeNetwork to it. + if sam.Version == 1 { + v.SrcServices = wire.SFNodeNetwork + } + ka.srcAddr, err = a.DeserializeNetAddress(v.Src, v.SrcServices) + if err != nil { + return fmt.Errorf("failed to deserialize netaddress "+ + "%s: %v", v.Src, err) + } + + ka.attempts = v.Attempts + ka.lastattempt = time.Unix(v.LastAttempt, 0) + ka.lastsuccess = time.Unix(v.LastSuccess, 0) + a.addrIndex[NetAddressKey(ka.na)] = ka + } + + for i := range sam.NewBuckets { + for _, val := range sam.NewBuckets[i] { + ka, ok := a.addrIndex[val] + if !ok { + return fmt.Errorf("newbucket contains %s but "+ + "none in address list", val) + } + + if ka.refs == 0 { + a.nNew++ + } + ka.refs++ + a.addrNew[i][val] = ka + } + } + for i := range sam.TriedBuckets { + for _, val := range sam.TriedBuckets[i] { + ka, ok := a.addrIndex[val] + if !ok { + return fmt.Errorf("Newbucket contains %s but "+ + "none in address list", val) + } + + ka.tried = true + a.nTried++ + a.addrTried[i].PushBack(ka) + } + } + + // Sanity checking. + for k, v := range a.addrIndex { + if v.refs == 0 && !v.tried { + return fmt.Errorf("address %s after serialisation "+ + "with no references", k) + } + + if v.refs > 0 && v.tried { + return fmt.Errorf("address %s after serialisation "+ + "which is both new and tried!", k) + } + } + + return nil +} + +// DeserializeNetAddress converts a given address string to a *wire.NetAddress. +func (a *AddrManager) DeserializeNetAddress(addr string, + services wire.ServiceFlag) (*wire.NetAddress, error) { + + host, portStr, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return nil, err + } + + return a.HostToNetAddress(host, uint16(port), services) +} + +// Start begins the core address handler which manages a pool of known +// addresses, timeouts, and interval based writes. +func (a *AddrManager) Start() { + // Already started? + if atomic.AddInt32(&a.started, 1) != 1 { + return + } + + log.Trace("Starting address manager") + + // Load peers we already know about from file. + a.loadPeers() + + // Start the address ticker to save addresses periodically. + a.wg.Add(1) + go a.addressHandler() +} + +// Stop gracefully shuts down the address manager by stopping the main handler. +func (a *AddrManager) Stop() error { + if atomic.AddInt32(&a.shutdown, 1) != 1 { + log.Warnf("Address manager is already in the process of " + + "shutting down") + return nil + } + + log.Infof("Address manager shutting down") + close(a.quit) + a.wg.Wait() + return nil +} + +// AddAddresses adds new addresses to the address manager. It enforces a max +// number of addresses and silently ignores duplicate addresses. It is +// safe for concurrent access. +func (a *AddrManager) AddAddresses(addrs []*wire.NetAddress, srcAddr *wire.NetAddress) { + a.mtx.Lock() + defer a.mtx.Unlock() + + for _, na := range addrs { + a.updateAddress(na, srcAddr) + } +} + +// AddAddress adds a new address to the address manager. It enforces a max +// number of addresses and silently ignores duplicate addresses. It is +// safe for concurrent access. +func (a *AddrManager) AddAddress(addr, srcAddr *wire.NetAddress) { + a.mtx.Lock() + defer a.mtx.Unlock() + + a.updateAddress(addr, srcAddr) +} + +// AddAddressByIP adds an address where we are given an ip:port and not a +// wire.NetAddress. +func (a *AddrManager) AddAddressByIP(addrIP string) error { + // Split IP and port + addr, portStr, err := net.SplitHostPort(addrIP) + if err != nil { + return err + } + // Put it in wire.Netaddress + ip := net.ParseIP(addr) + if ip == nil { + return fmt.Errorf("invalid ip address %s", addr) + } + port, err := strconv.ParseUint(portStr, 10, 0) + if err != nil { + return fmt.Errorf("invalid port %s: %v", portStr, err) + } + na := wire.NewNetAddressIPPort(ip, uint16(port), 0) + a.AddAddress(na, na) // XXX use correct src address + return nil +} + +// NumAddresses returns the number of addresses known to the address manager. +func (a *AddrManager) numAddresses() int { + return a.nTried + a.nNew +} + +// NumAddresses returns the number of addresses known to the address manager. +func (a *AddrManager) NumAddresses() int { + a.mtx.Lock() + defer a.mtx.Unlock() + + return a.numAddresses() +} + +// NeedMoreAddresses returns whether or not the address manager needs more +// addresses. +func (a *AddrManager) NeedMoreAddresses() bool { + a.mtx.Lock() + defer a.mtx.Unlock() + + return a.numAddresses() < needAddressThreshold +} + +// AddressCache returns the current address cache. It must be treated as +// read-only (but since it is a copy now, this is not as dangerous). +func (a *AddrManager) AddressCache() []*wire.NetAddress { + allAddr := a.getAddresses() + + numAddresses := len(allAddr) * getAddrPercent / 100 + if numAddresses > getAddrMax { + numAddresses = getAddrMax + } + + // Fisher-Yates shuffle the array. We only need to do the first + // `numAddresses' since we are throwing the rest. + for i := 0; i < numAddresses; i++ { + // pick a number between current index and the end + j := rand.Intn(len(allAddr)-i) + i + allAddr[i], allAddr[j] = allAddr[j], allAddr[i] + } + + // slice off the limit we are willing to share. + return allAddr[0:numAddresses] +} + +// getAddresses returns all of the addresses currently found within the +// manager's address cache. +func (a *AddrManager) getAddresses() []*wire.NetAddress { + a.mtx.Lock() + defer a.mtx.Unlock() + + addrIndexLen := len(a.addrIndex) + if addrIndexLen == 0 { + return nil + } + + addrs := make([]*wire.NetAddress, 0, addrIndexLen) + for _, v := range a.addrIndex { + addrs = append(addrs, v.na) + } + + return addrs +} + +// reset resets the address manager by reinitialising the random source +// and allocating fresh empty bucket storage. +func (a *AddrManager) reset() { + + a.addrIndex = make(map[string]*KnownAddress) + + // fill key with bytes from a good random source. + io.ReadFull(crand.Reader, a.key[:]) + for i := range a.addrNew { + a.addrNew[i] = make(map[string]*KnownAddress) + } + for i := range a.addrTried { + a.addrTried[i] = list.New() + } +} + +// HostToNetAddress returns a netaddress given a host address. If the address +// is a Tor .onion address this will be taken care of. Else if the host is +// not an IP address it will be resolved (via Tor if required). +func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.ServiceFlag) (*wire.NetAddress, error) { + // Tor address is 16 char base32 + ".onion" + var ip net.IP + if len(host) == 22 && host[16:] == ".onion" { + // go base32 encoding uses capitals (as does the rfc + // but Tor and bitcoind tend to user lowercase, so we switch + // case here. + data, err := base32.StdEncoding.DecodeString( + strings.ToUpper(host[:16])) + if err != nil { + return nil, err + } + prefix := []byte{0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43} + ip = net.IP(append(prefix, data...)) + } else if ip = net.ParseIP(host); ip == nil { + ips, err := a.lookupFunc(host) + if err != nil { + return nil, err + } + if len(ips) == 0 { + return nil, fmt.Errorf("no addresses found for %s", host) + } + ip = ips[0] + } + + return wire.NewNetAddressIPPort(ip, port, services), nil +} + +// ipString returns a string for the ip from the provided NetAddress. If the +// ip is in the range used for Tor addresses then it will be transformed into +// the relevant .onion address. +func ipString(na *wire.NetAddress) string { + if IsOnionCatTor(na) { + // We know now that na.IP is long enough. + base32 := base32.StdEncoding.EncodeToString(na.IP[6:]) + return strings.ToLower(base32) + ".onion" + } + + return na.IP.String() +} + +// NetAddressKey returns a string key in the form of ip:port for IPv4 addresses +// or [ip]:port for IPv6 addresses. +func NetAddressKey(na *wire.NetAddress) string { + port := strconv.FormatUint(uint64(na.Port), 10) + + return net.JoinHostPort(ipString(na), port) +} + +// GetAddress returns a single address that should be routable. It picks a +// random one from the possible addresses with preference given to ones that +// have not been used recently and should not pick 'close' addresses +// consecutively. +func (a *AddrManager) GetAddress() *KnownAddress { + // Protect concurrent access. + a.mtx.Lock() + defer a.mtx.Unlock() + + if a.numAddresses() == 0 { + return nil + } + + // Use a 50% chance for choosing between tried and new table entries. + if a.nTried > 0 && (a.nNew == 0 || a.rand.Intn(2) == 0) { + // Tried entry. + large := 1 << 30 + factor := 1.0 + for { + // pick a random bucket. + bucket := a.rand.Intn(len(a.addrTried)) + if a.addrTried[bucket].Len() == 0 { + continue + } + + // Pick a random entry in the list + e := a.addrTried[bucket].Front() + for i := + a.rand.Int63n(int64(a.addrTried[bucket].Len())); i > 0; i-- { + e = e.Next() + } + ka := e.Value.(*KnownAddress) + randval := a.rand.Intn(large) + if float64(randval) < (factor * ka.chance() * float64(large)) { + log.Tracef("Selected %v from tried bucket", + NetAddressKey(ka.na)) + return ka + } + factor *= 1.2 + } + } else { + // new node. + // XXX use a closure/function to avoid repeating this. + large := 1 << 30 + factor := 1.0 + for { + // Pick a random bucket. + bucket := a.rand.Intn(len(a.addrNew)) + if len(a.addrNew[bucket]) == 0 { + continue + } + // Then, a random entry in it. + var ka *KnownAddress + nth := a.rand.Intn(len(a.addrNew[bucket])) + for _, value := range a.addrNew[bucket] { + if nth == 0 { + ka = value + } + nth-- + } + randval := a.rand.Intn(large) + if float64(randval) < (factor * ka.chance() * float64(large)) { + log.Tracef("Selected %v from new bucket", + NetAddressKey(ka.na)) + return ka + } + factor *= 1.2 + } + } +} + +func (a *AddrManager) find(addr *wire.NetAddress) *KnownAddress { + return a.addrIndex[NetAddressKey(addr)] +} + +// Attempt increases the given address' attempt counter and updates +// the last attempt time. +func (a *AddrManager) Attempt(addr *wire.NetAddress) { + a.mtx.Lock() + defer a.mtx.Unlock() + + // find address. + // Surely address will be in tried by now? + ka := a.find(addr) + if ka == nil { + return + } + // set last tried time to now + ka.attempts++ + ka.lastattempt = time.Now() +} + +// Connected Marks the given address as currently connected and working at the +// current time. The address must already be known to AddrManager else it will +// be ignored. +func (a *AddrManager) Connected(addr *wire.NetAddress) { + a.mtx.Lock() + defer a.mtx.Unlock() + + ka := a.find(addr) + if ka == nil { + return + } + + // Update the time as long as it has been 20 minutes since last we did + // so. + now := time.Now() + if now.After(ka.na.Timestamp.Add(time.Minute * 20)) { + // ka.na is immutable, so replace it. + naCopy := *ka.na + naCopy.Timestamp = time.Now() + ka.na = &naCopy + } +} + +// Good marks the given address as good. To be called after a successful +// connection and version exchange. If the address is unknown to the address +// manager it will be ignored. +func (a *AddrManager) Good(addr *wire.NetAddress) { + a.mtx.Lock() + defer a.mtx.Unlock() + + ka := a.find(addr) + if ka == nil { + return + } + + // ka.Timestamp is not updated here to avoid leaking information + // about currently connected peers. + now := time.Now() + ka.lastsuccess = now + ka.lastattempt = now + ka.attempts = 0 + + // move to tried set, optionally evicting other addresses if neeed. + if ka.tried { + return + } + + // ok, need to move it to tried. + + // remove from all new buckets. + // record one of the buckets in question and call it the `first' + addrKey := NetAddressKey(addr) + oldBucket := -1 + for i := range a.addrNew { + // we check for existence so we can record the first one + if _, ok := a.addrNew[i][addrKey]; ok { + delete(a.addrNew[i], addrKey) + ka.refs-- + if oldBucket == -1 { + oldBucket = i + } + } + } + a.nNew-- + + if oldBucket == -1 { + // What? wasn't in a bucket after all.... Panic? + return + } + + bucket := a.getTriedBucket(ka.na) + + // Room in this tried bucket? + if a.addrTried[bucket].Len() < triedBucketSize { + ka.tried = true + a.addrTried[bucket].PushBack(ka) + a.nTried++ + return + } + + // No room, we have to evict something else. + entry := a.pickTried(bucket) + rmka := entry.Value.(*KnownAddress) + + // First bucket it would have been put in. + newBucket := a.getNewBucket(rmka.na, rmka.srcAddr) + + // If no room in the original bucket, we put it in a bucket we just + // freed up a space in. + if len(a.addrNew[newBucket]) >= newBucketSize { + newBucket = oldBucket + } + + // replace with ka in list. + ka.tried = true + entry.Value = ka + + rmka.tried = false + rmka.refs++ + + // We don't touch a.nTried here since the number of tried stays the same + // but we decemented new above, raise it again since we're putting + // something back. + a.nNew++ + + rmkey := NetAddressKey(rmka.na) + log.Tracef("Replacing %s with %s in tried", rmkey, addrKey) + + // We made sure there is space here just above. + a.addrNew[newBucket][rmkey] = rmka +} + +// SetServices sets the services for the giiven address to the provided value. +func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFlag) { + a.mtx.Lock() + defer a.mtx.Unlock() + + ka := a.find(addr) + if ka == nil { + return + } + + // Update the services if needed. + if ka.na.Services != services { + // ka.na is immutable, so replace it. + naCopy := *ka.na + naCopy.Services = services + ka.na = &naCopy + } +} + +// AddLocalAddress adds na to the list of known local addresses to advertise +// with the given priority. +func (a *AddrManager) AddLocalAddress(na *wire.NetAddress, priority AddressPriority) error { + if !IsRoutable(na) { + return fmt.Errorf("address %s is not routable", na.IP) + } + + a.lamtx.Lock() + defer a.lamtx.Unlock() + + key := NetAddressKey(na) + la, ok := a.localAddresses[key] + if !ok || la.score < priority { + if ok { + la.score = priority + 1 + } else { + a.localAddresses[key] = &localAddress{ + na: na, + score: priority, + } + } + } + return nil +} + +// getReachabilityFrom returns the relative reachability of the provided local +// address to the provided remote address. +func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int { + const ( + Unreachable = 0 + Default = iota + Teredo + Ipv6Weak + Ipv4 + Ipv6Strong + Private + ) + + if !IsRoutable(remoteAddr) { + return Unreachable + } + + if IsOnionCatTor(remoteAddr) { + if IsOnionCatTor(localAddr) { + return Private + } + + if IsRoutable(localAddr) && IsIPv4(localAddr) { + return Ipv4 + } + + return Default + } + + if IsRFC4380(remoteAddr) { + if !IsRoutable(localAddr) { + return Default + } + + if IsRFC4380(localAddr) { + return Teredo + } + + if IsIPv4(localAddr) { + return Ipv4 + } + + return Ipv6Weak + } + + if IsIPv4(remoteAddr) { + if IsRoutable(localAddr) && IsIPv4(localAddr) { + return Ipv4 + } + return Unreachable + } + + /* ipv6 */ + var tunnelled bool + // Is our v6 is tunnelled? + if IsRFC3964(localAddr) || IsRFC6052(localAddr) || IsRFC6145(localAddr) { + tunnelled = true + } + + if !IsRoutable(localAddr) { + return Default + } + + if IsRFC4380(localAddr) { + return Teredo + } + + if IsIPv4(localAddr) { + return Ipv4 + } + + if tunnelled { + // only prioritise ipv6 if we aren't tunnelling it. + return Ipv6Weak + } + + return Ipv6Strong +} + +// GetBestLocalAddress returns the most appropriate local address to use +// for the given remote address. +func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddress) *wire.NetAddress { + a.lamtx.Lock() + defer a.lamtx.Unlock() + + bestreach := 0 + var bestscore AddressPriority + var bestAddress *wire.NetAddress + for _, la := range a.localAddresses { + reach := getReachabilityFrom(la.na, remoteAddr) + if reach > bestreach || + (reach == bestreach && la.score > bestscore) { + bestreach = reach + bestscore = la.score + bestAddress = la.na + } + } + if bestAddress != nil { + log.Debugf("Suggesting address %s:%d for %s:%d", bestAddress.IP, + bestAddress.Port, remoteAddr.IP, remoteAddr.Port) + } else { + log.Debugf("No worthy address for %s:%d", remoteAddr.IP, + remoteAddr.Port) + + // Send something unroutable if nothing suitable. + var ip net.IP + if !IsIPv4(remoteAddr) && !IsOnionCatTor(remoteAddr) { + ip = net.IPv6zero + } else { + ip = net.IPv4zero + } + services := wire.SFNodeNetwork | wire.SFNodeWitness | wire.SFNodeBloom + bestAddress = wire.NewNetAddressIPPort(ip, 0, services) + } + + return bestAddress +} + +// New returns a new bitcoin address manager. +// Use Start to begin processing asynchronous address updates. +func New(dataDir string, lookupFunc func(string) ([]net.IP, error)) *AddrManager { + am := AddrManager{ + peersFile: filepath.Join(dataDir, "peers.json"), + lookupFunc: lookupFunc, + rand: rand.New(rand.NewSource(time.Now().UnixNano())), + quit: make(chan struct{}), + localAddresses: make(map[string]*localAddress), + version: serialisationVersion, + } + am.reset() + return &am +} diff --git a/vendor/github.com/btcsuite/btcd/addrmgr/cov_report.sh b/vendor/github.com/btcsuite/btcd/addrmgr/cov_report.sh new file mode 100644 index 0000000..307f05b --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/addrmgr/cov_report.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# This script uses gocov to generate a test coverage report. +# The gocov tool my be obtained with the following command: +# go get github.com/axw/gocov/gocov +# +# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. + +# Check for gocov. +type gocov >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo >&2 "This script requires the gocov tool." + echo >&2 "You may obtain it with the following command:" + echo >&2 "go get github.com/axw/gocov/gocov" + exit 1 +fi +gocov test | gocov report diff --git a/vendor/github.com/btcsuite/btcd/addrmgr/doc.go b/vendor/github.com/btcsuite/btcd/addrmgr/doc.go new file mode 100644 index 0000000..8ddc8bf --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/addrmgr/doc.go @@ -0,0 +1,38 @@ +// Copyright (c) 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package addrmgr implements concurrency safe Bitcoin address manager. + +Address Manager Overview + +In order maintain the peer-to-peer Bitcoin network, there needs to be a source +of addresses to connect to as nodes come and go. The Bitcoin protocol provides +the getaddr and addr messages to allow peers to communicate known addresses with +each other. However, there needs to a mechanism to store those results and +select peers from them. It is also important to note that remote peers can't +be trusted to send valid peers nor attempt to provide you with only peers they +control with malicious intent. + +With that in mind, this package provides a concurrency safe address manager for +caching and selecting peers in a non-deterministic manner. The general idea is +the caller adds addresses to the address manager and notifies it when addresses +are connected, known good, and attempted. The caller also requests addresses as +it needs them. + +The address manager internally segregates the addresses into groups and +non-deterministically selects groups in a cryptographically random manner. This +reduce the chances multiple addresses from the same nets are selected which +generally helps provide greater peer diversity, and perhaps more importantly, +drastically reduces the chances an attacker is able to coerce your peer into +only connecting to nodes they control. + +The address manager also understands routability and Tor addresses and tries +hard to only return routable addresses. In addition, it uses the information +provided by the caller about connected, known good, and attempted addresses to +periodically purge peers which no longer appear to be good peers as well as +bias the selection toward known good peers. The general idea is to make a best +effort at only providing usable addresses. +*/ +package addrmgr diff --git a/vendor/github.com/btcsuite/btcd/addrmgr/knownaddress.go b/vendor/github.com/btcsuite/btcd/addrmgr/knownaddress.go new file mode 100644 index 0000000..15469f3 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/addrmgr/knownaddress.go @@ -0,0 +1,102 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package addrmgr + +import ( + "time" + + "github.com/btcsuite/btcd/wire" +) + +// KnownAddress tracks information about a known network address that is used +// to determine how viable an address is. +type KnownAddress struct { + na *wire.NetAddress + srcAddr *wire.NetAddress + attempts int + lastattempt time.Time + lastsuccess time.Time + tried bool + refs int // reference count of new buckets +} + +// NetAddress returns the underlying wire.NetAddress associated with the +// known address. +func (ka *KnownAddress) NetAddress() *wire.NetAddress { + return ka.na +} + +// LastAttempt returns the last time the known address was attempted. +func (ka *KnownAddress) LastAttempt() time.Time { + return ka.lastattempt +} + +// Services returns the services supported by the peer with the known address. +func (ka *KnownAddress) Services() wire.ServiceFlag { + return ka.na.Services +} + +// chance returns the selection probability for a known address. The priority +// depends upon how recently the address has been seen, how recently it was last +// attempted and how often attempts to connect to it have failed. +func (ka *KnownAddress) chance() float64 { + now := time.Now() + lastAttempt := now.Sub(ka.lastattempt) + + if lastAttempt < 0 { + lastAttempt = 0 + } + + c := 1.0 + + // Very recent attempts are less likely to be retried. + if lastAttempt < 10*time.Minute { + c *= 0.01 + } + + // Failed attempts deprioritise. + for i := ka.attempts; i > 0; i-- { + c /= 1.5 + } + + return c +} + +// isBad returns true if the address in question has not been tried in the last +// minute and meets one of the following criteria: +// 1) It claims to be from the future +// 2) It hasn't been seen in over a month +// 3) It has failed at least three times and never succeeded +// 4) It has failed ten times in the last week +// All addresses that meet these criteria are assumed to be worthless and not +// worth keeping hold of. +func (ka *KnownAddress) isBad() bool { + if ka.lastattempt.After(time.Now().Add(-1 * time.Minute)) { + return false + } + + // From the future? + if ka.na.Timestamp.After(time.Now().Add(10 * time.Minute)) { + return true + } + + // Over a month old? + if ka.na.Timestamp.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) { + return true + } + + // Never succeeded? + if ka.lastsuccess.IsZero() && ka.attempts >= numRetries { + return true + } + + // Hasn't succeeded in too long? + if !ka.lastsuccess.After(time.Now().Add(-1*minBadDays*time.Hour*24)) && + ka.attempts >= maxFailures { + return true + } + + return false +} diff --git a/vendor/github.com/btcsuite/btcd/addrmgr/log.go b/vendor/github.com/btcsuite/btcd/addrmgr/log.go new file mode 100644 index 0000000..b3ebbd1 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/addrmgr/log.go @@ -0,0 +1,32 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package addrmgr + +import ( + "github.com/btcsuite/btclog" +) + +// log is a logger that is initialized with no output filters. This +// means the package will not perform any logging by default until the caller +// requests it. +var log btclog.Logger + +// The default amount of logging is none. +func init() { + DisableLog() +} + +// DisableLog disables all library log output. Logging output is disabled +// by default until either UseLogger or SetLogWriter are called. +func DisableLog() { + log = btclog.Disabled +} + +// UseLogger uses a specified Logger to output package logging info. +// This should be used in preference to SetLogWriter if the caller is also +// using btclog. +func UseLogger(logger btclog.Logger) { + log = logger +} diff --git a/vendor/github.com/btcsuite/btcd/addrmgr/network.go b/vendor/github.com/btcsuite/btcd/addrmgr/network.go new file mode 100644 index 0000000..51bfa3e --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/addrmgr/network.go @@ -0,0 +1,281 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package addrmgr + +import ( + "fmt" + "net" + + "github.com/btcsuite/btcd/wire" +) + +var ( + // rfc1918Nets specifies the IPv4 private address blocks as defined by + // by RFC1918 (10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16). + rfc1918Nets = []net.IPNet{ + ipNet("10.0.0.0", 8, 32), + ipNet("172.16.0.0", 12, 32), + ipNet("192.168.0.0", 16, 32), + } + + // rfc2544Net specifies the the IPv4 block as defined by RFC2544 + // (198.18.0.0/15) + rfc2544Net = ipNet("198.18.0.0", 15, 32) + + // rfc3849Net specifies the IPv6 documentation address block as defined + // by RFC3849 (2001:DB8::/32). + rfc3849Net = ipNet("2001:DB8::", 32, 128) + + // rfc3927Net specifies the IPv4 auto configuration address block as + // defined by RFC3927 (169.254.0.0/16). + rfc3927Net = ipNet("169.254.0.0", 16, 32) + + // rfc3964Net specifies the IPv6 to IPv4 encapsulation address block as + // defined by RFC3964 (2002::/16). + rfc3964Net = ipNet("2002::", 16, 128) + + // rfc4193Net specifies the IPv6 unique local address block as defined + // by RFC4193 (FC00::/7). + rfc4193Net = ipNet("FC00::", 7, 128) + + // rfc4380Net specifies the IPv6 teredo tunneling over UDP address block + // as defined by RFC4380 (2001::/32). + rfc4380Net = ipNet("2001::", 32, 128) + + // rfc4843Net specifies the IPv6 ORCHID address block as defined by + // RFC4843 (2001:10::/28). + rfc4843Net = ipNet("2001:10::", 28, 128) + + // rfc4862Net specifies the IPv6 stateless address autoconfiguration + // address block as defined by RFC4862 (FE80::/64). + rfc4862Net = ipNet("FE80::", 64, 128) + + // rfc5737Net specifies the IPv4 documentation address blocks as defined + // by RFC5737 (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) + rfc5737Net = []net.IPNet{ + ipNet("192.0.2.0", 24, 32), + ipNet("198.51.100.0", 24, 32), + ipNet("203.0.113.0", 24, 32), + } + + // rfc6052Net specifies the IPv6 well-known prefix address block as + // defined by RFC6052 (64:FF9B::/96). + rfc6052Net = ipNet("64:FF9B::", 96, 128) + + // rfc6145Net specifies the IPv6 to IPv4 translated address range as + // defined by RFC6145 (::FFFF:0:0:0/96). + rfc6145Net = ipNet("::FFFF:0:0:0", 96, 128) + + // rfc6598Net specifies the IPv4 block as defined by RFC6598 (100.64.0.0/10) + rfc6598Net = ipNet("100.64.0.0", 10, 32) + + // onionCatNet defines the IPv6 address block used to support Tor. + // bitcoind encodes a .onion address as a 16 byte number by decoding the + // address prior to the .onion (i.e. the key hash) base32 into a ten + // byte number. It then stores the first 6 bytes of the address as + // 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43. + // + // This is the same range used by OnionCat, which is part part of the + // RFC4193 unique local IPv6 range. + // + // In summary the format is: + // { magic 6 bytes, 10 bytes base32 decode of key hash } + onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128) + + // zero4Net defines the IPv4 address block for address staring with 0 + // (0.0.0.0/8). + zero4Net = ipNet("0.0.0.0", 8, 32) + + // heNet defines the Hurricane Electric IPv6 address block. + heNet = ipNet("2001:470::", 32, 128) +) + +// ipNet returns a net.IPNet struct given the passed IP address string, number +// of one bits to include at the start of the mask, and the total number of bits +// for the mask. +func ipNet(ip string, ones, bits int) net.IPNet { + return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)} +} + +// IsIPv4 returns whether or not the given address is an IPv4 address. +func IsIPv4(na *wire.NetAddress) bool { + return na.IP.To4() != nil +} + +// IsLocal returns whether or not the given address is a local address. +func IsLocal(na *wire.NetAddress) bool { + return na.IP.IsLoopback() || zero4Net.Contains(na.IP) +} + +// IsOnionCatTor returns whether or not the passed address is in the IPv6 range +// used by bitcoin to support Tor (fd87:d87e:eb43::/48). Note that this range +// is the same range used by OnionCat, which is part of the RFC4193 unique local +// IPv6 range. +func IsOnionCatTor(na *wire.NetAddress) bool { + return onionCatNet.Contains(na.IP) +} + +// IsRFC1918 returns whether or not the passed address is part of the IPv4 +// private network address space as defined by RFC1918 (10.0.0.0/8, +// 172.16.0.0/12, or 192.168.0.0/16). +func IsRFC1918(na *wire.NetAddress) bool { + for _, rfc := range rfc1918Nets { + if rfc.Contains(na.IP) { + return true + } + } + return false +} + +// IsRFC2544 returns whether or not the passed address is part of the IPv4 +// address space as defined by RFC2544 (198.18.0.0/15) +func IsRFC2544(na *wire.NetAddress) bool { + return rfc2544Net.Contains(na.IP) +} + +// IsRFC3849 returns whether or not the passed address is part of the IPv6 +// documentation range as defined by RFC3849 (2001:DB8::/32). +func IsRFC3849(na *wire.NetAddress) bool { + return rfc3849Net.Contains(na.IP) +} + +// IsRFC3927 returns whether or not the passed address is part of the IPv4 +// autoconfiguration range as defined by RFC3927 (169.254.0.0/16). +func IsRFC3927(na *wire.NetAddress) bool { + return rfc3927Net.Contains(na.IP) +} + +// IsRFC3964 returns whether or not the passed address is part of the IPv6 to +// IPv4 encapsulation range as defined by RFC3964 (2002::/16). +func IsRFC3964(na *wire.NetAddress) bool { + return rfc3964Net.Contains(na.IP) +} + +// IsRFC4193 returns whether or not the passed address is part of the IPv6 +// unique local range as defined by RFC4193 (FC00::/7). +func IsRFC4193(na *wire.NetAddress) bool { + return rfc4193Net.Contains(na.IP) +} + +// IsRFC4380 returns whether or not the passed address is part of the IPv6 +// teredo tunneling over UDP range as defined by RFC4380 (2001::/32). +func IsRFC4380(na *wire.NetAddress) bool { + return rfc4380Net.Contains(na.IP) +} + +// IsRFC4843 returns whether or not the passed address is part of the IPv6 +// ORCHID range as defined by RFC4843 (2001:10::/28). +func IsRFC4843(na *wire.NetAddress) bool { + return rfc4843Net.Contains(na.IP) +} + +// IsRFC4862 returns whether or not the passed address is part of the IPv6 +// stateless address autoconfiguration range as defined by RFC4862 (FE80::/64). +func IsRFC4862(na *wire.NetAddress) bool { + return rfc4862Net.Contains(na.IP) +} + +// IsRFC5737 returns whether or not the passed address is part of the IPv4 +// documentation address space as defined by RFC5737 (192.0.2.0/24, +// 198.51.100.0/24, 203.0.113.0/24) +func IsRFC5737(na *wire.NetAddress) bool { + for _, rfc := range rfc5737Net { + if rfc.Contains(na.IP) { + return true + } + } + + return false +} + +// IsRFC6052 returns whether or not the passed address is part of the IPv6 +// well-known prefix range as defined by RFC6052 (64:FF9B::/96). +func IsRFC6052(na *wire.NetAddress) bool { + return rfc6052Net.Contains(na.IP) +} + +// IsRFC6145 returns whether or not the passed address is part of the IPv6 to +// IPv4 translated address range as defined by RFC6145 (::FFFF:0:0:0/96). +func IsRFC6145(na *wire.NetAddress) bool { + return rfc6145Net.Contains(na.IP) +} + +// IsRFC6598 returns whether or not the passed address is part of the IPv4 +// shared address space specified by RFC6598 (100.64.0.0/10) +func IsRFC6598(na *wire.NetAddress) bool { + return rfc6598Net.Contains(na.IP) +} + +// IsValid returns whether or not the passed address is valid. The address is +// considered invalid under the following circumstances: +// IPv4: It is either a zero or all bits set address. +// IPv6: It is either a zero or RFC3849 documentation address. +func IsValid(na *wire.NetAddress) bool { + // IsUnspecified returns if address is 0, so only all bits set, and + // RFC3849 need to be explicitly checked. + return na.IP != nil && !(na.IP.IsUnspecified() || + na.IP.Equal(net.IPv4bcast)) +} + +// IsRoutable returns whether or not the passed address is routable over +// the public internet. This is true as long as the address is valid and is not +// in any reserved ranges. +func IsRoutable(na *wire.NetAddress) bool { + return IsValid(na) && !(IsRFC1918(na) || IsRFC2544(na) || + IsRFC3927(na) || IsRFC4862(na) || IsRFC3849(na) || + IsRFC4843(na) || IsRFC5737(na) || IsRFC6598(na) || + IsLocal(na) || (IsRFC4193(na) && !IsOnionCatTor(na))) +} + +// GroupKey returns a string representing the network group an address is part +// of. This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string +// "local" for a local address, the string "tor:key" where key is the /4 of the +// onion address for Tor address, and the string "unroutable" for an unroutable +// address. +func GroupKey(na *wire.NetAddress) string { + if IsLocal(na) { + return "local" + } + if !IsRoutable(na) { + return "unroutable" + } + if IsIPv4(na) { + return na.IP.Mask(net.CIDRMask(16, 32)).String() + } + if IsRFC6145(na) || IsRFC6052(na) { + // last four bytes are the ip address + ip := na.IP[12:16] + return ip.Mask(net.CIDRMask(16, 32)).String() + } + + if IsRFC3964(na) { + ip := na.IP[2:6] + return ip.Mask(net.CIDRMask(16, 32)).String() + + } + if IsRFC4380(na) { + // teredo tunnels have the last 4 bytes as the v4 address XOR + // 0xff. + ip := net.IP(make([]byte, 4)) + for i, byte := range na.IP[12:16] { + ip[i] = byte ^ 0xff + } + return ip.Mask(net.CIDRMask(16, 32)).String() + } + if IsOnionCatTor(na) { + // group is keyed off the first 4 bits of the actual onion key. + return fmt.Sprintf("tor:%d", na.IP[6]&((1<<4)-1)) + } + + // OK, so now we know ourselves to be a IPv6 address. + // bitcoind uses /32 for everything, except for Hurricane Electric's + // (he.net) IP range, which it uses /36 for. + bits := 32 + if heNet.Contains(na.IP) { + bits = 36 + } + + return na.IP.Mask(net.CIDRMask(bits, 128)).String() +} diff --git a/vendor/github.com/btcsuite/btcd/addrmgr/test_coverage.txt b/vendor/github.com/btcsuite/btcd/addrmgr/test_coverage.txt new file mode 100644 index 0000000..c67e0f6 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/addrmgr/test_coverage.txt @@ -0,0 +1,62 @@ + +github.com/conformal/btcd/addrmgr/network.go GroupKey 100.00% (23/23) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.reset 100.00% (6/6) +github.com/conformal/btcd/addrmgr/network.go IsRFC5737 100.00% (4/4) +github.com/conformal/btcd/addrmgr/network.go IsRFC1918 100.00% (4/4) +github.com/conformal/btcd/addrmgr/addrmanager.go New 100.00% (3/3) +github.com/conformal/btcd/addrmgr/addrmanager.go NetAddressKey 100.00% (2/2) +github.com/conformal/btcd/addrmgr/network.go IsRFC4862 100.00% (1/1) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.numAddresses 100.00% (1/1) +github.com/conformal/btcd/addrmgr/log.go init 100.00% (1/1) +github.com/conformal/btcd/addrmgr/log.go DisableLog 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go ipNet 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsIPv4 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsLocal 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsOnionCatTor 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC2544 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC3849 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC3927 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC3964 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC4193 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC4380 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC4843 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC6052 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC6145 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRFC6598 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsValid 100.00% (1/1) +github.com/conformal/btcd/addrmgr/network.go IsRoutable 100.00% (1/1) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.GetBestLocalAddress 94.74% (18/19) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddLocalAddress 90.91% (10/11) +github.com/conformal/btcd/addrmgr/addrmanager.go getReachabilityFrom 51.52% (17/33) +github.com/conformal/btcd/addrmgr/addrmanager.go ipString 50.00% (2/4) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.GetAddress 9.30% (4/43) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.deserializePeers 0.00% (0/50) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Good 0.00% (0/44) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.savePeers 0.00% (0/39) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.updateAddress 0.00% (0/30) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.expireNew 0.00% (0/22) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddressCache 0.00% (0/16) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.HostToNetAddress 0.00% (0/15) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.getNewBucket 0.00% (0/15) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddAddressByIP 0.00% (0/14) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.getTriedBucket 0.00% (0/14) +github.com/conformal/btcd/addrmgr/knownaddress.go knownAddress.chance 0.00% (0/13) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.loadPeers 0.00% (0/11) +github.com/conformal/btcd/addrmgr/knownaddress.go knownAddress.isBad 0.00% (0/11) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Connected 0.00% (0/10) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.addressHandler 0.00% (0/9) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.pickTried 0.00% (0/8) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.DeserializeNetAddress 0.00% (0/7) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Stop 0.00% (0/7) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Attempt 0.00% (0/7) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Start 0.00% (0/6) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddAddresses 0.00% (0/4) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.NeedMoreAddresses 0.00% (0/3) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.NumAddresses 0.00% (0/3) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddAddress 0.00% (0/3) +github.com/conformal/btcd/addrmgr/knownaddress.go knownAddress.LastAttempt 0.00% (0/1) +github.com/conformal/btcd/addrmgr/knownaddress.go knownAddress.NetAddress 0.00% (0/1) +github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.find 0.00% (0/1) +github.com/conformal/btcd/addrmgr/log.go UseLogger 0.00% (0/1) +github.com/conformal/btcd/addrmgr --------------------------------- 21.04% (113/537) + diff --git a/vendor/github.com/btcsuite/btcd/blockchain/README.md b/vendor/github.com/btcsuite/btcd/blockchain/README.md new file mode 100644 index 0000000..de5611b --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/blockchain/README.md @@ -0,0 +1,103 @@ +blockchain +========== + +[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/blockchain) + +Package blockchain implements bitcoin block handling and chain selection rules. +The test coverage is currently only around 60%, but will be increasing over +time. See `test_coverage.txt` for the gocov coverage report. Alternatively, if +you are running a POSIX OS, you can run the `cov_report.sh` script for a +real-time report. Package blockchain is licensed under the liberal ISC license. + +There is an associated blog post about the release of this package +[here](https://blog.conformal.com/btcchain-the-bitcoin-chain-package-from-bctd/). + +This package has intentionally been designed so it can be used as a standalone +package for any projects needing to handle processing of blocks into the bitcoin +block chain. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/blockchain +``` + +## Bitcoin Chain Processing Overview + +Before a block is allowed into the block chain, it must go through an intensive +series of validation rules. The following list serves as a general outline of +those rules to provide some intuition into what is going on under the hood, but +is by no means exhaustive: + + - Reject duplicate blocks + - Perform a series of sanity checks on the block and its transactions such as + verifying proof of work, timestamps, number and character of transactions, + transaction amounts, script complexity, and merkle root calculations + - Compare the block against predetermined checkpoints for expected timestamps + and difficulty based on elapsed time since the checkpoint + - Save the most recent orphan blocks for a limited time in case their parent + blocks become available + - Stop processing if the block is an orphan as the rest of the processing + depends on the block's position within the block chain + - Perform a series of more thorough checks that depend on the block's position + within the block chain such as verifying block difficulties adhere to + difficulty retarget rules, timestamps are after the median of the last + several blocks, all transactions are finalized, checkpoint blocks match, and + block versions are in line with the previous blocks + - Determine how the block fits into the chain and perform different actions + accordingly in order to ensure any side chains which have higher difficulty + than the main chain become the new main chain + - When a block is being connected to the main chain (either through + reorganization of a side chain to the main chain or just extending the + main chain), perform further checks on the block's transactions such as + verifying transaction duplicates, script complexity for the combination of + connected scripts, coinbase maturity, double spends, and connected + transaction values + - Run the transaction scripts to verify the spender is allowed to spend the + coins + - Insert the block into the block database + +## Examples + +* [ProcessBlock Example](http://godoc.org/github.com/btcsuite/btcd/blockchain#example-BlockChain-ProcessBlock) + Demonstrates how to create a new chain instance and use ProcessBlock to + attempt to add a block to the chain. This example intentionally + attempts to insert a duplicate genesis block to illustrate how an invalid + block is handled. + +* [CompactToBig Example](http://godoc.org/github.com/btcsuite/btcd/blockchain#example-CompactToBig) + Demonstrates how to convert the compact "bits" in a block header which + represent the target difficulty to a big integer and display it using the + typical hex notation. + +* [BigToCompact Example](http://godoc.org/github.com/btcsuite/btcd/blockchain#example-BigToCompact) + Demonstrates how to convert a target difficulty into the + compact "bits" in a block header which represent that target difficulty. + +## GPG Verification Key + +All official release tags are signed by Conformal so users can ensure the code +has not been tampered with and is coming from the btcsuite developers. To +verify the signature perform the following: + +- Download the public key from the Conformal website at + https://opensource.conformal.com/GIT-GPG-KEY-conformal.txt + +- Import the public key into your GPG keyring: + ```bash + gpg --import GIT-GPG-KEY-conformal.txt + ``` + +- Verify the release tag with the following command where `TAG_NAME` is a + placeholder for the specific tag: + ```bash + git tag -v TAG_NAME + ``` + +## License + + +Package blockchain is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/vendor/github.com/btcsuite/btcd/blockchain/accept.go b/vendor/github.com/btcsuite/btcd/blockchain/accept.go new file mode 100644 index 0000000..f85d655 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/blockchain/accept.go @@ -0,0 +1,92 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "fmt" + + "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcutil" +) + +// maybeAcceptBlock potentially accepts a block into the block chain and, if +// accepted, returns whether or not it is on the main chain. It performs +// several validation checks which depend on its position within the block chain +// before adding it. The block is expected to have already gone through +// ProcessBlock before calling this function with it. +// +// The flags are also passed to checkBlockContext and connectBestChain. See +// their documentation for how the flags modify their behavior. +// +// This function MUST be called with the chain state lock held (for writes). +func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) (bool, error) { + // The height of this block is one more than the referenced previous + // block. + prevHash := &block.MsgBlock().Header.PrevBlock + prevNode := b.index.LookupNode(prevHash) + if prevNode == nil { + str := fmt.Sprintf("previous block %s is unknown", prevHash) + return false, ruleError(ErrPreviousBlockUnknown, str) + } else if b.index.NodeStatus(prevNode).KnownInvalid() { + str := fmt.Sprintf("previous block %s is known to be invalid", prevHash) + return false, ruleError(ErrInvalidAncestorBlock, str) + } + + blockHeight := prevNode.height + 1 + block.SetHeight(blockHeight) + + // The block must pass all of the validation rules which depend on the + // position of the block within the block chain. + err := b.checkBlockContext(block, prevNode, flags) + if err != nil { + return false, err + } + + // Insert the block into the database if it's not already there. Even + // though it is possible the block will ultimately fail to connect, it + // has already passed all proof-of-work and validity tests which means + // it would be prohibitively expensive for an attacker to fill up the + // disk with a bunch of blocks that fail to connect. This is necessary + // since it allows block download to be decoupled from the much more + // expensive connection logic. It also has some other nice properties + // such as making blocks that never become part of the main chain or + // blocks that fail to connect available for further analysis. + err = b.db.Update(func(dbTx database.Tx) error { + return dbStoreBlock(dbTx, block) + }) + if err != nil { + return false, err + } + + // Create a new block node for the block and add it to the node index. Even + // if the block ultimately gets connected to the main chain, it starts out + // on a side chain. + blockHeader := &block.MsgBlock().Header + newNode := newBlockNode(blockHeader, prevNode) + newNode.status = statusDataStored + + b.index.AddNode(newNode) + err = b.index.flushToDB() + if err != nil { + return false, err + } + + // Connect the passed block to the chain while respecting proper chain + // selection according to the chain with the most proof of work. This + // also handles validation of the transaction scripts. + isMainChain, err := b.connectBestChain(newNode, block, flags) + if err != nil { + return false, err + } + + // Notify the caller that the new block was accepted into the block + // chain. The caller would typically want to react by relaying the + // inventory to other peers. + b.chainLock.Unlock() + b.sendNotification(NTBlockAccepted, block) + b.chainLock.Lock() + + return isMainChain, nil +} diff --git a/vendor/github.com/btcsuite/btcd/blockchain/blockindex.go b/vendor/github.com/btcsuite/btcd/blockchain/blockindex.go new file mode 100644 index 0000000..2ff2fa2 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/blockchain/blockindex.go @@ -0,0 +1,348 @@ +// Copyright (c) 2015-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "math/big" + "sort" + "sync" + "time" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcd/wire" +) + +// blockStatus is a bit field representing the validation state of the block. +type blockStatus byte + +const ( + // statusDataStored indicates that the block's payload is stored on disk. + statusDataStored blockStatus = 1 << iota + + // statusValid indicates that the block has been fully validated. + statusValid + + // statusValidateFailed indicates that the block has failed validation. + statusValidateFailed + + // statusInvalidAncestor indicates that one of the block's ancestors has + // has failed validation, thus the block is also invalid. + statusInvalidAncestor + + // statusNone indicates that the block has no validation state flags set. + // + // NOTE: This must be defined last in order to avoid influencing iota. + statusNone blockStatus = 0 +) + +// HaveData returns whether the full block data is stored in the database. This +// will return false for a block node where only the header is downloaded or +// kept. +func (status blockStatus) HaveData() bool { + return status&statusDataStored != 0 +} + +// KnownValid returns whether the block is known to be valid. This will return +// false for a valid block that has not been fully validated yet. +func (status blockStatus) KnownValid() bool { + return status&statusValid != 0 +} + +// KnownInvalid returns whether the block is known to be invalid. This may be +// because the block itself failed validation or any of its ancestors is +// invalid. This will return false for invalid blocks that have not been proven +// invalid yet. +func (status blockStatus) KnownInvalid() bool { + return status&(statusValidateFailed|statusInvalidAncestor) != 0 +} + +// blockNode represents a block within the block chain and is primarily used to +// aid in selecting the best chain to be the main chain. The main chain is +// stored into the block database. +type blockNode struct { + // NOTE: Additions, deletions, or modifications to the order of the + // definitions in this struct should not be changed without considering + // how it affects alignment on 64-bit platforms. The current order is + // specifically crafted to result in minimal padding. There will be + // hundreds of thousands of these in memory, so a few extra bytes of + // padding adds up. + + // parent is the parent block for this node. + parent *blockNode + + // hash is the double sha 256 of the block. + hash chainhash.Hash + + // workSum is the total amount of work in the chain up to and including + // this node. + workSum *big.Int + + // height is the position in the block chain. + height int32 + + // Some fields from block headers to aid in best chain selection and + // reconstructing headers from memory. These must be treated as + // immutable and are intentionally ordered to avoid padding on 64-bit + // platforms. + version int32 + bits uint32 + nonce uint32 + timestamp int64 + merkleRoot chainhash.Hash + + // status is a bitfield representing the validation state of the block. The + // status field, unlike the other fields, may be written to and so should + // only be accessed using the concurrent-safe NodeStatus method on + // blockIndex once the node has been added to the global index. + status blockStatus +} + +// initBlockNode initializes a block node from the given header and parent node, +// calculating the height and workSum from the respective fields on the parent. +// This function is NOT safe for concurrent access. It must only be called when +// initially creating a node. +func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, parent *blockNode) { + *node = blockNode{ + hash: blockHeader.BlockHash(), + workSum: CalcWork(blockHeader.Bits), + version: blockHeader.Version, + bits: blockHeader.Bits, + nonce: blockHeader.Nonce, + timestamp: blockHeader.Timestamp.Unix(), + merkleRoot: blockHeader.MerkleRoot, + } + if parent != nil { + node.parent = parent + node.height = parent.height + 1 + node.workSum = node.workSum.Add(parent.workSum, node.workSum) + } +} + +// newBlockNode returns a new block node for the given block header and parent +// node, calculating the height and workSum from the respective fields on the +// parent. This function is NOT safe for concurrent access. +func newBlockNode(blockHeader *wire.BlockHeader, parent *blockNode) *blockNode { + var node blockNode + initBlockNode(&node, blockHeader, parent) + return &node +} + +// Header constructs a block header from the node and returns it. +// +// This function is safe for concurrent access. +func (node *blockNode) Header() wire.BlockHeader { + // No lock is needed because all accessed fields are immutable. + prevHash := &zeroHash + if node.parent != nil { + prevHash = &node.parent.hash + } + return wire.BlockHeader{ + Version: node.version, + PrevBlock: *prevHash, + MerkleRoot: node.merkleRoot, + Timestamp: time.Unix(node.timestamp, 0), + Bits: node.bits, + Nonce: node.nonce, + } +} + +// Ancestor returns the ancestor block node at the provided height by following +// the chain backwards from this node. The returned block will be nil when a +// height is requested that is after the height of the passed node or is less +// than zero. +// +// This function is safe for concurrent access. +func (node *blockNode) Ancestor(height int32) *blockNode { + if height < 0 || height > node.height { + return nil + } + + n := node + for ; n != nil && n.height != height; n = n.parent { + // Intentionally left blank + } + + return n +} + +// RelativeAncestor returns the ancestor block node a relative 'distance' blocks +// before this node. This is equivalent to calling Ancestor with the node's +// height minus provided distance. +// +// This function is safe for concurrent access. +func (node *blockNode) RelativeAncestor(distance int32) *blockNode { + return node.Ancestor(node.height - distance) +} + +// CalcPastMedianTime calculates the median time of the previous few blocks +// prior to, and including, the block node. +// +// This function is safe for concurrent access. +func (node *blockNode) CalcPastMedianTime() time.Time { + // Create a slice of the previous few block timestamps used to calculate + // the median per the number defined by the constant medianTimeBlocks. + timestamps := make([]int64, medianTimeBlocks) + numNodes := 0 + iterNode := node + for i := 0; i < medianTimeBlocks && iterNode != nil; i++ { + timestamps[i] = iterNode.timestamp + numNodes++ + + iterNode = iterNode.parent + } + + // Prune the slice to the actual number of available timestamps which + // will be fewer than desired near the beginning of the block chain + // and sort them. + timestamps = timestamps[:numNodes] + sort.Sort(timeSorter(timestamps)) + + // NOTE: The consensus rules incorrectly calculate the median for even + // numbers of blocks. A true median averages the middle two elements + // for a set with an even number of elements in it. Since the constant + // for the previous number of blocks to be used is odd, this is only an + // issue for a few blocks near the beginning of the chain. I suspect + // this is an optimization even though the result is slightly wrong for + // a few of the first blocks since after the first few blocks, there + // will always be an odd number of blocks in the set per the constant. + // + // This code follows suit to ensure the same rules are used, however, be + // aware that should the medianTimeBlocks constant ever be changed to an + // even number, this code will be wrong. + medianTimestamp := timestamps[numNodes/2] + return time.Unix(medianTimestamp, 0) +} + +// blockIndex provides facilities for keeping track of an in-memory index of the +// block chain. Although the name block chain suggests a single chain of +// blocks, it is actually a tree-shaped structure where any node can have +// multiple children. However, there can only be one active branch which does +// indeed form a chain from the tip all the way back to the genesis block. +type blockIndex struct { + // The following fields are set when the instance is created and can't + // be changed afterwards, so there is no need to protect them with a + // separate mutex. + db database.DB + chainParams *chaincfg.Params + + sync.RWMutex + index map[chainhash.Hash]*blockNode + dirty map[*blockNode]struct{} +} + +// newBlockIndex returns a new empty instance of a block index. The index will +// be dynamically populated as block nodes are loaded from the database and +// manually added. +func newBlockIndex(db database.DB, chainParams *chaincfg.Params) *blockIndex { + return &blockIndex{ + db: db, + chainParams: chainParams, + index: make(map[chainhash.Hash]*blockNode), + dirty: make(map[*blockNode]struct{}), + } +} + +// HaveBlock returns whether or not the block index contains the provided hash. +// +// This function is safe for concurrent access. +func (bi *blockIndex) HaveBlock(hash *chainhash.Hash) bool { + bi.RLock() + _, hasBlock := bi.index[*hash] + bi.RUnlock() + return hasBlock +} + +// LookupNode returns the block node identified by the provided hash. It will +// return nil if there is no entry for the hash. +// +// This function is safe for concurrent access. +func (bi *blockIndex) LookupNode(hash *chainhash.Hash) *blockNode { + bi.RLock() + node := bi.index[*hash] + bi.RUnlock() + return node +} + +// AddNode adds the provided node to the block index and marks it as dirty. +// Duplicate entries are not checked so it is up to caller to avoid adding them. +// +// This function is safe for concurrent access. +func (bi *blockIndex) AddNode(node *blockNode) { + bi.Lock() + bi.addNode(node) + bi.dirty[node] = struct{}{} + bi.Unlock() +} + +// addNode adds the provided node to the block index, but does not mark it as +// dirty. This can be used while initializing the block index. +// +// This function is NOT safe for concurrent access. +func (bi *blockIndex) addNode(node *blockNode) { + bi.index[node.hash] = node +} + +// NodeStatus provides concurrent-safe access to the status field of a node. +// +// This function is safe for concurrent access. +func (bi *blockIndex) NodeStatus(node *blockNode) blockStatus { + bi.RLock() + status := node.status + bi.RUnlock() + return status +} + +// SetStatusFlags flips the provided status flags on the block node to on, +// regardless of whether they were on or off previously. This does not unset any +// flags currently on. +// +// This function is safe for concurrent access. +func (bi *blockIndex) SetStatusFlags(node *blockNode, flags blockStatus) { + bi.Lock() + node.status |= flags + bi.dirty[node] = struct{}{} + bi.Unlock() +} + +// UnsetStatusFlags flips the provided status flags on the block node to off, +// regardless of whether they were on or off previously. +// +// This function is safe for concurrent access. +func (bi *blockIndex) UnsetStatusFlags(node *blockNode, flags blockStatus) { + bi.Lock() + node.status &^= flags + bi.dirty[node] = struct{}{} + bi.Unlock() +} + +// flushToDB writes all dirty block nodes to the database. If all writes +// succeed, this clears the dirty set. +func (bi *blockIndex) flushToDB() error { + bi.Lock() + if len(bi.dirty) == 0 { + bi.Unlock() + return nil + } + + err := bi.db.Update(func(dbTx database.Tx) error { + for node := range bi.dirty { + err := dbStoreBlockNode(dbTx, node) + if err != nil { + return err + } + } + return nil + }) + + // If write was successful, clear the dirty set. + if err == nil { + bi.dirty = make(map[*blockNode]struct{}) + } + + bi.Unlock() + return err +} diff --git a/vendor/github.com/btcsuite/btcd/blockchain/chain.go b/vendor/github.com/btcsuite/btcd/blockchain/chain.go new file mode 100644 index 0000000..71c1b2e --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/blockchain/chain.go @@ -0,0 +1,1803 @@ +// Copyright (c) 2013-2018 The btcsuite developers +// Copyright (c) 2015-2018 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "container/list" + "fmt" + "sync" + "time" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" +) + +const ( + // maxOrphanBlocks is the maximum number of orphan blocks that can be + // queued. + maxOrphanBlocks = 100 +) + +// BlockLocator is used to help locate a specific block. The algorithm for +// building the block locator is to add the hashes in reverse order until +// the genesis block is reached. In order to keep the list of locator hashes +// to a reasonable number of entries, first the most recent previous 12 block +// hashes are added, then the step is doubled each loop iteration to +// exponentially decrease the number of hashes as a function of the distance +// from the block being located. +// +// For example, assume a block chain with a side chain as depicted below: +// genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 +// \-> 16a -> 17a +// +// The block locator for block 17a would be the hashes of blocks: +// [17a 16a 15 14 13 12 11 10 9 8 7 6 4 genesis] +type BlockLocator []*chainhash.Hash + +// orphanBlock represents a block that we don't yet have the parent for. It +// is a normal block plus an expiration time to prevent caching the orphan +// forever. +type orphanBlock struct { + block *btcutil.Block + expiration time.Time +} + +// BestState houses information about the current best block and other info +// related to the state of the main chain as it exists from the point of view of +// the current best block. +// +// The BestSnapshot method can be used to obtain access to this information +// in a concurrent safe manner and the data will not be changed out from under +// the caller when chain state changes occur as the function name implies. +// However, the returned snapshot must be treated as immutable since it is +// shared by all callers. +type BestState struct { + Hash chainhash.Hash // The hash of the block. + Height int32 // The height of the block. + Bits uint32 // The difficulty bits of the block. + BlockSize uint64 // The size of the block. + BlockWeight uint64 // The weight of the block. + NumTxns uint64 // The number of txns in the block. + TotalTxns uint64 // The total number of txns in the chain. + MedianTime time.Time // Median time as per CalcPastMedianTime. +} + +// newBestState returns a new best stats instance for the given parameters. +func newBestState(node *blockNode, blockSize, blockWeight, numTxns, + totalTxns uint64, medianTime time.Time) *BestState { + + return &BestState{ + Hash: node.hash, + Height: node.height, + Bits: node.bits, + BlockSize: blockSize, + BlockWeight: blockWeight, + NumTxns: numTxns, + TotalTxns: totalTxns, + MedianTime: medianTime, + } +} + +// BlockChain provides functions for working with the bitcoin block chain. +// It includes functionality such as rejecting duplicate blocks, ensuring blocks +// follow all rules, orphan handling, checkpoint handling, and best chain +// selection with reorganization. +type BlockChain struct { + // The following fields are set when the instance is created and can't + // be changed afterwards, so there is no need to protect them with a + // separate mutex. + checkpoints []chaincfg.Checkpoint + checkpointsByHeight map[int32]*chaincfg.Checkpoint + db database.DB + chainParams *chaincfg.Params + timeSource MedianTimeSource + sigCache *txscript.SigCache + indexManager IndexManager + hashCache *txscript.HashCache + + // The following fields are calculated based upon the provided chain + // parameters. They are also set when the instance is created and + // can't be changed afterwards, so there is no need to protect them with + // a separate mutex. + minRetargetTimespan int64 // target timespan / adjustment factor + maxRetargetTimespan int64 // target timespan * adjustment factor + blocksPerRetarget int32 // target timespan / target time per block + + // chainLock protects concurrent access to the vast majority of the + // fields in this struct below this point. + chainLock sync.RWMutex + + // These fields are related to the memory block index. They both have + // their own locks, however they are often also protected by the chain + // lock to help prevent logic races when blocks are being processed. + // + // index houses the entire block index in memory. The block index is + // a tree-shaped structure. + // + // bestChain tracks the current active chain by making use of an + // efficient chain view into the block index. + index *blockIndex + bestChain *chainView + + // These fields are related to handling of orphan blocks. They are + // protected by a combination of the chain lock and the orphan lock. + orphanLock sync.RWMutex + orphans map[chainhash.Hash]*orphanBlock + prevOrphans map[chainhash.Hash][]*orphanBlock + oldestOrphan *orphanBlock + + // These fields are related to checkpoint handling. They are protected + // by the chain lock. + nextCheckpoint *chaincfg.Checkpoint + checkpointNode *blockNode + + // The state is used as a fairly efficient way to cache information + // about the current best chain state that is returned to callers when + // requested. It operates on the principle of MVCC such that any time a + // new block becomes the best block, the state pointer is replaced with + // a new struct and the old state is left untouched. In this way, + // multiple callers can be pointing to different best chain states. + // This is acceptable for most callers because the state is only being + // queried at a specific point in time. + // + // In addition, some of the fields are stored in the database so the + // chain state can be quickly reconstructed on load. + stateLock sync.RWMutex + stateSnapshot *BestState + + // The following caches are used to efficiently keep track of the + // current deployment threshold state of each rule change deployment. + // + // This information is stored in the database so it can be quickly + // reconstructed on load. + // + // warningCaches caches the current deployment threshold state for blocks + // in each of the **possible** deployments. This is used in order to + // detect when new unrecognized rule changes are being voted on and/or + // have been activated such as will be the case when older versions of + // the software are being used + // + // deploymentCaches caches the current deployment threshold state for + // blocks in each of the actively defined deployments. + warningCaches []thresholdStateCache + deploymentCaches []thresholdStateCache + + // The following fields are used to determine if certain warnings have + // already been shown. + // + // unknownRulesWarned refers to warnings due to unknown rules being + // activated. + // + // unknownVersionsWarned refers to warnings due to unknown versions + // being mined. + unknownRulesWarned bool + unknownVersionsWarned bool + + // The notifications field stores a slice of callbacks to be executed on + // certain blockchain events. + notificationsLock sync.RWMutex + notifications []NotificationCallback +} + +// HaveBlock returns whether or not the chain instance has the block represented +// by the passed hash. This includes checking the various places a block can +// be like part of the main chain, on a side chain, or in the orphan pool. +// +// This function is safe for concurrent access. +func (b *BlockChain) HaveBlock(hash *chainhash.Hash) (bool, error) { + exists, err := b.blockExists(hash) + if err != nil { + return false, err + } + return exists || b.IsKnownOrphan(hash), nil +} + +// IsKnownOrphan returns whether the passed hash is currently a known orphan. +// Keep in mind that only a limited number of orphans are held onto for a +// limited amount of time, so this function must not be used as an absolute +// way to test if a block is an orphan block. A full block (as opposed to just +// its hash) must be passed to ProcessBlock for that purpose. However, calling +// ProcessBlock with an orphan that already exists results in an error, so this +// function provides a mechanism for a caller to intelligently detect *recent* +// duplicate orphans and react accordingly. +// +// This function is safe for concurrent access. +func (b *BlockChain) IsKnownOrphan(hash *chainhash.Hash) bool { + // Protect concurrent access. Using a read lock only so multiple + // readers can query without blocking each other. + b.orphanLock.RLock() + _, exists := b.orphans[*hash] + b.orphanLock.RUnlock() + + return exists +} + +// GetOrphanRoot returns the head of the chain for the provided hash from the +// map of orphan blocks. +// +// This function is safe for concurrent access. +func (b *BlockChain) GetOrphanRoot(hash *chainhash.Hash) *chainhash.Hash { + // Protect concurrent access. Using a read lock only so multiple + // readers can query without blocking each other. + b.orphanLock.RLock() + defer b.orphanLock.RUnlock() + + // Keep looping while the parent of each orphaned block is + // known and is an orphan itself. + orphanRoot := hash + prevHash := hash + for { + orphan, exists := b.orphans[*prevHash] + if !exists { + break + } + orphanRoot = prevHash + prevHash = &orphan.block.MsgBlock().Header.PrevBlock + } + + return orphanRoot +} + +// removeOrphanBlock removes the passed orphan block from the orphan pool and +// previous orphan index. +func (b *BlockChain) removeOrphanBlock(orphan *orphanBlock) { + // Protect concurrent access. + b.orphanLock.Lock() + defer b.orphanLock.Unlock() + + // Remove the orphan block from the orphan pool. + orphanHash := orphan.block.Hash() + delete(b.orphans, *orphanHash) + + // Remove the reference from the previous orphan index too. An indexing + // for loop is intentionally used over a range here as range does not + // reevaluate the slice on each iteration nor does it adjust the index + // for the modified slice. + prevHash := &orphan.block.MsgBlock().Header.PrevBlock + orphans := b.prevOrphans[*prevHash] + for i := 0; i < len(orphans); i++ { + hash := orphans[i].block.Hash() + if hash.IsEqual(orphanHash) { + copy(orphans[i:], orphans[i+1:]) + orphans[len(orphans)-1] = nil + orphans = orphans[:len(orphans)-1] + i-- + } + } + b.prevOrphans[*prevHash] = orphans + + // Remove the map entry altogether if there are no longer any orphans + // which depend on the parent hash. + if len(b.prevOrphans[*prevHash]) == 0 { + delete(b.prevOrphans, *prevHash) + } +} + +// addOrphanBlock adds the passed block (which is already determined to be +// an orphan prior calling this function) to the orphan pool. It lazily cleans +// up any expired blocks so a separate cleanup poller doesn't need to be run. +// It also imposes a maximum limit on the number of outstanding orphan +// blocks and will remove the oldest received orphan block if the limit is +// exceeded. +func (b *BlockChain) addOrphanBlock(block *btcutil.Block) { + // Remove expired orphan blocks. + for _, oBlock := range b.orphans { + if time.Now().After(oBlock.expiration) { + b.removeOrphanBlock(oBlock) + continue + } + + // Update the oldest orphan block pointer so it can be discarded + // in case the orphan pool fills up. + if b.oldestOrphan == nil || oBlock.expiration.Before(b.oldestOrphan.expiration) { + b.oldestOrphan = oBlock + } + } + + // Limit orphan blocks to prevent memory exhaustion. + if len(b.orphans)+1 > maxOrphanBlocks { + // Remove the oldest orphan to make room for the new one. + b.removeOrphanBlock(b.oldestOrphan) + b.oldestOrphan = nil + } + + // Protect concurrent access. This is intentionally done here instead + // of near the top since removeOrphanBlock does its own locking and + // the range iterator is not invalidated by removing map entries. + b.orphanLock.Lock() + defer b.orphanLock.Unlock() + + // Insert the block into the orphan map with an expiration time + // 1 hour from now. + expiration := time.Now().Add(time.Hour) + oBlock := &orphanBlock{ + block: block, + expiration: expiration, + } + b.orphans[*block.Hash()] = oBlock + + // Add to previous hash lookup index for faster dependency lookups. + prevHash := &block.MsgBlock().Header.PrevBlock + b.prevOrphans[*prevHash] = append(b.prevOrphans[*prevHash], oBlock) +} + +// SequenceLock represents the converted relative lock-time in seconds, and +// absolute block-height for a transaction input's relative lock-times. +// According to SequenceLock, after the referenced input has been confirmed +// within a block, a transaction spending that input can be included into a +// block either after 'seconds' (according to past median time), or once the +// 'BlockHeight' has been reached. +type SequenceLock struct { + Seconds int64 + BlockHeight int32 +} + +// CalcSequenceLock computes a relative lock-time SequenceLock for the passed +// transaction using the passed UtxoViewpoint to obtain the past median time +// for blocks in which the referenced inputs of the transactions were included +// within. The generated SequenceLock lock can be used in conjunction with a +// block height, and adjusted median block time to determine if all the inputs +// referenced within a transaction have reached sufficient maturity allowing +// the candidate transaction to be included in a block. +// +// This function is safe for concurrent access. +func (b *BlockChain) CalcSequenceLock(tx *btcutil.Tx, utxoView *UtxoViewpoint, mempool bool) (*SequenceLock, error) { + b.chainLock.Lock() + defer b.chainLock.Unlock() + + return b.calcSequenceLock(b.bestChain.Tip(), tx, utxoView, mempool) +} + +// calcSequenceLock computes the relative lock-times for the passed +// transaction. See the exported version, CalcSequenceLock for further details. +// +// This function MUST be called with the chain state lock held (for writes). +func (b *BlockChain) calcSequenceLock(node *blockNode, tx *btcutil.Tx, utxoView *UtxoViewpoint, mempool bool) (*SequenceLock, error) { + // A value of -1 for each relative lock type represents a relative time + // lock value that will allow a transaction to be included in a block + // at any given height or time. This value is returned as the relative + // lock time in the case that BIP 68 is disabled, or has not yet been + // activated. + sequenceLock := &SequenceLock{Seconds: -1, BlockHeight: -1} + + // The sequence locks semantics are always active for transactions + // within the mempool. + csvSoftforkActive := mempool + + // If we're performing block validation, then we need to query the BIP9 + // state. + if !csvSoftforkActive { + // Obtain the latest BIP9 version bits state for the + // CSV-package soft-fork deployment. The adherence of sequence + // locks depends on the current soft-fork state. + csvState, err := b.deploymentState(node.parent, chaincfg.DeploymentCSV) + if err != nil { + return nil, err + } + csvSoftforkActive = csvState == ThresholdActive + } + + // If the transaction's version is less than 2, and BIP 68 has not yet + // been activated then sequence locks are disabled. Additionally, + // sequence locks don't apply to coinbase transactions Therefore, we + // return sequence lock values of -1 indicating that this transaction + // can be included within a block at any given height or time. + mTx := tx.MsgTx() + sequenceLockActive := mTx.Version >= 2 && csvSoftforkActive + if !sequenceLockActive || IsCoinBase(tx) { + return sequenceLock, nil + } + + // Grab the next height from the PoV of the passed blockNode to use for + // inputs present in the mempool. + nextHeight := node.height + 1 + + for txInIndex, txIn := range mTx.TxIn { + utxo := utxoView.LookupEntry(txIn.PreviousOutPoint) + if utxo == nil { + str := fmt.Sprintf("output %v referenced from "+ + "transaction %s:%d either does not exist or "+ + "has already been spent", txIn.PreviousOutPoint, + tx.Hash(), txInIndex) + return sequenceLock, ruleError(ErrMissingTxOut, str) + } + + // If the input height is set to the mempool height, then we + // assume the transaction makes it into the next block when + // evaluating its sequence blocks. + inputHeight := utxo.BlockHeight() + if inputHeight == 0x7fffffff { + inputHeight = nextHeight + } + + // Given a sequence number, we apply the relative time lock + // mask in order to obtain the time lock delta required before + // this input can be spent. + sequenceNum := txIn.Sequence + relativeLock := int64(sequenceNum & wire.SequenceLockTimeMask) + + switch { + // Relative time locks are disabled for this input, so we can + // skip any further calculation. + case sequenceNum&wire.SequenceLockTimeDisabled == wire.SequenceLockTimeDisabled: + continue + case sequenceNum&wire.SequenceLockTimeIsSeconds == wire.SequenceLockTimeIsSeconds: + // This input requires a relative time lock expressed + // in seconds before it can be spent. Therefore, we + // need to query for the block prior to the one in + // which this input was included within so we can + // compute the past median time for the block prior to + // the one which included this referenced output. + prevInputHeight := inputHeight - 1 + if prevInputHeight < 0 { + prevInputHeight = 0 + } + blockNode := node.Ancestor(prevInputHeight) + medianTime := blockNode.CalcPastMedianTime() + + // Time based relative time-locks as defined by BIP 68 + // have a time granularity of RelativeLockSeconds, so + // we shift left by this amount to convert to the + // proper relative time-lock. We also subtract one from + // the relative lock to maintain the original lockTime + // semantics. + timeLockSeconds := (relativeLock << wire.SequenceLockTimeGranularity) - 1 + timeLock := medianTime.Unix() + timeLockSeconds + if timeLock > sequenceLock.Seconds { + sequenceLock.Seconds = timeLock + } + default: + // The relative lock-time for this input is expressed + // in blocks so we calculate the relative offset from + // the input's height as its converted absolute + // lock-time. We subtract one from the relative lock in + // order to maintain the original lockTime semantics. + blockHeight := inputHeight + int32(relativeLock-1) + if blockHeight > sequenceLock.BlockHeight { + sequenceLock.BlockHeight = blockHeight + } + } + } + + return sequenceLock, nil +} + +// LockTimeToSequence converts the passed relative locktime to a sequence +// number in accordance to BIP-68. +// See: https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki +// * (Compatibility) +func LockTimeToSequence(isSeconds bool, locktime uint32) uint32 { + // If we're expressing the relative lock time in blocks, then the + // corresponding sequence number is simply the desired input age. + if !isSeconds { + return locktime + } + + // Set the 22nd bit which indicates the lock time is in seconds, then + // shift the locktime over by 9 since the time granularity is in + // 512-second intervals (2^9). This results in a max lock-time of + // 33,553,920 seconds, or 1.1 years. + return wire.SequenceLockTimeIsSeconds | + locktime>>wire.SequenceLockTimeGranularity +} + +// getReorganizeNodes finds the fork point between the main chain and the passed +// node and returns a list of block nodes that would need to be detached from +// the main chain and a list of block nodes that would need to be attached to +// the fork point (which will be the end of the main chain after detaching the +// returned list of block nodes) in order to reorganize the chain such that the +// passed node is the new end of the main chain. The lists will be empty if the +// passed node is not on a side chain. +// +// This function may modify node statuses in the block index without flushing. +// +// This function MUST be called with the chain state lock held (for reads). +func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List) { + attachNodes := list.New() + detachNodes := list.New() + + // Do not reorganize to a known invalid chain. Ancestors deeper than the + // direct parent are checked below but this is a quick check before doing + // more unnecessary work. + if b.index.NodeStatus(node.parent).KnownInvalid() { + b.index.SetStatusFlags(node, statusInvalidAncestor) + return detachNodes, attachNodes + } + + // Find the fork point (if any) adding each block to the list of nodes + // to attach to the main tree. Push them onto the list in reverse order + // so they are attached in the appropriate order when iterating the list + // later. + forkNode := b.bestChain.FindFork(node) + invalidChain := false + for n := node; n != nil && n != forkNode; n = n.parent { + if b.index.NodeStatus(n).KnownInvalid() { + invalidChain = true + break + } + attachNodes.PushFront(n) + } + + // If any of the node's ancestors are invalid, unwind attachNodes, marking + // each one as invalid for future reference. + if invalidChain { + var next *list.Element + for e := attachNodes.Front(); e != nil; e = next { + next = e.Next() + n := attachNodes.Remove(e).(*blockNode) + b.index.SetStatusFlags(n, statusInvalidAncestor) + } + return detachNodes, attachNodes + } + + // Start from the end of the main chain and work backwards until the + // common ancestor adding each block to the list of nodes to detach from + // the main chain. + for n := b.bestChain.Tip(); n != nil && n != forkNode; n = n.parent { + detachNodes.PushBack(n) + } + + return detachNodes, attachNodes +} + +// connectBlock handles connecting the passed node/block to the end of the main +// (best) chain. +// +// This passed utxo view must have all referenced txos the block spends marked +// as spent and all of the new txos the block creates added to it. In addition, +// the passed stxos slice must be populated with all of the information for the +// spent txos. This approach is used because the connection validation that +// must happen prior to calling this function requires the same details, so +// it would be inefficient to repeat it. +// +// This function MUST be called with the chain state lock held (for writes). +func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, + view *UtxoViewpoint, stxos []SpentTxOut) error { + + // Make sure it's extending the end of the best chain. + prevHash := &block.MsgBlock().Header.PrevBlock + if !prevHash.IsEqual(&b.bestChain.Tip().hash) { + return AssertError("connectBlock must be called with a block " + + "that extends the main chain") + } + + // Sanity check the correct number of stxos are provided. + if len(stxos) != countSpentOutputs(block) { + return AssertError("connectBlock called with inconsistent " + + "spent transaction out information") + } + + // No warnings about unknown rules or versions until the chain is + // current. + if b.isCurrent() { + // Warn if any unknown new rules are either about to activate or + // have already been activated. + if err := b.warnUnknownRuleActivations(node); err != nil { + return err + } + + // Warn if a high enough percentage of the last blocks have + // unexpected versions. + if err := b.warnUnknownVersions(node); err != nil { + return err + } + } + + // Write any block status changes to DB before updating best state. + err := b.index.flushToDB() + if err != nil { + return err + } + + // Generate a new best state snapshot that will be used to update the + // database and later memory if all database updates are successful. + b.stateLock.RLock() + curTotalTxns := b.stateSnapshot.TotalTxns + b.stateLock.RUnlock() + numTxns := uint64(len(block.MsgBlock().Transactions)) + blockSize := uint64(block.MsgBlock().SerializeSize()) + blockWeight := uint64(GetBlockWeight(block)) + state := newBestState(node, blockSize, blockWeight, numTxns, + curTotalTxns+numTxns, node.CalcPastMedianTime()) + + // Atomically insert info into the database. + err = b.db.Update(func(dbTx database.Tx) error { + // Update best block state. + err := dbPutBestState(dbTx, state, node.workSum) + if err != nil { + return err + } + + // Add the block hash and height to the block index which tracks + // the main chain. + err = dbPutBlockIndex(dbTx, block.Hash(), node.height) + if err != nil { + return err + } + + // Update the utxo set using the state of the utxo view. This + // entails removing all of the utxos spent and adding the new + // ones created by the block. + err = dbPutUtxoView(dbTx, view) + if err != nil { + return err + } + + // Update the transaction spend journal by adding a record for + // the block that contains all txos spent by it. + err = dbPutSpendJournalEntry(dbTx, block.Hash(), stxos) + if err != nil { + return err + } + + // Allow the index manager to call each of the currently active + // optional indexes with the block being connected so they can + // update themselves accordingly. + if b.indexManager != nil { + err := b.indexManager.ConnectBlock(dbTx, block, stxos) + if err != nil { + return err + } + } + + return nil + }) + if err != nil { + return err + } + + // Prune fully spent entries and mark all entries in the view unmodified + // now that the modifications have been committed to the database. + view.commit() + + // This node is now the end of the best chain. + b.bestChain.SetTip(node) + + // Update the state for the best block. Notice how this replaces the + // entire struct instead of updating the existing one. This effectively + // allows the old version to act as a snapshot which callers can use + // freely without needing to hold a lock for the duration. See the + // comments on the state variable for more details. + b.stateLock.Lock() + b.stateSnapshot = state + b.stateLock.Unlock() + + // Notify the caller that the block was connected to the main chain. + // The caller would typically want to react with actions such as + // updating wallets. + b.chainLock.Unlock() + b.sendNotification(NTBlockConnected, block) + b.chainLock.Lock() + + return nil +} + +// disconnectBlock handles disconnecting the passed node/block from the end of +// the main (best) chain. +// +// This function MUST be called with the chain state lock held (for writes). +func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint) error { + // Make sure the node being disconnected is the end of the best chain. + if !node.hash.IsEqual(&b.bestChain.Tip().hash) { + return AssertError("disconnectBlock must be called with the " + + "block at the end of the main chain") + } + + // Load the previous block since some details for it are needed below. + prevNode := node.parent + var prevBlock *btcutil.Block + err := b.db.View(func(dbTx database.Tx) error { + var err error + prevBlock, err = dbFetchBlockByNode(dbTx, prevNode) + return err + }) + if err != nil { + return err + } + + // Write any block status changes to DB before updating best state. + err = b.index.flushToDB() + if err != nil { + return err + } + + // Generate a new best state snapshot that will be used to update the + // database and later memory if all database updates are successful. + b.stateLock.RLock() + curTotalTxns := b.stateSnapshot.TotalTxns + b.stateLock.RUnlock() + numTxns := uint64(len(prevBlock.MsgBlock().Transactions)) + blockSize := uint64(prevBlock.MsgBlock().SerializeSize()) + blockWeight := uint64(GetBlockWeight(prevBlock)) + newTotalTxns := curTotalTxns - uint64(len(block.MsgBlock().Transactions)) + state := newBestState(prevNode, blockSize, blockWeight, numTxns, + newTotalTxns, prevNode.CalcPastMedianTime()) + + err = b.db.Update(func(dbTx database.Tx) error { + // Update best block state. + err := dbPutBestState(dbTx, state, node.workSum) + if err != nil { + return err + } + + // Remove the block hash and height from the block index which + // tracks the main chain. + err = dbRemoveBlockIndex(dbTx, block.Hash(), node.height) + if err != nil { + return err + } + + // Update the utxo set using the state of the utxo view. This + // entails restoring all of the utxos spent and removing the new + // ones created by the block. + err = dbPutUtxoView(dbTx, view) + if err != nil { + return err + } + + // Before we delete the spend journal entry for this back, + // we'll fetch it as is so the indexers can utilize if needed. + stxos, err := dbFetchSpendJournalEntry(dbTx, block) + if err != nil { + return err + } + + // Update the transaction spend journal by removing the record + // that contains all txos spent by the block. + err = dbRemoveSpendJournalEntry(dbTx, block.Hash()) + if err != nil { + return err + } + + // Allow the index manager to call each of the currently active + // optional indexes with the block being disconnected so they + // can update themselves accordingly. + if b.indexManager != nil { + err := b.indexManager.DisconnectBlock(dbTx, block, stxos) + if err != nil { + return err + } + } + + return nil + }) + if err != nil { + return err + } + + // Prune fully spent entries and mark all entries in the view unmodified + // now that the modifications have been committed to the database. + view.commit() + + // This node's parent is now the end of the best chain. + b.bestChain.SetTip(node.parent) + + // Update the state for the best block. Notice how this replaces the + // entire struct instead of updating the existing one. This effectively + // allows the old version to act as a snapshot which callers can use + // freely without needing to hold a lock for the duration. See the + // comments on the state variable for more details. + b.stateLock.Lock() + b.stateSnapshot = state + b.stateLock.Unlock() + + // Notify the caller that the block was disconnected from the main + // chain. The caller would typically want to react with actions such as + // updating wallets. + b.chainLock.Unlock() + b.sendNotification(NTBlockDisconnected, block) + b.chainLock.Lock() + + return nil +} + +// countSpentOutputs returns the number of utxos the passed block spends. +func countSpentOutputs(block *btcutil.Block) int { + // Exclude the coinbase transaction since it can't spend anything. + var numSpent int + for _, tx := range block.Transactions()[1:] { + numSpent += len(tx.MsgTx().TxIn) + } + return numSpent +} + +// reorganizeChain reorganizes the block chain by disconnecting the nodes in the +// detachNodes list and connecting the nodes in the attach list. It expects +// that the lists are already in the correct order and are in sync with the +// end of the current best chain. Specifically, nodes that are being +// disconnected must be in reverse order (think of popping them off the end of +// the chain) and nodes the are being attached must be in forwards order +// (think pushing them onto the end of the chain). +// +// This function may modify node statuses in the block index without flushing. +// +// This function MUST be called with the chain state lock held (for writes). +func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error { + // Nothing to do if no reorganize nodes were provided. + if detachNodes.Len() == 0 && attachNodes.Len() == 0 { + return nil + } + + // Ensure the provided nodes match the current best chain. + tip := b.bestChain.Tip() + if detachNodes.Len() != 0 { + firstDetachNode := detachNodes.Front().Value.(*blockNode) + if firstDetachNode.hash != tip.hash { + return AssertError(fmt.Sprintf("reorganize nodes to detach are "+ + "not for the current best chain -- first detach node %v, "+ + "current chain %v", &firstDetachNode.hash, &tip.hash)) + } + } + + // Ensure the provided nodes are for the same fork point. + if attachNodes.Len() != 0 && detachNodes.Len() != 0 { + firstAttachNode := attachNodes.Front().Value.(*blockNode) + lastDetachNode := detachNodes.Back().Value.(*blockNode) + if firstAttachNode.parent.hash != lastDetachNode.parent.hash { + return AssertError(fmt.Sprintf("reorganize nodes do not have the "+ + "same fork point -- first attach parent %v, last detach "+ + "parent %v", &firstAttachNode.parent.hash, + &lastDetachNode.parent.hash)) + } + } + + // Track the old and new best chains heads. + oldBest := tip + newBest := tip + + // All of the blocks to detach and related spend journal entries needed + // to unspend transaction outputs in the blocks being disconnected must + // be loaded from the database during the reorg check phase below and + // then they are needed again when doing the actual database updates. + // Rather than doing two loads, cache the loaded data into these slices. + detachBlocks := make([]*btcutil.Block, 0, detachNodes.Len()) + detachSpentTxOuts := make([][]SpentTxOut, 0, detachNodes.Len()) + attachBlocks := make([]*btcutil.Block, 0, attachNodes.Len()) + + // Disconnect all of the blocks back to the point of the fork. This + // entails loading the blocks and their associated spent txos from the + // database and using that information to unspend all of the spent txos + // and remove the utxos created by the blocks. + view := NewUtxoViewpoint() + view.SetBestHash(&oldBest.hash) + for e := detachNodes.Front(); e != nil; e = e.Next() { + n := e.Value.(*blockNode) + var block *btcutil.Block + err := b.db.View(func(dbTx database.Tx) error { + var err error + block, err = dbFetchBlockByNode(dbTx, n) + return err + }) + if err != nil { + return err + } + if n.hash != *block.Hash() { + return AssertError(fmt.Sprintf("detach block node hash %v (height "+ + "%v) does not match previous parent block hash %v", &n.hash, + n.height, block.Hash())) + } + + // Load all of the utxos referenced by the block that aren't + // already in the view. + err = view.fetchInputUtxos(b.db, block) + if err != nil { + return err + } + + // Load all of the spent txos for the block from the spend + // journal. + var stxos []SpentTxOut + err = b.db.View(func(dbTx database.Tx) error { + stxos, err = dbFetchSpendJournalEntry(dbTx, block) + return err + }) + if err != nil { + return err + } + + // Store the loaded block and spend journal entry for later. + detachBlocks = append(detachBlocks, block) + detachSpentTxOuts = append(detachSpentTxOuts, stxos) + + err = view.disconnectTransactions(b.db, block, stxos) + if err != nil { + return err + } + + newBest = n.parent + } + + // Set the fork point only if there are nodes to attach since otherwise + // blocks are only being disconnected and thus there is no fork point. + var forkNode *blockNode + if attachNodes.Len() > 0 { + forkNode = newBest + } + + // Perform several checks to verify each block that needs to be attached + // to the main chain can be connected without violating any rules and + // without actually connecting the block. + // + // NOTE: These checks could be done directly when connecting a block, + // however the downside to that approach is that if any of these checks + // fail after disconnecting some blocks or attaching others, all of the + // operations have to be rolled back to get the chain back into the + // state it was before the rule violation (or other failure). There are + // at least a couple of ways accomplish that rollback, but both involve + // tweaking the chain and/or database. This approach catches these + // issues before ever modifying the chain. + for e := attachNodes.Front(); e != nil; e = e.Next() { + n := e.Value.(*blockNode) + + var block *btcutil.Block + err := b.db.View(func(dbTx database.Tx) error { + var err error + block, err = dbFetchBlockByNode(dbTx, n) + return err + }) + if err != nil { + return err + } + + // Store the loaded block for later. + attachBlocks = append(attachBlocks, block) + + // Skip checks if node has already been fully validated. Although + // checkConnectBlock gets skipped, we still need to update the UTXO + // view. + if b.index.NodeStatus(n).KnownValid() { + err = view.fetchInputUtxos(b.db, block) + if err != nil { + return err + } + err = view.connectTransactions(block, nil) + if err != nil { + return err + } + + newBest = n + continue + } + + // Notice the spent txout details are not requested here and + // thus will not be generated. This is done because the state + // is not being immediately written to the database, so it is + // not needed. + // + // In the case the block is determined to be invalid due to a + // rule violation, mark it as invalid and mark all of its + // descendants as having an invalid ancestor. + err = b.checkConnectBlock(n, block, view, nil) + if err != nil { + if _, ok := err.(RuleError); ok { + b.index.SetStatusFlags(n, statusValidateFailed) + for de := e.Next(); de != nil; de = de.Next() { + dn := de.Value.(*blockNode) + b.index.SetStatusFlags(dn, statusInvalidAncestor) + } + } + return err + } + b.index.SetStatusFlags(n, statusValid) + + newBest = n + } + + // Reset the view for the actual connection code below. This is + // required because the view was previously modified when checking if + // the reorg would be successful and the connection code requires the + // view to be valid from the viewpoint of each block being connected or + // disconnected. + view = NewUtxoViewpoint() + view.SetBestHash(&b.bestChain.Tip().hash) + + // Disconnect blocks from the main chain. + for i, e := 0, detachNodes.Front(); e != nil; i, e = i+1, e.Next() { + n := e.Value.(*blockNode) + block := detachBlocks[i] + + // Load all of the utxos referenced by the block that aren't + // already in the view. + err := view.fetchInputUtxos(b.db, block) + if err != nil { + return err + } + + // Update the view to unspend all of the spent txos and remove + // the utxos created by the block. + err = view.disconnectTransactions(b.db, block, + detachSpentTxOuts[i]) + if err != nil { + return err + } + + // Update the database and chain state. + err = b.disconnectBlock(n, block, view) + if err != nil { + return err + } + } + + // Connect the new best chain blocks. + for i, e := 0, attachNodes.Front(); e != nil; i, e = i+1, e.Next() { + n := e.Value.(*blockNode) + block := attachBlocks[i] + + // Load all of the utxos referenced by the block that aren't + // already in the view. + err := view.fetchInputUtxos(b.db, block) + if err != nil { + return err + } + + // Update the view to mark all utxos referenced by the block + // as spent and add all transactions being created by this block + // to it. Also, provide an stxo slice so the spent txout + // details are generated. + stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) + err = view.connectTransactions(block, &stxos) + if err != nil { + return err + } + + // Update the database and chain state. + err = b.connectBlock(n, block, view, stxos) + if err != nil { + return err + } + } + + // Log the point where the chain forked and old and new best chain + // heads. + if forkNode != nil { + log.Infof("REORGANIZE: Chain forks at %v (height %v)", forkNode.hash, + forkNode.height) + } + log.Infof("REORGANIZE: Old best chain head was %v (height %v)", + &oldBest.hash, oldBest.height) + log.Infof("REORGANIZE: New best chain head is %v (height %v)", + newBest.hash, newBest.height) + + return nil +} + +// connectBestChain handles connecting the passed block to the chain while +// respecting proper chain selection according to the chain with the most +// proof of work. In the typical case, the new block simply extends the main +// chain. However, it may also be extending (or creating) a side chain (fork) +// which may or may not end up becoming the main chain depending on which fork +// cumulatively has the most proof of work. It returns whether or not the block +// ended up on the main chain (either due to extending the main chain or causing +// a reorganization to become the main chain). +// +// The flags modify the behavior of this function as follows: +// - BFFastAdd: Avoids several expensive transaction validation operations. +// This is useful when using checkpoints. +// +// This function MUST be called with the chain state lock held (for writes). +func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, flags BehaviorFlags) (bool, error) { + fastAdd := flags&BFFastAdd == BFFastAdd + + flushIndexState := func() { + // Intentionally ignore errors writing updated node status to DB. If + // it fails to write, it's not the end of the world. If the block is + // valid, we flush in connectBlock and if the block is invalid, the + // worst that can happen is we revalidate the block after a restart. + if writeErr := b.index.flushToDB(); writeErr != nil { + log.Warnf("Error flushing block index changes to disk: %v", + writeErr) + } + } + + // We are extending the main (best) chain with a new block. This is the + // most common case. + parentHash := &block.MsgBlock().Header.PrevBlock + if parentHash.IsEqual(&b.bestChain.Tip().hash) { + // Skip checks if node has already been fully validated. + fastAdd = fastAdd || b.index.NodeStatus(node).KnownValid() + + // Perform several checks to verify the block can be connected + // to the main chain without violating any rules and without + // actually connecting the block. + view := NewUtxoViewpoint() + view.SetBestHash(parentHash) + stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) + if !fastAdd { + err := b.checkConnectBlock(node, block, view, &stxos) + if err == nil { + b.index.SetStatusFlags(node, statusValid) + } else if _, ok := err.(RuleError); ok { + b.index.SetStatusFlags(node, statusValidateFailed) + } else { + return false, err + } + + flushIndexState() + + if err != nil { + return false, err + } + } + + // In the fast add case the code to check the block connection + // was skipped, so the utxo view needs to load the referenced + // utxos, spend them, and add the new utxos being created by + // this block. + if fastAdd { + err := view.fetchInputUtxos(b.db, block) + if err != nil { + return false, err + } + err = view.connectTransactions(block, &stxos) + if err != nil { + return false, err + } + } + + // Connect the block to the main chain. + err := b.connectBlock(node, block, view, stxos) + if err != nil { + // If we got hit with a rule error, then we'll mark + // that status of the block as invalid and flush the + // index state to disk before returning with the error. + if _, ok := err.(RuleError); ok { + b.index.SetStatusFlags( + node, statusValidateFailed, + ) + } + + flushIndexState() + + return false, err + } + + // If this is fast add, or this block node isn't yet marked as + // valid, then we'll update its status and flush the state to + // disk again. + if fastAdd || !b.index.NodeStatus(node).KnownValid() { + b.index.SetStatusFlags(node, statusValid) + flushIndexState() + } + + return true, nil + } + if fastAdd { + log.Warnf("fastAdd set in the side chain case? %v\n", + block.Hash()) + } + + // We're extending (or creating) a side chain, but the cumulative + // work for this new side chain is not enough to make it the new chain. + if node.workSum.Cmp(b.bestChain.Tip().workSum) <= 0 { + // Log information about how the block is forking the chain. + fork := b.bestChain.FindFork(node) + if fork.hash.IsEqual(parentHash) { + log.Infof("FORK: Block %v forks the chain at height %d"+ + "/block %v, but does not cause a reorganize", + node.hash, fork.height, fork.hash) + } else { + log.Infof("EXTEND FORK: Block %v extends a side chain "+ + "which forks the chain at height %d/block %v", + node.hash, fork.height, fork.hash) + } + + return false, nil + } + + // We're extending (or creating) a side chain and the cumulative work + // for this new side chain is more than the old best chain, so this side + // chain needs to become the main chain. In order to accomplish that, + // find the common ancestor of both sides of the fork, disconnect the + // blocks that form the (now) old fork from the main chain, and attach + // the blocks that form the new chain to the main chain starting at the + // common ancenstor (the point where the chain forked). + detachNodes, attachNodes := b.getReorganizeNodes(node) + + // Reorganize the chain. + log.Infof("REORGANIZE: Block %v is causing a reorganize.", node.hash) + err := b.reorganizeChain(detachNodes, attachNodes) + + // Either getReorganizeNodes or reorganizeChain could have made unsaved + // changes to the block index, so flush regardless of whether there was an + // error. The index would only be dirty if the block failed to connect, so + // we can ignore any errors writing. + if writeErr := b.index.flushToDB(); writeErr != nil { + log.Warnf("Error flushing block index changes to disk: %v", writeErr) + } + + return err == nil, err +} + +// isCurrent returns whether or not the chain believes it is current. Several +// factors are used to guess, but the key factors that allow the chain to +// believe it is current are: +// - Latest block height is after the latest checkpoint (if enabled) +// - Latest block has a timestamp newer than 24 hours ago +// +// This function MUST be called with the chain state lock held (for reads). +func (b *BlockChain) isCurrent() bool { + // Not current if the latest main (best) chain height is before the + // latest known good checkpoint (when checkpoints are enabled). + checkpoint := b.LatestCheckpoint() + if checkpoint != nil && b.bestChain.Tip().height < checkpoint.Height { + return false + } + + // Not current if the latest best block has a timestamp before 24 hours + // ago. + // + // The chain appears to be current if none of the checks reported + // otherwise. + minus24Hours := b.timeSource.AdjustedTime().Add(-24 * time.Hour).Unix() + return b.bestChain.Tip().timestamp >= minus24Hours +} + +// IsCurrent returns whether or not the chain believes it is current. Several +// factors are used to guess, but the key factors that allow the chain to +// believe it is current are: +// - Latest block height is after the latest checkpoint (if enabled) +// - Latest block has a timestamp newer than 24 hours ago +// +// This function is safe for concurrent access. +func (b *BlockChain) IsCurrent() bool { + b.chainLock.RLock() + defer b.chainLock.RUnlock() + + return b.isCurrent() +} + +// BestSnapshot returns information about the current best chain block and +// related state as of the current point in time. The returned instance must be +// treated as immutable since it is shared by all callers. +// +// This function is safe for concurrent access. +func (b *BlockChain) BestSnapshot() *BestState { + b.stateLock.RLock() + snapshot := b.stateSnapshot + b.stateLock.RUnlock() + return snapshot +} + +// HeaderByHash returns the block header identified by the given hash or an +// error if it doesn't exist. Note that this will return headers from both the +// main and side chains. +func (b *BlockChain) HeaderByHash(hash *chainhash.Hash) (wire.BlockHeader, error) { + node := b.index.LookupNode(hash) + if node == nil { + err := fmt.Errorf("block %s is not known", hash) + return wire.BlockHeader{}, err + } + + return node.Header(), nil +} + +// MainChainHasBlock returns whether or not the block with the given hash is in +// the main chain. +// +// This function is safe for concurrent access. +func (b *BlockChain) MainChainHasBlock(hash *chainhash.Hash) bool { + node := b.index.LookupNode(hash) + return node != nil && b.bestChain.Contains(node) +} + +// BlockLocatorFromHash returns a block locator for the passed block hash. +// See BlockLocator for details on the algorithm used to create a block locator. +// +// In addition to the general algorithm referenced above, this function will +// return the block locator for the latest known tip of the main (best) chain if +// the passed hash is not currently known. +// +// This function is safe for concurrent access. +func (b *BlockChain) BlockLocatorFromHash(hash *chainhash.Hash) BlockLocator { + b.chainLock.RLock() + node := b.index.LookupNode(hash) + locator := b.bestChain.blockLocator(node) + b.chainLock.RUnlock() + return locator +} + +// LatestBlockLocator returns a block locator for the latest known tip of the +// main (best) chain. +// +// This function is safe for concurrent access. +func (b *BlockChain) LatestBlockLocator() (BlockLocator, error) { + b.chainLock.RLock() + locator := b.bestChain.BlockLocator(nil) + b.chainLock.RUnlock() + return locator, nil +} + +// BlockHeightByHash returns the height of the block with the given hash in the +// main chain. +// +// This function is safe for concurrent access. +func (b *BlockChain) BlockHeightByHash(hash *chainhash.Hash) (int32, error) { + node := b.index.LookupNode(hash) + if node == nil || !b.bestChain.Contains(node) { + str := fmt.Sprintf("block %s is not in the main chain", hash) + return 0, errNotInMainChain(str) + } + + return node.height, nil +} + +// BlockHashByHeight returns the hash of the block at the given height in the +// main chain. +// +// This function is safe for concurrent access. +func (b *BlockChain) BlockHashByHeight(blockHeight int32) (*chainhash.Hash, error) { + node := b.bestChain.NodeByHeight(blockHeight) + if node == nil { + str := fmt.Sprintf("no block at height %d exists", blockHeight) + return nil, errNotInMainChain(str) + + } + + return &node.hash, nil +} + +// HeightRange returns a range of block hashes for the given start and end +// heights. It is inclusive of the start height and exclusive of the end +// height. The end height will be limited to the current main chain height. +// +// This function is safe for concurrent access. +func (b *BlockChain) HeightRange(startHeight, endHeight int32) ([]chainhash.Hash, error) { + // Ensure requested heights are sane. + if startHeight < 0 { + return nil, fmt.Errorf("start height of fetch range must not "+ + "be less than zero - got %d", startHeight) + } + if endHeight < startHeight { + return nil, fmt.Errorf("end height of fetch range must not "+ + "be less than the start height - got start %d, end %d", + startHeight, endHeight) + } + + // There is nothing to do when the start and end heights are the same, + // so return now to avoid the chain view lock. + if startHeight == endHeight { + return nil, nil + } + + // Grab a lock on the chain view to prevent it from changing due to a + // reorg while building the hashes. + b.bestChain.mtx.Lock() + defer b.bestChain.mtx.Unlock() + + // When the requested start height is after the most recent best chain + // height, there is nothing to do. + latestHeight := b.bestChain.tip().height + if startHeight > latestHeight { + return nil, nil + } + + // Limit the ending height to the latest height of the chain. + if endHeight > latestHeight+1 { + endHeight = latestHeight + 1 + } + + // Fetch as many as are available within the specified range. + hashes := make([]chainhash.Hash, 0, endHeight-startHeight) + for i := startHeight; i < endHeight; i++ { + hashes = append(hashes, b.bestChain.nodeByHeight(i).hash) + } + return hashes, nil +} + +// HeightToHashRange returns a range of block hashes for the given start height +// and end hash, inclusive on both ends. The hashes are for all blocks that are +// ancestors of endHash with height greater than or equal to startHeight. The +// end hash must belong to a block that is known to be valid. +// +// This function is safe for concurrent access. +func (b *BlockChain) HeightToHashRange(startHeight int32, + endHash *chainhash.Hash, maxResults int) ([]chainhash.Hash, error) { + + endNode := b.index.LookupNode(endHash) + if endNode == nil { + return nil, fmt.Errorf("no known block header with hash %v", endHash) + } + if !b.index.NodeStatus(endNode).KnownValid() { + return nil, fmt.Errorf("block %v is not yet validated", endHash) + } + endHeight := endNode.height + + if startHeight < 0 { + return nil, fmt.Errorf("start height (%d) is below 0", startHeight) + } + if startHeight > endHeight { + return nil, fmt.Errorf("start height (%d) is past end height (%d)", + startHeight, endHeight) + } + + resultsLength := int(endHeight - startHeight + 1) + if resultsLength > maxResults { + return nil, fmt.Errorf("number of results (%d) would exceed max (%d)", + resultsLength, maxResults) + } + + // Walk backwards from endHeight to startHeight, collecting block hashes. + node := endNode + hashes := make([]chainhash.Hash, resultsLength) + for i := resultsLength - 1; i >= 0; i-- { + hashes[i] = node.hash + node = node.parent + } + return hashes, nil +} + +// IntervalBlockHashes returns hashes for all blocks that are ancestors of +// endHash where the block height is a positive multiple of interval. +// +// This function is safe for concurrent access. +func (b *BlockChain) IntervalBlockHashes(endHash *chainhash.Hash, interval int, +) ([]chainhash.Hash, error) { + + endNode := b.index.LookupNode(endHash) + if endNode == nil { + return nil, fmt.Errorf("no known block header with hash %v", endHash) + } + if !b.index.NodeStatus(endNode).KnownValid() { + return nil, fmt.Errorf("block %v is not yet validated", endHash) + } + endHeight := endNode.height + + resultsLength := int(endHeight) / interval + hashes := make([]chainhash.Hash, resultsLength) + + b.bestChain.mtx.Lock() + defer b.bestChain.mtx.Unlock() + + blockNode := endNode + for index := int(endHeight) / interval; index > 0; index-- { + // Use the bestChain chainView for faster lookups once lookup intersects + // the best chain. + blockHeight := int32(index * interval) + if b.bestChain.contains(blockNode) { + blockNode = b.bestChain.nodeByHeight(blockHeight) + } else { + blockNode = blockNode.Ancestor(blockHeight) + } + + hashes[index-1] = blockNode.hash + } + + return hashes, nil +} + +// locateInventory returns the node of the block after the first known block in +// the locator along with the number of subsequent nodes needed to either reach +// the provided stop hash or the provided max number of entries. +// +// In addition, there are two special cases: +// +// - When no locators are provided, the stop hash is treated as a request for +// that block, so it will either return the node associated with the stop hash +// if it is known, or nil if it is unknown +// - When locators are provided, but none of them are known, nodes starting +// after the genesis block will be returned +// +// This is primarily a helper function for the locateBlocks and locateHeaders +// functions. +// +// This function MUST be called with the chain state lock held (for reads). +func (b *BlockChain) locateInventory(locator BlockLocator, hashStop *chainhash.Hash, maxEntries uint32) (*blockNode, uint32) { + // There are no block locators so a specific block is being requested + // as identified by the stop hash. + stopNode := b.index.LookupNode(hashStop) + if len(locator) == 0 { + if stopNode == nil { + // No blocks with the stop hash were found so there is + // nothing to do. + return nil, 0 + } + return stopNode, 1 + } + + // Find the most recent locator block hash in the main chain. In the + // case none of the hashes in the locator are in the main chain, fall + // back to the genesis block. + startNode := b.bestChain.Genesis() + for _, hash := range locator { + node := b.index.LookupNode(hash) + if node != nil && b.bestChain.Contains(node) { + startNode = node + break + } + } + + // Start at the block after the most recently known block. When there + // is no next block it means the most recently known block is the tip of + // the best chain, so there is nothing more to do. + startNode = b.bestChain.Next(startNode) + if startNode == nil { + return nil, 0 + } + + // Calculate how many entries are needed. + total := uint32((b.bestChain.Tip().height - startNode.height) + 1) + if stopNode != nil && b.bestChain.Contains(stopNode) && + stopNode.height >= startNode.height { + + total = uint32((stopNode.height - startNode.height) + 1) + } + if total > maxEntries { + total = maxEntries + } + + return startNode, total +} + +// locateBlocks returns the hashes of the blocks after the first known block in +// the locator until the provided stop hash is reached, or up to the provided +// max number of block hashes. +// +// See the comment on the exported function for more details on special cases. +// +// This function MUST be called with the chain state lock held (for reads). +func (b *BlockChain) locateBlocks(locator BlockLocator, hashStop *chainhash.Hash, maxHashes uint32) []chainhash.Hash { + // Find the node after the first known block in the locator and the + // total number of nodes after it needed while respecting the stop hash + // and max entries. + node, total := b.locateInventory(locator, hashStop, maxHashes) + if total == 0 { + return nil + } + + // Populate and return the found hashes. + hashes := make([]chainhash.Hash, 0, total) + for i := uint32(0); i < total; i++ { + hashes = append(hashes, node.hash) + node = b.bestChain.Next(node) + } + return hashes +} + +// LocateBlocks returns the hashes of the blocks after the first known block in +// the locator until the provided stop hash is reached, or up to the provided +// max number of block hashes. +// +// In addition, there are two special cases: +// +// - When no locators are provided, the stop hash is treated as a request for +// that block, so it will either return the stop hash itself if it is known, +// or nil if it is unknown +// - When locators are provided, but none of them are known, hashes starting +// after the genesis block will be returned +// +// This function is safe for concurrent access. +func (b *BlockChain) LocateBlocks(locator BlockLocator, hashStop *chainhash.Hash, maxHashes uint32) []chainhash.Hash { + b.chainLock.RLock() + hashes := b.locateBlocks(locator, hashStop, maxHashes) + b.chainLock.RUnlock() + return hashes +} + +// locateHeaders returns the headers of the blocks after the first known block +// in the locator until the provided stop hash is reached, or up to the provided +// max number of block headers. +// +// See the comment on the exported function for more details on special cases. +// +// This function MUST be called with the chain state lock held (for reads). +func (b *BlockChain) locateHeaders(locator BlockLocator, hashStop *chainhash.Hash, maxHeaders uint32) []wire.BlockHeader { + // Find the node after the first known block in the locator and the + // total number of nodes after it needed while respecting the stop hash + // and max entries. + node, total := b.locateInventory(locator, hashStop, maxHeaders) + if total == 0 { + return nil + } + + // Populate and return the found headers. + headers := make([]wire.BlockHeader, 0, total) + for i := uint32(0); i < total; i++ { + headers = append(headers, node.Header()) + node = b.bestChain.Next(node) + } + return headers +} + +// LocateHeaders returns the headers of the blocks after the first known block +// in the locator until the provided stop hash is reached, or up to a max of +// wire.MaxBlockHeadersPerMsg headers. +// +// In addition, there are two special cases: +// +// - When no locators are provided, the stop hash is treated as a request for +// that header, so it will either return the header for the stop hash itself +// if it is known, or nil if it is unknown +// - When locators are provided, but none of them are known, headers starting +// after the genesis block will be returned +// +// This function is safe for concurrent access. +func (b *BlockChain) LocateHeaders(locator BlockLocator, hashStop *chainhash.Hash) []wire.BlockHeader { + b.chainLock.RLock() + headers := b.locateHeaders(locator, hashStop, wire.MaxBlockHeadersPerMsg) + b.chainLock.RUnlock() + return headers +} + +// IndexManager provides a generic interface that the is called when blocks are +// connected and disconnected to and from the tip of the main chain for the +// purpose of supporting optional indexes. +type IndexManager interface { + // Init is invoked during chain initialize in order to allow the index + // manager to initialize itself and any indexes it is managing. The + // channel parameter specifies a channel the caller can close to signal + // that the process should be interrupted. It can be nil if that + // behavior is not desired. + Init(*BlockChain, <-chan struct{}) error + + // ConnectBlock is invoked when a new block has been connected to the + // main chain. The set of output spent within a block is also passed in + // so indexers can access the previous output scripts input spent if + // required. + ConnectBlock(database.Tx, *btcutil.Block, []SpentTxOut) error + + // DisconnectBlock is invoked when a block has been disconnected from + // the main chain. The set of outputs scripts that were spent within + // this block is also returned so indexers can clean up the prior index + // state for this block. + DisconnectBlock(database.Tx, *btcutil.Block, []SpentTxOut) error +} + +// Config is a descriptor which specifies the blockchain instance configuration. +type Config struct { + // DB defines the database which houses the blocks and will be used to + // store all metadata created by this package such as the utxo set. + // + // This field is required. + DB database.DB + + // Interrupt specifies a channel the caller can close to signal that + // long running operations, such as catching up indexes or performing + // database migrations, should be interrupted. + // + // This field can be nil if the caller does not desire the behavior. + Interrupt <-chan struct{} + + // ChainParams identifies which chain parameters the chain is associated + // with. + // + // This field is required. + ChainParams *chaincfg.Params + + // Checkpoints hold caller-defined checkpoints that should be added to + // the default checkpoints in ChainParams. Checkpoints must be sorted + // by height. + // + // This field can be nil if the caller does not wish to specify any + // checkpoints. + Checkpoints []chaincfg.Checkpoint + + // TimeSource defines the median time source to use for things such as + // block processing and determining whether or not the chain is current. + // + // The caller is expected to keep a reference to the time source as well + // and add time samples from other peers on the network so the local + // time is adjusted to be in agreement with other peers. + TimeSource MedianTimeSource + + // SigCache defines a signature cache to use when when validating + // signatures. This is typically most useful when individual + // transactions are already being validated prior to their inclusion in + // a block such as what is usually done via a transaction memory pool. + // + // This field can be nil if the caller is not interested in using a + // signature cache. + SigCache *txscript.SigCache + + // IndexManager defines an index manager to use when initializing the + // chain and connecting and disconnecting blocks. + // + // This field can be nil if the caller does not wish to make use of an + // index manager. + IndexManager IndexManager + + // HashCache defines a transaction hash mid-state cache to use when + // validating transactions. This cache has the potential to greatly + // speed up transaction validation as re-using the pre-calculated + // mid-state eliminates the O(N^2) validation complexity due to the + // SigHashAll flag. + // + // This field can be nil if the caller is not interested in using a + // signature cache. + HashCache *txscript.HashCache +} + +// New returns a BlockChain instance using the provided configuration details. +func New(config *Config) (*BlockChain, error) { + // Enforce required config fields. + if config.DB == nil { + return nil, AssertError("blockchain.New database is nil") + } + if config.ChainParams == nil { + return nil, AssertError("blockchain.New chain parameters nil") + } + if config.TimeSource == nil { + return nil, AssertError("blockchain.New timesource is nil") + } + + // Generate a checkpoint by height map from the provided checkpoints + // and assert the provided checkpoints are sorted by height as required. + var checkpointsByHeight map[int32]*chaincfg.Checkpoint + var prevCheckpointHeight int32 + if len(config.Checkpoints) > 0 { + checkpointsByHeight = make(map[int32]*chaincfg.Checkpoint) + for i := range config.Checkpoints { + checkpoint := &config.Checkpoints[i] + if checkpoint.Height <= prevCheckpointHeight { + return nil, AssertError("blockchain.New " + + "checkpoints are not sorted by height") + } + + checkpointsByHeight[checkpoint.Height] = checkpoint + prevCheckpointHeight = checkpoint.Height + } + } + + params := config.ChainParams + targetTimespan := int64(params.TargetTimespan / time.Second) + targetTimePerBlock := int64(params.TargetTimePerBlock / time.Second) + adjustmentFactor := params.RetargetAdjustmentFactor + b := BlockChain{ + checkpoints: config.Checkpoints, + checkpointsByHeight: checkpointsByHeight, + db: config.DB, + chainParams: params, + timeSource: config.TimeSource, + sigCache: config.SigCache, + indexManager: config.IndexManager, + minRetargetTimespan: targetTimespan / adjustmentFactor, + maxRetargetTimespan: targetTimespan * adjustmentFactor, + blocksPerRetarget: int32(targetTimespan / targetTimePerBlock), + index: newBlockIndex(config.DB, params), + hashCache: config.HashCache, + bestChain: newChainView(nil), + orphans: make(map[chainhash.Hash]*orphanBlock), + prevOrphans: make(map[chainhash.Hash][]*orphanBlock), + warningCaches: newThresholdCaches(vbNumBits), + deploymentCaches: newThresholdCaches(chaincfg.DefinedDeployments), + } + + // Initialize the chain state from the passed database. When the db + // does not yet contain any chain state, both it and the chain state + // will be initialized to contain only the genesis block. + if err := b.initChainState(); err != nil { + return nil, err + } + + // Perform any upgrades to the various chain-specific buckets as needed. + if err := b.maybeUpgradeDbBuckets(config.Interrupt); err != nil { + return nil, err + } + + // Initialize and catch up all of the currently active optional indexes + // as needed. + if config.IndexManager != nil { + err := config.IndexManager.Init(&b, config.Interrupt) + if err != nil { + return nil, err + } + } + + // Initialize rule change threshold state caches. + if err := b.initThresholdCaches(); err != nil { + return nil, err + } + + bestNode := b.bestChain.Tip() + log.Infof("Chain state (height %d, hash %v, totaltx %d, work %v)", + bestNode.height, bestNode.hash, b.stateSnapshot.TotalTxns, + bestNode.workSum) + + return &b, nil +} diff --git a/vendor/github.com/btcsuite/btcd/blockchain/chainio.go b/vendor/github.com/btcsuite/btcd/blockchain/chainio.go new file mode 100644 index 0000000..8d76d3c --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/blockchain/chainio.go @@ -0,0 +1,1416 @@ +// Copyright (c) 2015-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "bytes" + "encoding/binary" + "fmt" + "math/big" + "sync" + "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" +) + +const ( + // blockHdrSize is the size of a block header. This is simply the + // constant from wire and is only provided here for convenience since + // wire.MaxBlockHeaderPayload is quite long. + blockHdrSize = wire.MaxBlockHeaderPayload + + // latestUtxoSetBucketVersion is the current version of the utxo set + // bucket that is used to track all unspent outputs. + latestUtxoSetBucketVersion = 2 + + // latestSpendJournalBucketVersion is the current version of the spend + // journal bucket that is used to track all spent transactions for use + // in reorgs. + latestSpendJournalBucketVersion = 1 +) + +var ( + // blockIndexBucketName is the name of the db bucket used to house to the + // block headers and contextual information. + blockIndexBucketName = []byte("blockheaderidx") + + // hashIndexBucketName is the name of the db bucket used to house to the + // block hash -> block height index. + hashIndexBucketName = []byte("hashidx") + + // heightIndexBucketName is the name of the db bucket used to house to + // the block height -> block hash index. + heightIndexBucketName = []byte("heightidx") + + // chainStateKeyName is the name of the db key used to store the best + // chain state. + chainStateKeyName = []byte("chainstate") + + // spendJournalVersionKeyName is the name of the db key used to store + // the version of the spend journal currently in the database. + spendJournalVersionKeyName = []byte("spendjournalversion") + + // spendJournalBucketName is the name of the db bucket used to house + // transactions outputs that are spent in each block. + spendJournalBucketName = []byte("spendjournal") + + // utxoSetVersionKeyName is the name of the db key used to store the + // version of the utxo set currently in the database. + utxoSetVersionKeyName = []byte("utxosetversion") + + // utxoSetBucketName is the name of the db bucket used to house the + // unspent transaction output set. + utxoSetBucketName = []byte("utxosetv2") + + // byteOrder is the preferred byte order used for serializing numeric + // fields for storage in the database. + byteOrder = binary.LittleEndian +) + +// errNotInMainChain signifies that a block hash or height that is not in the +// main chain was requested. +type errNotInMainChain string + +// Error implements the error interface. +func (e errNotInMainChain) Error() string { + return string(e) +} + +// isNotInMainChainErr returns whether or not the passed error is an +// errNotInMainChain error. +func isNotInMainChainErr(err error) bool { + _, ok := err.(errNotInMainChain) + return ok +} + +// errDeserialize signifies that a problem was encountered when deserializing +// data. +type errDeserialize string + +// Error implements the error interface. +func (e errDeserialize) Error() string { + return string(e) +} + +// isDeserializeErr returns whether or not the passed error is an errDeserialize +// error. +func isDeserializeErr(err error) bool { + _, ok := err.(errDeserialize) + return ok +} + +// isDbBucketNotFoundErr returns whether or not the passed error is a +// database.Error with an error code of database.ErrBucketNotFound. +func isDbBucketNotFoundErr(err error) bool { + dbErr, ok := err.(database.Error) + return ok && dbErr.ErrorCode == database.ErrBucketNotFound +} + +// dbFetchVersion fetches an individual version with the given key from the +// metadata bucket. It is primarily used to track versions on entities such as +// buckets. It returns zero if the provided key does not exist. +func dbFetchVersion(dbTx database.Tx, key []byte) uint32 { + serialized := dbTx.Metadata().Get(key) + if serialized == nil { + return 0 + } + + return byteOrder.Uint32(serialized[:]) +} + +// dbPutVersion uses an existing database transaction to update the provided +// key in the metadata bucket to the given version. It is primarily used to +// track versions on entities such as buckets. +func dbPutVersion(dbTx database.Tx, key []byte, version uint32) error { + var serialized [4]byte + byteOrder.PutUint32(serialized[:], version) + return dbTx.Metadata().Put(key, serialized[:]) +} + +// dbFetchOrCreateVersion uses an existing database transaction to attempt to +// fetch the provided key from the metadata bucket as a version and in the case +// it doesn't exist, it adds the entry with the provided default version and +// returns that. This is useful during upgrades to automatically handle loading +// and adding version keys as necessary. +func dbFetchOrCreateVersion(dbTx database.Tx, key []byte, defaultVersion uint32) (uint32, error) { + version := dbFetchVersion(dbTx, key) + if version == 0 { + version = defaultVersion + err := dbPutVersion(dbTx, key, version) + if err != nil { + return 0, err + } + } + + return version, nil +} + +// ----------------------------------------------------------------------------- +// The transaction spend journal consists of an entry for each block connected +// to the main chain which contains the transaction outputs the block spends +// serialized such that the order is the reverse of the order they were spent. +// +// This is required because reorganizing the chain necessarily entails +// disconnecting blocks to get back to the point of the fork which implies +// unspending all of the transaction outputs that each block previously spent. +// Since the utxo set, by definition, only contains unspent transaction outputs, +// the spent transaction outputs must be resurrected from somewhere. There is +// more than one way this could be done, however this is the most straight +// forward method that does not require having a transaction index and unpruned +// blockchain. +// +// NOTE: This format is NOT self describing. The additional details such as +// the number of entries (transaction inputs) are expected to come from the +// block itself and the utxo set (for legacy entries). The rationale in doing +// this is to save space. This is also the reason the spent outputs are +// serialized in the reverse order they are spent because later transactions are +// allowed to spend outputs from earlier ones in the same block. +// +// The reserved field below used to keep track of the version of the containing +// transaction when the height in the header code was non-zero, however the +// height is always non-zero now, but keeping the extra reserved field allows +// backwards compatibility. +// +// The serialized format is: +// +// [
],... +// +// Field Type Size +// header code VLQ variable +// reserved byte 1 +// compressed txout +// compressed amount VLQ variable +// compressed script []byte variable +// +// The serialized header code format is: +// bit 0 - containing transaction is a coinbase +// bits 1-x - height of the block that contains the spent txout +// +// Example 1: +// From block 170 in main blockchain. +// +// 1300320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c +// <><><------------------------------------------------------------------> +// | | | +// | reserved compressed txout +// header code +// +// - header code: 0x13 (coinbase, height 9) +// - reserved: 0x00 +// - compressed txout 0: +// - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) +// - 0x05: special script type pay-to-pubkey +// - 0x11...5c: x-coordinate of the pubkey +// +// Example 2: +// Adapted from block 100025 in main blockchain. +// +// 8b99700091f20f006edbc6c4d31bae9f1ccc38538a114bf42de65e868b99700086c64700b2fb57eadf61e106a100a7445a8c3f67898841ec +// <----><><----------------------------------------------><----><><----------------------------------------------> +// | | | | | | +// | reserved compressed txout | reserved compressed txout +// header code header code +// +// - Last spent output: +// - header code: 0x8b9970 (not coinbase, height 100024) +// - reserved: 0x00 +// - compressed txout: +// - 0x91f20f: VLQ-encoded compressed amount for 34405000000 (344.05 BTC) +// - 0x00: special script type pay-to-pubkey-hash +// - 0x6e...86: pubkey hash +// - Second to last spent output: +// - header code: 0x8b9970 (not coinbase, height 100024) +// - reserved: 0x00 +// - compressed txout: +// - 0x86c647: VLQ-encoded compressed amount for 13761000000 (137.61 BTC) +// - 0x00: special script type pay-to-pubkey-hash +// - 0xb2...ec: pubkey hash +// ----------------------------------------------------------------------------- + +// SpentTxOut contains a spent transaction output and potentially additional +// contextual information such as whether or not it was contained in a coinbase +// transaction, the version of the transaction it was contained in, and which +// block height the containing transaction was included in. As described in +// the comments above, the additional contextual information will only be valid +// when this spent txout is spending the last unspent output of the containing +// transaction. +type SpentTxOut struct { + // Amount is the amount of the output. + Amount int64 + + // PkScipt is the the public key script for the output. + PkScript []byte + + // Height is the height of the the block containing the creating tx. + Height int32 + + // Denotes if the creating tx is a coinbase. + IsCoinBase bool +} + +// FetchSpendJournal attempts to retrieve the spend journal, or the set of +// outputs spent for the target block. This provides a view of all the outputs +// that will be consumed once the target block is connected to the end of the +// main chain. +// +// This function is safe for concurrent access. +func (b *BlockChain) FetchSpendJournal(targetBlock *btcutil.Block) ([]SpentTxOut, error) { + b.chainLock.RLock() + defer b.chainLock.RUnlock() + + var spendEntries []SpentTxOut + err := b.db.View(func(dbTx database.Tx) error { + var err error + + spendEntries, err = dbFetchSpendJournalEntry(dbTx, targetBlock) + return err + }) + if err != nil { + return nil, err + } + + return spendEntries, nil +} + +// spentTxOutHeaderCode returns the calculated header code to be used when +// serializing the provided stxo entry. +func spentTxOutHeaderCode(stxo *SpentTxOut) uint64 { + // As described in the serialization format comments, the header code + // encodes the height shifted over one bit and the coinbase flag in the + // lowest bit. + headerCode := uint64(stxo.Height) << 1 + if stxo.IsCoinBase { + headerCode |= 0x01 + } + + return headerCode +} + +// spentTxOutSerializeSize returns the number of bytes it would take to +// serialize the passed stxo according to the format described above. +func spentTxOutSerializeSize(stxo *SpentTxOut) int { + size := serializeSizeVLQ(spentTxOutHeaderCode(stxo)) + if stxo.Height > 0 { + // The legacy v1 spend journal format conditionally tracked the + // containing transaction version when the height was non-zero, + // so this is required for backwards compat. + size += serializeSizeVLQ(0) + } + return size + compressedTxOutSize(uint64(stxo.Amount), stxo.PkScript) +} + +// putSpentTxOut serializes the passed stxo according to the format described +// above directly into the passed target byte slice. The target byte slice must +// be at least large enough to handle the number of bytes returned by the +// SpentTxOutSerializeSize function or it will panic. +func putSpentTxOut(target []byte, stxo *SpentTxOut) int { + headerCode := spentTxOutHeaderCode(stxo) + offset := putVLQ(target, headerCode) + if stxo.Height > 0 { + // The legacy v1 spend journal format conditionally tracked the + // containing transaction version when the height was non-zero, + // so this is required for backwards compat. + offset += putVLQ(target[offset:], 0) + } + return offset + putCompressedTxOut(target[offset:], uint64(stxo.Amount), + stxo.PkScript) +} + +// decodeSpentTxOut decodes the passed serialized stxo entry, possibly followed +// by other data, into the passed stxo struct. It returns the number of bytes +// read. +func decodeSpentTxOut(serialized []byte, stxo *SpentTxOut) (int, error) { + // Ensure there are bytes to decode. + if len(serialized) == 0 { + return 0, errDeserialize("no serialized bytes") + } + + // Deserialize the header code. + code, offset := deserializeVLQ(serialized) + if offset >= len(serialized) { + return offset, errDeserialize("unexpected end of data after " + + "header code") + } + + // Decode the header code. + // + // Bit 0 indicates containing transaction is a coinbase. + // Bits 1-x encode height of containing transaction. + stxo.IsCoinBase = code&0x01 != 0 + stxo.Height = int32(code >> 1) + if stxo.Height > 0 { + // The legacy v1 spend journal format conditionally tracked the + // containing transaction version when the height was non-zero, + // so this is required for backwards compat. + _, bytesRead := deserializeVLQ(serialized[offset:]) + offset += bytesRead + if offset >= len(serialized) { + return offset, errDeserialize("unexpected end of data " + + "after reserved") + } + } + + // Decode the compressed txout. + amount, pkScript, bytesRead, err := decodeCompressedTxOut( + serialized[offset:]) + offset += bytesRead + if err != nil { + return offset, errDeserialize(fmt.Sprintf("unable to decode "+ + "txout: %v", err)) + } + stxo.Amount = int64(amount) + stxo.PkScript = pkScript + return offset, nil +} + +// deserializeSpendJournalEntry decodes the passed serialized byte slice into a +// slice of spent txouts according to the format described in detail above. +// +// Since the serialization format is not self describing, as noted in the +// format comments, this function also requires the transactions that spend the +// txouts. +func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx) ([]SpentTxOut, error) { + // Calculate the total number of stxos. + var numStxos int + for _, tx := range txns { + numStxos += len(tx.TxIn) + } + + // When a block has no spent txouts there is nothing to serialize. + if len(serialized) == 0 { + // Ensure the block actually has no stxos. This should never + // happen unless there is database corruption or an empty entry + // erroneously made its way into the database. + if numStxos != 0 { + return nil, AssertError(fmt.Sprintf("mismatched spend "+ + "journal serialization - no serialization for "+ + "expected %d stxos", numStxos)) + } + + return nil, nil + } + + // Loop backwards through all transactions so everything is read in + // reverse order to match the serialization order. + stxoIdx := numStxos - 1 + offset := 0 + stxos := make([]SpentTxOut, numStxos) + for txIdx := len(txns) - 1; txIdx > -1; txIdx-- { + tx := txns[txIdx] + + // Loop backwards through all of the transaction inputs and read + // the associated stxo. + for txInIdx := len(tx.TxIn) - 1; txInIdx > -1; txInIdx-- { + txIn := tx.TxIn[txInIdx] + stxo := &stxos[stxoIdx] + stxoIdx-- + + n, err := decodeSpentTxOut(serialized[offset:], stxo) + offset += n + if err != nil { + return nil, errDeserialize(fmt.Sprintf("unable "+ + "to decode stxo for %v: %v", + txIn.PreviousOutPoint, err)) + } + } + } + + return stxos, nil +} + +// serializeSpendJournalEntry serializes all of the passed spent txouts into a +// single byte slice according to the format described in detail above. +func serializeSpendJournalEntry(stxos []SpentTxOut) []byte { + if len(stxos) == 0 { + return nil + } + + // Calculate the size needed to serialize the entire journal entry. + var size int + for i := range stxos { + size += spentTxOutSerializeSize(&stxos[i]) + } + serialized := make([]byte, size) + + // Serialize each individual stxo directly into the slice in reverse + // order one after the other. + var offset int + for i := len(stxos) - 1; i > -1; i-- { + offset += putSpentTxOut(serialized[offset:], &stxos[i]) + } + + return serialized +} + +// dbFetchSpendJournalEntry fetches the spend journal entry for the passed block +// and deserializes it into a slice of spent txout entries. +// +// NOTE: Legacy entries will not have the coinbase flag or height set unless it +// was the final output spend in the containing transaction. It is up to the +// caller to handle this properly by looking the information up in the utxo set. +func dbFetchSpendJournalEntry(dbTx database.Tx, block *btcutil.Block) ([]SpentTxOut, error) { + // Exclude the coinbase transaction since it can't spend anything. + spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) + serialized := spendBucket.Get(block.Hash()[:]) + blockTxns := block.MsgBlock().Transactions[1:] + stxos, err := deserializeSpendJournalEntry(serialized, blockTxns) + if err != nil { + // Ensure any deserialization errors are returned as database + // corruption errors. + if isDeserializeErr(err) { + return nil, database.Error{ + ErrorCode: database.ErrCorruption, + Description: fmt.Sprintf("corrupt spend "+ + "information for %v: %v", block.Hash(), + err), + } + } + + return nil, err + } + + return stxos, nil +} + +// dbPutSpendJournalEntry uses an existing database transaction to update the +// spend journal entry for the given block hash using the provided slice of +// spent txouts. The spent txouts slice must contain an entry for every txout +// the transactions in the block spend in the order they are spent. +func dbPutSpendJournalEntry(dbTx database.Tx, blockHash *chainhash.Hash, stxos []SpentTxOut) error { + spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) + serialized := serializeSpendJournalEntry(stxos) + return spendBucket.Put(blockHash[:], serialized) +} + +// dbRemoveSpendJournalEntry uses an existing database transaction to remove the +// spend journal entry for the passed block hash. +func dbRemoveSpendJournalEntry(dbTx database.Tx, blockHash *chainhash.Hash) error { + spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) + return spendBucket.Delete(blockHash[:]) +} + +// ----------------------------------------------------------------------------- +// The unspent transaction output (utxo) set consists of an entry for each +// unspent output using a format that is optimized to reduce space using domain +// specific compression algorithms. This format is a slightly modified version +// of the format used in Bitcoin Core. +// +// Each entry is keyed by an outpoint as specified below. It is important to +// note that the key encoding uses a VLQ, which employs an MSB encoding so +// iteration of utxos when doing byte-wise comparisons will produce them in +// order. +// +// The serialized key format is: +// +// +// Field Type Size +// hash chainhash.Hash chainhash.HashSize +// output index VLQ variable +// +// The serialized value format is: +// +//
+// +// Field Type Size +// header code VLQ variable +// compressed txout +// compressed amount VLQ variable +// compressed script []byte variable +// +// The serialized header code format is: +// bit 0 - containing transaction is a coinbase +// bits 1-x - height of the block that contains the unspent txout +// +// Example 1: +// From tx in main blockchain: +// Blk 1, 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098:0 +// +// 03320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52 +// <><------------------------------------------------------------------> +// | | +// header code compressed txout +// +// - header code: 0x03 (coinbase, height 1) +// - compressed txout: +// - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) +// - 0x04: special script type pay-to-pubkey +// - 0x96...52: x-coordinate of the pubkey +// +// Example 2: +// From tx in main blockchain: +// Blk 113931, 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f:2 +// +// 8cf316800900b8025be1b3efc63b0ad48e7f9f10e87544528d58 +// <----><------------------------------------------> +// | | +// header code compressed txout +// +// - header code: 0x8cf316 (not coinbase, height 113931) +// - compressed txout: +// - 0x8009: VLQ-encoded compressed amount for 15000000 (0.15 BTC) +// - 0x00: special script type pay-to-pubkey-hash +// - 0xb8...58: pubkey hash +// +// Example 3: +// From tx in main blockchain: +// Blk 338156, 1b02d1c8cfef60a189017b9a420c682cf4a0028175f2f563209e4ff61c8c3620:22 +// +// a8a2588ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6 +// <----><--------------------------------------------------> +// | | +// header code compressed txout +// +// - header code: 0xa8a258 (not coinbase, height 338156) +// - compressed txout: +// - 0x8ba5b9e763: VLQ-encoded compressed amount for 366875659 (3.66875659 BTC) +// - 0x01: special script type pay-to-script-hash +// - 0x1d...e6: script hash +// ----------------------------------------------------------------------------- + +// maxUint32VLQSerializeSize is the maximum number of bytes a max uint32 takes +// to serialize as a VLQ. +var maxUint32VLQSerializeSize = serializeSizeVLQ(1<<32 - 1) + +// outpointKeyPool defines a concurrent safe free list of byte slices used to +// provide temporary buffers for outpoint database keys. +var outpointKeyPool = sync.Pool{ + New: func() interface{} { + b := make([]byte, chainhash.HashSize+maxUint32VLQSerializeSize) + return &b // Pointer to slice to avoid boxing alloc. + }, +} + +// outpointKey returns a key suitable for use as a database key in the utxo set +// while making use of a free list. A new buffer is allocated if there are not +// already any available on the free list. The returned byte slice should be +// returned to the free list by using the recycleOutpointKey function when the +// caller is done with it _unless_ the slice will need to live for longer than +// the caller can calculate such as when used to write to the database. +func outpointKey(outpoint wire.OutPoint) *[]byte { + // A VLQ employs an MSB encoding, so they are useful not only to reduce + // the amount of storage space, but also so iteration of utxos when + // doing byte-wise comparisons will produce them in order. + key := outpointKeyPool.Get().(*[]byte) + idx := uint64(outpoint.Index) + *key = (*key)[:chainhash.HashSize+serializeSizeVLQ(idx)] + copy(*key, outpoint.Hash[:]) + putVLQ((*key)[chainhash.HashSize:], idx) + return key +} + +// recycleOutpointKey puts the provided byte slice, which should have been +// obtained via the outpointKey function, back on the free list. +func recycleOutpointKey(key *[]byte) { + outpointKeyPool.Put(key) +} + +// utxoEntryHeaderCode returns the calculated header code to be used when +// serializing the provided utxo entry. +func utxoEntryHeaderCode(entry *UtxoEntry) (uint64, error) { + if entry.IsSpent() { + return 0, AssertError("attempt to serialize spent utxo header") + } + + // As described in the serialization format comments, the header code + // encodes the height shifted over one bit and the coinbase flag in the + // lowest bit. + headerCode := uint64(entry.BlockHeight()) << 1 + if entry.IsCoinBase() { + headerCode |= 0x01 + } + + return headerCode, nil +} + +// serializeUtxoEntry returns the entry serialized to a format that is suitable +// for long-term storage. The format is described in detail above. +func serializeUtxoEntry(entry *UtxoEntry) ([]byte, error) { + // Spent outputs have no serialization. + if entry.IsSpent() { + return nil, nil + } + + // Encode the header code. + headerCode, err := utxoEntryHeaderCode(entry) + if err != nil { + return nil, err + } + + // Calculate the size needed to serialize the entry. + size := serializeSizeVLQ(headerCode) + + compressedTxOutSize(uint64(entry.Amount()), entry.PkScript()) + + // Serialize the header code followed by the compressed unspent + // transaction output. + serialized := make([]byte, size) + offset := putVLQ(serialized, headerCode) + offset += putCompressedTxOut(serialized[offset:], uint64(entry.Amount()), + entry.PkScript()) + + return serialized, nil +} + +// deserializeUtxoEntry decodes a utxo entry from the passed serialized byte +// slice into a new UtxoEntry using a format that is suitable for long-term +// storage. The format is described in detail above. +func deserializeUtxoEntry(serialized []byte) (*UtxoEntry, error) { + // Deserialize the header code. + code, offset := deserializeVLQ(serialized) + if offset >= len(serialized) { + return nil, errDeserialize("unexpected end of data after header") + } + + // Decode the header code. + // + // Bit 0 indicates whether the containing transaction is a coinbase. + // Bits 1-x encode height of containing transaction. + isCoinBase := code&0x01 != 0 + blockHeight := int32(code >> 1) + + // Decode the compressed unspent transaction output. + amount, pkScript, _, err := decodeCompressedTxOut(serialized[offset:]) + if err != nil { + return nil, errDeserialize(fmt.Sprintf("unable to decode "+ + "utxo: %v", err)) + } + + entry := &UtxoEntry{ + amount: int64(amount), + pkScript: pkScript, + blockHeight: blockHeight, + packedFlags: 0, + } + if isCoinBase { + entry.packedFlags |= tfCoinBase + } + + return entry, nil +} + +// dbFetchUtxoEntryByHash attempts to find and fetch a utxo for the given hash. +// It uses a cursor and seek to try and do this as efficiently as possible. +// +// When there are no entries for the provided hash, nil will be returned for the +// both the entry and the error. +func dbFetchUtxoEntryByHash(dbTx database.Tx, hash *chainhash.Hash) (*UtxoEntry, error) { + // Attempt to find an entry by seeking for the hash along with a zero + // index. Due to the fact the keys are serialized as , + // where the index uses an MSB encoding, if there are any entries for + // the hash at all, one will be found. + cursor := dbTx.Metadata().Bucket(utxoSetBucketName).Cursor() + key := outpointKey(wire.OutPoint{Hash: *hash, Index: 0}) + ok := cursor.Seek(*key) + recycleOutpointKey(key) + if !ok { + return nil, nil + } + + // An entry was found, but it could just be an entry with the next + // highest hash after the requested one, so make sure the hashes + // actually match. + cursorKey := cursor.Key() + if len(cursorKey) < chainhash.HashSize { + return nil, nil + } + if !bytes.Equal(hash[:], cursorKey[:chainhash.HashSize]) { + return nil, nil + } + + return deserializeUtxoEntry(cursor.Value()) +} + +// dbFetchUtxoEntry uses an existing database transaction to fetch the specified +// transaction output from the utxo set. +// +// When there is no entry for the provided output, nil will be returned for both +// the entry and the error. +func dbFetchUtxoEntry(dbTx database.Tx, outpoint wire.OutPoint) (*UtxoEntry, error) { + // Fetch the unspent transaction output information for the passed + // transaction output. Return now when there is no entry. + key := outpointKey(outpoint) + utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) + serializedUtxo := utxoBucket.Get(*key) + recycleOutpointKey(key) + if serializedUtxo == nil { + return nil, nil + } + + // A non-nil zero-length entry means there is an entry in the database + // for a spent transaction output which should never be the case. + if len(serializedUtxo) == 0 { + return nil, AssertError(fmt.Sprintf("database contains entry "+ + "for spent tx output %v", outpoint)) + } + + // Deserialize the utxo entry and return it. + entry, err := deserializeUtxoEntry(serializedUtxo) + if err != nil { + // Ensure any deserialization errors are returned as database + // corruption errors. + if isDeserializeErr(err) { + return nil, database.Error{ + ErrorCode: database.ErrCorruption, + Description: fmt.Sprintf("corrupt utxo entry "+ + "for %v: %v", outpoint, err), + } + } + + return nil, err + } + + return entry, nil +} + +// dbPutUtxoView uses an existing database transaction to update the utxo set +// in the database based on the provided utxo view contents and state. In +// particular, only the entries that have been marked as modified are written +// to the database. +func dbPutUtxoView(dbTx database.Tx, view *UtxoViewpoint) error { + utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) + for outpoint, entry := range view.entries { + // No need to update the database if the entry was not modified. + if entry == nil || !entry.isModified() { + continue + } + + // Remove the utxo entry if it is spent. + if entry.IsSpent() { + key := outpointKey(outpoint) + err := utxoBucket.Delete(*key) + recycleOutpointKey(key) + if err != nil { + return err + } + + continue + } + + // Serialize and store the utxo entry. + serialized, err := serializeUtxoEntry(entry) + if err != nil { + return err + } + key := outpointKey(outpoint) + err = utxoBucket.Put(*key, serialized) + // NOTE: The key is intentionally not recycled here since the + // database interface contract prohibits modifications. It will + // be garbage collected normally when the database is done with + // it. + if err != nil { + return err + } + } + + return nil +} + +// ----------------------------------------------------------------------------- +// The block index consists of two buckets with an entry for every block in the +// main chain. One bucket is for the hash to height mapping and the other is +// for the height to hash mapping. +// +// The serialized format for values in the hash to height bucket is: +// +// +// Field Type Size +// height uint32 4 bytes +// +// The serialized format for values in the height to hash bucket is: +// +// +// Field Type Size +// hash chainhash.Hash chainhash.HashSize +// ----------------------------------------------------------------------------- + +// dbPutBlockIndex uses an existing database transaction to update or add the +// block index entries for the hash to height and height to hash mappings for +// the provided values. +func dbPutBlockIndex(dbTx database.Tx, hash *chainhash.Hash, height int32) error { + // Serialize the height for use in the index entries. + var serializedHeight [4]byte + byteOrder.PutUint32(serializedHeight[:], uint32(height)) + + // Add the block hash to height mapping to the index. + meta := dbTx.Metadata() + hashIndex := meta.Bucket(hashIndexBucketName) + if err := hashIndex.Put(hash[:], serializedHeight[:]); err != nil { + return err + } + + // Add the block height to hash mapping to the index. + heightIndex := meta.Bucket(heightIndexBucketName) + return heightIndex.Put(serializedHeight[:], hash[:]) +} + +// dbRemoveBlockIndex uses an existing database transaction remove block index +// entries from the hash to height and height to hash mappings for the provided +// values. +func dbRemoveBlockIndex(dbTx database.Tx, hash *chainhash.Hash, height int32) error { + // Remove the block hash to height mapping. + meta := dbTx.Metadata() + hashIndex := meta.Bucket(hashIndexBucketName) + if err := hashIndex.Delete(hash[:]); err != nil { + return err + } + + // Remove the block height to hash mapping. + var serializedHeight [4]byte + byteOrder.PutUint32(serializedHeight[:], uint32(height)) + heightIndex := meta.Bucket(heightIndexBucketName) + return heightIndex.Delete(serializedHeight[:]) +} + +// dbFetchHeightByHash uses an existing database transaction to retrieve the +// height for the provided hash from the index. +func dbFetchHeightByHash(dbTx database.Tx, hash *chainhash.Hash) (int32, error) { + meta := dbTx.Metadata() + hashIndex := meta.Bucket(hashIndexBucketName) + serializedHeight := hashIndex.Get(hash[:]) + if serializedHeight == nil { + str := fmt.Sprintf("block %s is not in the main chain", hash) + return 0, errNotInMainChain(str) + } + + return int32(byteOrder.Uint32(serializedHeight)), nil +} + +// dbFetchHashByHeight uses an existing database transaction to retrieve the +// hash for the provided height from the index. +func dbFetchHashByHeight(dbTx database.Tx, height int32) (*chainhash.Hash, error) { + var serializedHeight [4]byte + byteOrder.PutUint32(serializedHeight[:], uint32(height)) + + meta := dbTx.Metadata() + heightIndex := meta.Bucket(heightIndexBucketName) + hashBytes := heightIndex.Get(serializedHeight[:]) + if hashBytes == nil { + str := fmt.Sprintf("no block at height %d exists", height) + return nil, errNotInMainChain(str) + } + + var hash chainhash.Hash + copy(hash[:], hashBytes) + return &hash, nil +} + +// ----------------------------------------------------------------------------- +// The best chain state consists of the best block hash and height, the total +// number of transactions up to and including those in the best block, and the +// accumulated work sum up to and including the best block. +// +// The serialized format is: +// +// +// +// Field Type Size +// block hash chainhash.Hash chainhash.HashSize +// block height uint32 4 bytes +// total txns uint64 8 bytes +// work sum length uint32 4 bytes +// work sum big.Int work sum length +// ----------------------------------------------------------------------------- + +// bestChainState represents the data to be stored the database for the current +// best chain state. +type bestChainState struct { + hash chainhash.Hash + height uint32 + totalTxns uint64 + workSum *big.Int +} + +// serializeBestChainState returns the serialization of the passed block best +// chain state. This is data to be stored in the chain state bucket. +func serializeBestChainState(state bestChainState) []byte { + // Calculate the full size needed to serialize the chain state. + workSumBytes := state.workSum.Bytes() + workSumBytesLen := uint32(len(workSumBytes)) + serializedLen := chainhash.HashSize + 4 + 8 + 4 + workSumBytesLen + + // Serialize the chain state. + serializedData := make([]byte, serializedLen) + copy(serializedData[0:chainhash.HashSize], state.hash[:]) + offset := uint32(chainhash.HashSize) + byteOrder.PutUint32(serializedData[offset:], state.height) + offset += 4 + byteOrder.PutUint64(serializedData[offset:], state.totalTxns) + offset += 8 + byteOrder.PutUint32(serializedData[offset:], workSumBytesLen) + offset += 4 + copy(serializedData[offset:], workSumBytes) + return serializedData[:] +} + +// deserializeBestChainState deserializes the passed serialized best chain +// state. This is data stored in the chain state bucket and is updated after +// every block is connected or disconnected form the main chain. +// block. +func deserializeBestChainState(serializedData []byte) (bestChainState, error) { + // Ensure the serialized data has enough bytes to properly deserialize + // the hash, height, total transactions, and work sum length. + if len(serializedData) < chainhash.HashSize+16 { + return bestChainState{}, database.Error{ + ErrorCode: database.ErrCorruption, + Description: "corrupt best chain state", + } + } + + state := bestChainState{} + copy(state.hash[:], serializedData[0:chainhash.HashSize]) + offset := uint32(chainhash.HashSize) + state.height = byteOrder.Uint32(serializedData[offset : offset+4]) + offset += 4 + state.totalTxns = byteOrder.Uint64(serializedData[offset : offset+8]) + offset += 8 + workSumBytesLen := byteOrder.Uint32(serializedData[offset : offset+4]) + offset += 4 + + // Ensure the serialized data has enough bytes to deserialize the work + // sum. + if uint32(len(serializedData[offset:])) < workSumBytesLen { + return bestChainState{}, database.Error{ + ErrorCode: database.ErrCorruption, + Description: "corrupt best chain state", + } + } + workSumBytes := serializedData[offset : offset+workSumBytesLen] + state.workSum = new(big.Int).SetBytes(workSumBytes) + + return state, nil +} + +// dbPutBestState uses an existing database transaction to update the best chain +// state with the given parameters. +func dbPutBestState(dbTx database.Tx, snapshot *BestState, workSum *big.Int) error { + // Serialize the current best chain state. + serializedData := serializeBestChainState(bestChainState{ + hash: snapshot.Hash, + height: uint32(snapshot.Height), + totalTxns: snapshot.TotalTxns, + workSum: workSum, + }) + + // Store the current best chain state into the database. + return dbTx.Metadata().Put(chainStateKeyName, serializedData) +} + +// createChainState initializes both the database and the chain state to the +// genesis block. This includes creating the necessary buckets and inserting +// the genesis block, so it must only be called on an uninitialized database. +func (b *BlockChain) createChainState() error { + // Create a new node from the genesis block and set it as the best node. + genesisBlock := btcutil.NewBlock(b.chainParams.GenesisBlock) + genesisBlock.SetHeight(0) + header := &genesisBlock.MsgBlock().Header + node := newBlockNode(header, nil) + node.status = statusDataStored | statusValid + b.bestChain.SetTip(node) + + // Add the new node to the index which is used for faster lookups. + b.index.addNode(node) + + // Initialize the state related to the best block. Since it is the + // genesis block, use its timestamp for the median time. + numTxns := uint64(len(genesisBlock.MsgBlock().Transactions)) + blockSize := uint64(genesisBlock.MsgBlock().SerializeSize()) + blockWeight := uint64(GetBlockWeight(genesisBlock)) + b.stateSnapshot = newBestState(node, blockSize, blockWeight, numTxns, + numTxns, time.Unix(node.timestamp, 0)) + + // Create the initial the database chain state including creating the + // necessary index buckets and inserting the genesis block. + err := b.db.Update(func(dbTx database.Tx) error { + meta := dbTx.Metadata() + + // Create the bucket that houses the block index data. + _, err := meta.CreateBucket(blockIndexBucketName) + if err != nil { + return err + } + + // Create the bucket that houses the chain block hash to height + // index. + _, err = meta.CreateBucket(hashIndexBucketName) + if err != nil { + return err + } + + // Create the bucket that houses the chain block height to hash + // index. + _, err = meta.CreateBucket(heightIndexBucketName) + if err != nil { + return err + } + + // Create the bucket that houses the spend journal data and + // store its version. + _, err = meta.CreateBucket(spendJournalBucketName) + if err != nil { + return err + } + err = dbPutVersion(dbTx, utxoSetVersionKeyName, + latestUtxoSetBucketVersion) + if err != nil { + return err + } + + // Create the bucket that houses the utxo set and store its + // version. Note that the genesis block coinbase transaction is + // intentionally not inserted here since it is not spendable by + // consensus rules. + _, err = meta.CreateBucket(utxoSetBucketName) + if err != nil { + return err + } + err = dbPutVersion(dbTx, spendJournalVersionKeyName, + latestSpendJournalBucketVersion) + if err != nil { + return err + } + + // Save the genesis block to the block index database. + err = dbStoreBlockNode(dbTx, node) + if err != nil { + return err + } + + // Add the genesis block hash to height and height to hash + // mappings to the index. + err = dbPutBlockIndex(dbTx, &node.hash, node.height) + if err != nil { + return err + } + + // Store the current best chain state into the database. + err = dbPutBestState(dbTx, b.stateSnapshot, node.workSum) + if err != nil { + return err + } + + // Store the genesis block into the database. + return dbStoreBlock(dbTx, genesisBlock) + }) + return err +} + +// initChainState attempts to load and initialize the chain state from the +// database. When the db does not yet contain any chain state, both it and the +// chain state are initialized to the genesis block. +func (b *BlockChain) initChainState() error { + // Determine the state of the chain database. We may need to initialize + // everything from scratch or upgrade certain buckets. + var initialized, hasBlockIndex bool + err := b.db.View(func(dbTx database.Tx) error { + initialized = dbTx.Metadata().Get(chainStateKeyName) != nil + hasBlockIndex = dbTx.Metadata().Bucket(blockIndexBucketName) != nil + return nil + }) + if err != nil { + return err + } + + if !initialized { + // At this point the database has not already been initialized, so + // initialize both it and the chain state to the genesis block. + return b.createChainState() + } + + if !hasBlockIndex { + err := migrateBlockIndex(b.db) + if err != nil { + return nil + } + } + + // Attempt to load the chain state from the database. + err = b.db.View(func(dbTx database.Tx) error { + // Fetch the stored chain state from the database metadata. + // When it doesn't exist, it means the database hasn't been + // initialized for use with chain yet, so break out now to allow + // that to happen under a writable database transaction. + serializedData := dbTx.Metadata().Get(chainStateKeyName) + log.Tracef("Serialized chain state: %x", serializedData) + state, err := deserializeBestChainState(serializedData) + if err != nil { + return err + } + + // Load all of the headers from the data for the known best + // chain and construct the block index accordingly. Since the + // number of nodes are already known, perform a single alloc + // for them versus a whole bunch of little ones to reduce + // pressure on the GC. + log.Infof("Loading block index...") + + blockIndexBucket := dbTx.Metadata().Bucket(blockIndexBucketName) + + // Determine how many blocks will be loaded into the index so we can + // allocate the right amount. + var blockCount int32 + cursor := blockIndexBucket.Cursor() + for ok := cursor.First(); ok; ok = cursor.Next() { + blockCount++ + } + blockNodes := make([]blockNode, blockCount) + + var i int32 + var lastNode *blockNode + cursor = blockIndexBucket.Cursor() + for ok := cursor.First(); ok; ok = cursor.Next() { + header, status, err := deserializeBlockRow(cursor.Value()) + if err != nil { + return err + } + + // Determine the parent block node. Since we iterate block headers + // in order of height, if the blocks are mostly linear there is a + // very good chance the previous header processed is the parent. + var parent *blockNode + if lastNode == nil { + blockHash := header.BlockHash() + if !blockHash.IsEqual(b.chainParams.GenesisHash) { + return AssertError(fmt.Sprintf("initChainState: Expected "+ + "first entry in block index to be genesis block, "+ + "found %s", blockHash)) + } + } else if header.PrevBlock == lastNode.hash { + // Since we iterate block headers in order of height, if the + // blocks are mostly linear there is a very good chance the + // previous header processed is the parent. + parent = lastNode + } else { + parent = b.index.LookupNode(&header.PrevBlock) + if parent == nil { + return AssertError(fmt.Sprintf("initChainState: Could "+ + "not find parent for block %s", header.BlockHash())) + } + } + + // Initialize the block node for the block, connect it, + // and add it to the block index. + node := &blockNodes[i] + initBlockNode(node, header, parent) + node.status = status + b.index.addNode(node) + + lastNode = node + i++ + } + + // Set the best chain view to the stored best state. + tip := b.index.LookupNode(&state.hash) + if tip == nil { + return AssertError(fmt.Sprintf("initChainState: cannot find "+ + "chain tip %s in block index", state.hash)) + } + b.bestChain.SetTip(tip) + + // Load the raw block bytes for the best block. + blockBytes, err := dbTx.FetchBlock(&state.hash) + if err != nil { + return err + } + var block wire.MsgBlock + err = block.Deserialize(bytes.NewReader(blockBytes)) + if err != nil { + return err + } + + // As a final consistency check, we'll run through all the + // nodes which are ancestors of the current chain tip, and mark + // them as valid if they aren't already marked as such. This + // is a safe assumption as all the block before the current tip + // are valid by definition. + for iterNode := tip; iterNode != nil; iterNode = iterNode.parent { + // If this isn't already marked as valid in the index, then + // we'll mark it as valid now to ensure consistency once + // we're up and running. + if !iterNode.status.KnownValid() { + log.Infof("Block %v (height=%v) ancestor of "+ + "chain tip not marked as valid, "+ + "upgrading to valid for consistency", + iterNode.hash, iterNode.height) + + b.index.SetStatusFlags(iterNode, statusValid) + } + } + + // Initialize the state related to the best block. + blockSize := uint64(len(blockBytes)) + blockWeight := uint64(GetBlockWeight(btcutil.NewBlock(&block))) + numTxns := uint64(len(block.Transactions)) + b.stateSnapshot = newBestState(tip, blockSize, blockWeight, + numTxns, state.totalTxns, tip.CalcPastMedianTime()) + + return nil + }) + if err != nil { + return err + } + + // As we might have updated the index after it was loaded, we'll + // attempt to flush the index to the DB. This will only result in a + // write if the elements are dirty, so it'll usually be a noop. + return b.index.flushToDB() +} + +// deserializeBlockRow parses a value in the block index bucket into a block +// header and block status bitfield. +func deserializeBlockRow(blockRow []byte) (*wire.BlockHeader, blockStatus, error) { + buffer := bytes.NewReader(blockRow) + + var header wire.BlockHeader + err := header.Deserialize(buffer) + if err != nil { + return nil, statusNone, err + } + + statusByte, err := buffer.ReadByte() + if err != nil { + return nil, statusNone, err + } + + return &header, blockStatus(statusByte), nil +} + +// dbFetchHeaderByHash uses an existing database transaction to retrieve the +// block header for the provided hash. +func dbFetchHeaderByHash(dbTx database.Tx, hash *chainhash.Hash) (*wire.BlockHeader, error) { + headerBytes, err := dbTx.FetchBlockHeader(hash) + if err != nil { + return nil, err + } + + var header wire.BlockHeader + err = header.Deserialize(bytes.NewReader(headerBytes)) + if err != nil { + return nil, err + } + + return &header, nil +} + +// dbFetchHeaderByHeight uses an existing database transaction to retrieve the +// block header for the provided height. +func dbFetchHeaderByHeight(dbTx database.Tx, height int32) (*wire.BlockHeader, error) { + hash, err := dbFetchHashByHeight(dbTx, height) + if err != nil { + return nil, err + } + + return dbFetchHeaderByHash(dbTx, hash) +} + +// dbFetchBlockByNode uses an existing database transaction to retrieve the +// raw block for the provided node, deserialize it, and return a btcutil.Block +// with the height set. +func dbFetchBlockByNode(dbTx database.Tx, node *blockNode) (*btcutil.Block, error) { + // Load the raw block bytes from the database. + blockBytes, err := dbTx.FetchBlock(&node.hash) + if err != nil { + return nil, err + } + + // Create the encapsulated block and set the height appropriately. + block, err := btcutil.NewBlockFromBytes(blockBytes) + if err != nil { + return nil, err + } + block.SetHeight(node.height) + + return block, nil +} + +// dbStoreBlockNode stores the block header and validation status to the block +// index bucket. This overwrites the current entry if there exists one. +func dbStoreBlockNode(dbTx database.Tx, node *blockNode) error { + // Serialize block data to be stored. + w := bytes.NewBuffer(make([]byte, 0, blockHdrSize+1)) + header := node.Header() + err := header.Serialize(w) + if err != nil { + return err + } + err = w.WriteByte(byte(node.status)) + if err != nil { + return err + } + value := w.Bytes() + + // Write block header data to block index bucket. + blockIndexBucket := dbTx.Metadata().Bucket(blockIndexBucketName) + key := blockIndexKey(&node.hash, uint32(node.height)) + return blockIndexBucket.Put(key, value) +} + +// dbStoreBlock stores the provided block in the database if it is not already +// there. The full block data is written to ffldb. +func dbStoreBlock(dbTx database.Tx, block *btcutil.Block) error { + hasBlock, err := dbTx.HasBlock(block.Hash()) + if err != nil { + return err + } + if hasBlock { + return nil + } + return dbTx.StoreBlock(block) +} + +// blockIndexKey generates the binary key for an entry in the block index +// bucket. The key is composed of the block height encoded as a big-endian +// 32-bit unsigned int followed by the 32 byte block hash. +func blockIndexKey(blockHash *chainhash.Hash, blockHeight uint32) []byte { + indexKey := make([]byte, chainhash.HashSize+4) + binary.BigEndian.PutUint32(indexKey[0:4], blockHeight) + copy(indexKey[4:chainhash.HashSize+4], blockHash[:]) + return indexKey +} + +// BlockByHeight returns the block at the given height in the main chain. +// +// This function is safe for concurrent access. +func (b *BlockChain) BlockByHeight(blockHeight int32) (*btcutil.Block, error) { + // Lookup the block height in the best chain. + node := b.bestChain.NodeByHeight(blockHeight) + if node == nil { + str := fmt.Sprintf("no block at height %d exists", blockHeight) + return nil, errNotInMainChain(str) + } + + // Load the block from the database and return it. + var block *btcutil.Block + err := b.db.View(func(dbTx database.Tx) error { + var err error + block, err = dbFetchBlockByNode(dbTx, node) + return err + }) + return block, err +} + +// BlockByHash returns the block from the main chain with the given hash with +// the appropriate chain height set. +// +// This function is safe for concurrent access. +func (b *BlockChain) BlockByHash(hash *chainhash.Hash) (*btcutil.Block, error) { + // Lookup the block hash in block index and ensure it is in the best + // chain. + node := b.index.LookupNode(hash) + if node == nil || !b.bestChain.Contains(node) { + str := fmt.Sprintf("block %s is not in the main chain", hash) + return nil, errNotInMainChain(str) + } + + // Load the block from the database and return it. + var block *btcutil.Block + err := b.db.View(func(dbTx database.Tx) error { + var err error + block, err = dbFetchBlockByNode(dbTx, node) + return err + }) + return block, err +} diff --git a/vendor/github.com/btcsuite/btcd/blockchain/chainview.go b/vendor/github.com/btcsuite/btcd/blockchain/chainview.go new file mode 100644 index 0000000..a4c3692 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/blockchain/chainview.go @@ -0,0 +1,423 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "sync" +) + +// approxNodesPerWeek is an approximation of the number of new blocks there are +// in a week on average. +const approxNodesPerWeek = 6 * 24 * 7 + +// log2FloorMasks defines the masks to use when quickly calculating +// floor(log2(x)) in a constant log2(32) = 5 steps, where x is a uint32, using +// shifts. They are derived from (2^(2^x) - 1) * (2^(2^x)), for x in 4..0. +var log2FloorMasks = []uint32{0xffff0000, 0xff00, 0xf0, 0xc, 0x2} + +// fastLog2Floor calculates and returns floor(log2(x)) in a constant 5 steps. +func fastLog2Floor(n uint32) uint8 { + rv := uint8(0) + exponent := uint8(16) + for i := 0; i < 5; i++ { + if n&log2FloorMasks[i] != 0 { + rv += exponent + n >>= exponent + } + exponent >>= 1 + } + return rv +} + +// chainView provides a flat view of a specific branch of the block chain from +// its tip back to the genesis block and provides various convenience functions +// for comparing chains. +// +// For example, assume a block chain with a side chain as depicted below: +// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 +// \-> 4a -> 5a -> 6a +// +// The chain view for the branch ending in 6a consists of: +// genesis -> 1 -> 2 -> 3 -> 4a -> 5a -> 6a +type chainView struct { + mtx sync.Mutex + nodes []*blockNode +} + +// newChainView returns a new chain view for the given tip block node. Passing +// nil as the tip will result in a chain view that is not initialized. The tip +// can be updated at any time via the setTip function. +func newChainView(tip *blockNode) *chainView { + // The mutex is intentionally not held since this is a constructor. + var c chainView + c.setTip(tip) + return &c +} + +// genesis returns the genesis block for the chain view. This only differs from +// the exported version in that it is up to the caller to ensure the lock is +// held. +// +// This function MUST be called with the view mutex locked (for reads). +func (c *chainView) genesis() *blockNode { + if len(c.nodes) == 0 { + return nil + } + + return c.nodes[0] +} + +// Genesis returns the genesis block for the chain view. +// +// This function is safe for concurrent access. +func (c *chainView) Genesis() *blockNode { + c.mtx.Lock() + genesis := c.genesis() + c.mtx.Unlock() + return genesis +} + +// tip returns the current tip block node for the chain view. It will return +// nil if there is no tip. This only differs from the exported version in that +// it is up to the caller to ensure the lock is held. +// +// This function MUST be called with the view mutex locked (for reads). +func (c *chainView) tip() *blockNode { + if len(c.nodes) == 0 { + return nil + } + + return c.nodes[len(c.nodes)-1] +} + +// Tip returns the current tip block node for the chain view. It will return +// nil if there is no tip. +// +// This function is safe for concurrent access. +func (c *chainView) Tip() *blockNode { + c.mtx.Lock() + tip := c.tip() + c.mtx.Unlock() + return tip +} + +// setTip sets the chain view to use the provided block node as the current tip +// and ensures the view is consistent by populating it with the nodes obtained +// by walking backwards all the way to genesis block as necessary. Further +// calls will only perform the minimum work needed, so switching between chain +// tips is efficient. This only differs from the exported version in that it is +// up to the caller to ensure the lock is held. +// +// This function MUST be called with the view mutex locked (for writes). +func (c *chainView) setTip(node *blockNode) { + if node == nil { + // Keep the backing array around for potential future use. + c.nodes = c.nodes[:0] + return + } + + // Create or resize the slice that will hold the block nodes to the + // provided tip height. When creating the slice, it is created with + // some additional capacity for the underlying array as append would do + // in order to reduce overhead when extending the chain later. As long + // as the underlying array already has enough capacity, simply expand or + // contract the slice accordingly. The additional capacity is chosen + // such that the array should only have to be extended about once a + // week. + needed := node.height + 1 + if int32(cap(c.nodes)) < needed { + nodes := make([]*blockNode, needed, needed+approxNodesPerWeek) + copy(nodes, c.nodes) + c.nodes = nodes + } else { + prevLen := int32(len(c.nodes)) + c.nodes = c.nodes[0:needed] + for i := prevLen; i < needed; i++ { + c.nodes[i] = nil + } + } + + for node != nil && c.nodes[node.height] != node { + c.nodes[node.height] = node + node = node.parent + } +} + +// SetTip sets the chain view to use the provided block node as the current tip +// and ensures the view is consistent by populating it with the nodes obtained +// by walking backwards all the way to genesis block as necessary. Further +// calls will only perform the minimum work needed, so switching between chain +// tips is efficient. +// +// This function is safe for concurrent access. +func (c *chainView) SetTip(node *blockNode) { + c.mtx.Lock() + c.setTip(node) + c.mtx.Unlock() +} + +// height returns the height of the tip of the chain view. It will return -1 if +// there is no tip (which only happens if the chain view has not been +// initialized). This only differs from the exported version in that it is up +// to the caller to ensure the lock is held. +// +// This function MUST be called with the view mutex locked (for reads). +func (c *chainView) height() int32 { + return int32(len(c.nodes) - 1) +} + +// Height returns the height of the tip of the chain view. It will return -1 if +// there is no tip (which only happens if the chain view has not been +// initialized). +// +// This function is safe for concurrent access. +func (c *chainView) Height() int32 { + c.mtx.Lock() + height := c.height() + c.mtx.Unlock() + return height +} + +// nodeByHeight returns the block node at the specified height. Nil will be +// returned if the height does not exist. This only differs from the exported +// version in that it is up to the caller to ensure the lock is held. +// +// This function MUST be called with the view mutex locked (for reads). +func (c *chainView) nodeByHeight(height int32) *blockNode { + if height < 0 || height >= int32(len(c.nodes)) { + return nil + } + + return c.nodes[height] +} + +// NodeByHeight returns the block node at the specified height. Nil will be +// returned if the height does not exist. +// +// This function is safe for concurrent access. +func (c *chainView) NodeByHeight(height int32) *blockNode { + c.mtx.Lock() + node := c.nodeByHeight(height) + c.mtx.Unlock() + return node +} + +// Equals returns whether or not two chain views are the same. Uninitialized +// views (tip set to nil) are considered equal. +// +// This function is safe for concurrent access. +func (c *chainView) Equals(other *chainView) bool { + c.mtx.Lock() + other.mtx.Lock() + equals := len(c.nodes) == len(other.nodes) && c.tip() == other.tip() + other.mtx.Unlock() + c.mtx.Unlock() + return equals +} + +// contains returns whether or not the chain view contains the passed block +// node. This only differs from the exported version in that it is up to the +// caller to ensure the lock is held. +// +// This function MUST be called with the view mutex locked (for reads). +func (c *chainView) contains(node *blockNode) bool { + return c.nodeByHeight(node.height) == node +} + +// Contains returns whether or not the chain view contains the passed block +// node. +// +// This function is safe for concurrent access. +func (c *chainView) Contains(node *blockNode) bool { + c.mtx.Lock() + contains := c.contains(node) + c.mtx.Unlock() + return contains +} + +// next returns the successor to the provided node for the chain view. It will +// return nil if there is no successor or the provided node is not part of the +// view. This only differs from the exported version in that it is up to the +// caller to ensure the lock is held. +// +// See the comment on the exported function for more details. +// +// This function MUST be called with the view mutex locked (for reads). +func (c *chainView) next(node *blockNode) *blockNode { + if node == nil || !c.contains(node) { + return nil + } + + return c.nodeByHeight(node.height + 1) +} + +// Next returns the successor to the provided node for the chain view. It will +// return nil if there is no successfor or the provided node is not part of the +// view. +// +// For example, assume a block chain with a side chain as depicted below: +// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 +// \-> 4a -> 5a -> 6a +// +// Further, assume the view is for the longer chain depicted above. That is to +// say it consists of: +// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 +// +// Invoking this function with block node 5 would return block node 6 while +// invoking it with block node 5a would return nil since that node is not part +// of the view. +// +// This function is safe for concurrent access. +func (c *chainView) Next(node *blockNode) *blockNode { + c.mtx.Lock() + next := c.next(node) + c.mtx.Unlock() + return next +} + +// findFork returns the final common block between the provided node and the +// the chain view. It will return nil if there is no common block. This only +// differs from the exported version in that it is up to the caller to ensure +// the lock is held. +// +// See the exported FindFork comments for more details. +// +// This function MUST be called with the view mutex locked (for reads). +func (c *chainView) findFork(node *blockNode) *blockNode { + // No fork point for node that doesn't exist. + if node == nil { + return nil + } + + // When the height of the passed node is higher than the height of the + // tip of the current chain view, walk backwards through the nodes of + // the other chain until the heights match (or there or no more nodes in + // which case there is no common node between the two). + // + // NOTE: This isn't strictly necessary as the following section will + // find the node as well, however, it is more efficient to avoid the + // contains check since it is already known that the common node can't + // possibly be past the end of the current chain view. It also allows + // this code to take advantage of any potential future optimizations to + // the Ancestor function such as using an O(log n) skip list. + chainHeight := c.height() + if node.height > chainHeight { + node = node.Ancestor(chainHeight) + } + + // Walk the other chain backwards as long as the current one does not + // contain the node or there are no more nodes in which case there is no + // common node between the two. + for node != nil && !c.contains(node) { + node = node.parent + } + + return node +} + +// FindFork returns the final common block between the provided node and the +// the chain view. It will return nil if there is no common block. +// +// For example, assume a block chain with a side chain as depicted below: +// genesis -> 1 -> 2 -> ... -> 5 -> 6 -> 7 -> 8 +// \-> 6a -> 7a +// +// Further, assume the view is for the longer chain depicted above. That is to +// say it consists of: +// genesis -> 1 -> 2 -> ... -> 5 -> 6 -> 7 -> 8. +// +// Invoking this function with block node 7a would return block node 5 while +// invoking it with block node 7 would return itself since it is already part of +// the branch formed by the view. +// +// This function is safe for concurrent access. +func (c *chainView) FindFork(node *blockNode) *blockNode { + c.mtx.Lock() + fork := c.findFork(node) + c.mtx.Unlock() + return fork +} + +// blockLocator returns a block locator for the passed block node. The passed +// node can be nil in which case the block locator for the current tip +// associated with the view will be returned. This only differs from the +// exported version in that it is up to the caller to ensure the lock is held. +// +// See the exported BlockLocator function comments for more details. +// +// This function MUST be called with the view mutex locked (for reads). +func (c *chainView) blockLocator(node *blockNode) BlockLocator { + // Use the current tip if requested. + if node == nil { + node = c.tip() + } + if node == nil { + return nil + } + + // Calculate the max number of entries that will ultimately be in the + // block locator. See the description of the algorithm for how these + // numbers are derived. + var maxEntries uint8 + if node.height <= 12 { + maxEntries = uint8(node.height) + 1 + } else { + // Requested hash itself + previous 10 entries + genesis block. + // Then floor(log2(height-10)) entries for the skip portion. + adjustedHeight := uint32(node.height) - 10 + maxEntries = 12 + fastLog2Floor(adjustedHeight) + } + locator := make(BlockLocator, 0, maxEntries) + + step := int32(1) + for node != nil { + locator = append(locator, &node.hash) + + // Nothing more to add once the genesis block has been added. + if node.height == 0 { + break + } + + // Calculate height of previous node to include ensuring the + // final node is the genesis block. + height := node.height - step + if height < 0 { + height = 0 + } + + // When the node is in the current chain view, all of its + // ancestors must be too, so use a much faster O(1) lookup in + // that case. Otherwise, fall back to walking backwards through + // the nodes of the other chain to the correct ancestor. + if c.contains(node) { + node = c.nodes[height] + } else { + node = node.Ancestor(height) + } + + // Once 11 entries have been included, start doubling the + // distance between included hashes. + if len(locator) > 10 { + step *= 2 + } + } + + return locator +} + +// BlockLocator returns a block locator for the passed block node. The passed +// node can be nil in which case the block locator for the current tip +// associated with the view will be returned. +// +// See the BlockLocator type for details on the algorithm used to create a block +// locator. +// +// This function is safe for concurrent access. +func (c *chainView) BlockLocator(node *blockNode) BlockLocator { + c.mtx.Lock() + locator := c.blockLocator(node) + c.mtx.Unlock() + return locator +} diff --git a/vendor/github.com/btcsuite/btcd/blockchain/checkpoints.go b/vendor/github.com/btcsuite/btcd/blockchain/checkpoints.go new file mode 100644 index 0000000..af3b6d9 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/blockchain/checkpoints.go @@ -0,0 +1,261 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "fmt" + "time" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcutil" +) + +// CheckpointConfirmations is the number of blocks before the end of the current +// best block chain that a good checkpoint candidate must be. +const CheckpointConfirmations = 2016 + +// newHashFromStr converts the passed big-endian hex string into a +// chainhash.Hash. It only differs from the one available in chainhash in that +// it ignores the error since it will only (and must only) be called with +// hard-coded, and therefore known good, hashes. +func newHashFromStr(hexStr string) *chainhash.Hash { + hash, _ := chainhash.NewHashFromStr(hexStr) + return hash +} + +// Checkpoints returns a slice of checkpoints (regardless of whether they are +// already known). When there are no checkpoints for the chain, it will return +// nil. +// +// This function is safe for concurrent access. +func (b *BlockChain) Checkpoints() []chaincfg.Checkpoint { + return b.checkpoints +} + +// HasCheckpoints returns whether this BlockChain has checkpoints defined. +// +// This function is safe for concurrent access. +func (b *BlockChain) HasCheckpoints() bool { + return len(b.checkpoints) > 0 +} + +// LatestCheckpoint returns the most recent checkpoint (regardless of whether it +// is already known). When there are no defined checkpoints for the active chain +// instance, it will return nil. +// +// This function is safe for concurrent access. +func (b *BlockChain) LatestCheckpoint() *chaincfg.Checkpoint { + if !b.HasCheckpoints() { + return nil + } + return &b.checkpoints[len(b.checkpoints)-1] +} + +// verifyCheckpoint returns whether the passed block height and hash combination +// match the checkpoint data. It also returns true if there is no checkpoint +// data for the passed block height. +func (b *BlockChain) verifyCheckpoint(height int32, hash *chainhash.Hash) bool { + if !b.HasCheckpoints() { + return true + } + + // Nothing to check if there is no checkpoint data for the block height. + checkpoint, exists := b.checkpointsByHeight[height] + if !exists { + return true + } + + if !checkpoint.Hash.IsEqual(hash) { + return false + } + + log.Infof("Verified checkpoint at height %d/block %s", checkpoint.Height, + checkpoint.Hash) + return true +} + +// findPreviousCheckpoint finds the most recent checkpoint that is already +// available in the downloaded portion of the block chain and returns the +// associated block node. It returns nil if a checkpoint can't be found (this +// should really only happen for blocks before the first checkpoint). +// +// This function MUST be called with the chain lock held (for reads). +func (b *BlockChain) findPreviousCheckpoint() (*blockNode, error) { + if !b.HasCheckpoints() { + return nil, nil + } + + // Perform the initial search to find and cache the latest known + // checkpoint if the best chain is not known yet or we haven't already + // previously searched. + checkpoints := b.checkpoints + numCheckpoints := len(checkpoints) + if b.checkpointNode == nil && b.nextCheckpoint == nil { + // Loop backwards through the available checkpoints to find one + // that is already available. + for i := numCheckpoints - 1; i >= 0; i-- { + node := b.index.LookupNode(checkpoints[i].Hash) + if node == nil || !b.bestChain.Contains(node) { + continue + } + + // Checkpoint found. Cache it for future lookups and + // set the next expected checkpoint accordingly. + b.checkpointNode = node + if i < numCheckpoints-1 { + b.nextCheckpoint = &checkpoints[i+1] + } + return b.checkpointNode, nil + } + + // No known latest checkpoint. This will only happen on blocks + // before the first known checkpoint. So, set the next expected + // checkpoint to the first checkpoint and return the fact there + // is no latest known checkpoint block. + b.nextCheckpoint = &checkpoints[0] + return nil, nil + } + + // At this point we've already searched for the latest known checkpoint, + // so when there is no next checkpoint, the current checkpoint lockin + // will always be the latest known checkpoint. + if b.nextCheckpoint == nil { + return b.checkpointNode, nil + } + + // When there is a next checkpoint and the height of the current best + // chain does not exceed it, the current checkpoint lockin is still + // the latest known checkpoint. + if b.bestChain.Tip().height < b.nextCheckpoint.Height { + return b.checkpointNode, nil + } + + // We've reached or exceeded the next checkpoint height. Note that + // once a checkpoint lockin has been reached, forks are prevented from + // any blocks before the checkpoint, so we don't have to worry about the + // checkpoint going away out from under us due to a chain reorganize. + + // Cache the latest known checkpoint for future lookups. Note that if + // this lookup fails something is very wrong since the chain has already + // passed the checkpoint which was verified as accurate before inserting + // it. + checkpointNode := b.index.LookupNode(b.nextCheckpoint.Hash) + if checkpointNode == nil { + return nil, AssertError(fmt.Sprintf("findPreviousCheckpoint "+ + "failed lookup of known good block node %s", + b.nextCheckpoint.Hash)) + } + b.checkpointNode = checkpointNode + + // Set the next expected checkpoint. + checkpointIndex := -1 + for i := numCheckpoints - 1; i >= 0; i-- { + if checkpoints[i].Hash.IsEqual(b.nextCheckpoint.Hash) { + checkpointIndex = i + break + } + } + b.nextCheckpoint = nil + if checkpointIndex != -1 && checkpointIndex < numCheckpoints-1 { + b.nextCheckpoint = &checkpoints[checkpointIndex+1] + } + + return b.checkpointNode, nil +} + +// isNonstandardTransaction determines whether a transaction contains any +// scripts which are not one of the standard types. +func isNonstandardTransaction(tx *btcutil.Tx) bool { + // Check all of the output public key scripts for non-standard scripts. + for _, txOut := range tx.MsgTx().TxOut { + scriptClass := txscript.GetScriptClass(txOut.PkScript) + if scriptClass == txscript.NonStandardTy { + return true + } + } + return false +} + +// IsCheckpointCandidate returns whether or not the passed block is a good +// checkpoint candidate. +// +// The factors used to determine a good checkpoint are: +// - The block must be in the main chain +// - The block must be at least 'CheckpointConfirmations' blocks prior to the +// current end of the main chain +// - The timestamps for the blocks before and after the checkpoint must have +// timestamps which are also before and after the checkpoint, respectively +// (due to the median time allowance this is not always the case) +// - The block must not contain any strange transaction such as those with +// nonstandard scripts +// +// The intent is that candidates are reviewed by a developer to make the final +// decision and then manually added to the list of checkpoints for a network. +// +// This function is safe for concurrent access. +func (b *BlockChain) IsCheckpointCandidate(block *btcutil.Block) (bool, error) { + b.chainLock.RLock() + defer b.chainLock.RUnlock() + + // A checkpoint must be in the main chain. + node := b.index.LookupNode(block.Hash()) + if node == nil || !b.bestChain.Contains(node) { + return false, nil + } + + // Ensure the height of the passed block and the entry for the block in + // the main chain match. This should always be the case unless the + // caller provided an invalid block. + if node.height != block.Height() { + return false, fmt.Errorf("passed block height of %d does not "+ + "match the main chain height of %d", block.Height(), + node.height) + } + + // A checkpoint must be at least CheckpointConfirmations blocks + // before the end of the main chain. + mainChainHeight := b.bestChain.Tip().height + if node.height > (mainChainHeight - CheckpointConfirmations) { + return false, nil + } + + // A checkpoint must be have at least one block after it. + // + // This should always succeed since the check above already made sure it + // is CheckpointConfirmations back, but be safe in case the constant + // changes. + nextNode := b.bestChain.Next(node) + if nextNode == nil { + return false, nil + } + + // A checkpoint must be have at least one block before it. + if node.parent == nil { + return false, nil + } + + // A checkpoint must have timestamps for the block and the blocks on + // either side of it in order (due to the median time allowance this is + // not always the case). + prevTime := time.Unix(node.parent.timestamp, 0) + curTime := block.MsgBlock().Header.Timestamp + nextTime := time.Unix(nextNode.timestamp, 0) + if prevTime.After(curTime) || nextTime.Before(curTime) { + return false, nil + } + + // A checkpoint must have transactions that only contain standard + // scripts. + for _, tx := range block.Transactions() { + if isNonstandardTransaction(tx) { + return false, nil + } + } + + // All of the checks passed, so the block is a candidate. + return true, nil +} diff --git a/vendor/github.com/btcsuite/btcd/blockchain/compress.go b/vendor/github.com/btcsuite/btcd/blockchain/compress.go new file mode 100644 index 0000000..611b9f0 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/blockchain/compress.go @@ -0,0 +1,586 @@ +// Copyright (c) 2015-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/txscript" +) + +// ----------------------------------------------------------------------------- +// A variable length quantity (VLQ) is an encoding that uses an arbitrary number +// of binary octets to represent an arbitrarily large integer. The scheme +// employs a most significant byte (MSB) base-128 encoding where the high bit in +// each byte indicates whether or not the byte is the final one. In addition, +// to ensure there are no redundant encodings, an offset is subtracted every +// time a group of 7 bits is shifted out. Therefore each integer can be +// represented in exactly one way, and each representation stands for exactly +// one integer. +// +// Another nice property of this encoding is that it provides a compact +// representation of values that are typically used to indicate sizes. For +// example, the values 0 - 127 are represented with a single byte, 128 - 16511 +// with two bytes, and 16512 - 2113663 with three bytes. +// +// While the encoding allows arbitrarily large integers, it is artificially +// limited in this code to an unsigned 64-bit integer for efficiency purposes. +// +// Example encodings: +// 0 -> [0x00] +// 127 -> [0x7f] * Max 1-byte value +// 128 -> [0x80 0x00] +// 129 -> [0x80 0x01] +// 255 -> [0x80 0x7f] +// 256 -> [0x81 0x00] +// 16511 -> [0xff 0x7f] * Max 2-byte value +// 16512 -> [0x80 0x80 0x00] +// 32895 -> [0x80 0xff 0x7f] +// 2113663 -> [0xff 0xff 0x7f] * Max 3-byte value +// 270549119 -> [0xff 0xff 0xff 0x7f] * Max 4-byte value +// 2^64-1 -> [0x80 0xfe 0xfe 0xfe 0xfe 0xfe 0xfe 0xfe 0xfe 0x7f] +// +// References: +// https://en.wikipedia.org/wiki/Variable-length_quantity +// http://www.codecodex.com/wiki/Variable-Length_Integers +// ----------------------------------------------------------------------------- + +// serializeSizeVLQ returns the number of bytes it would take to serialize the +// passed number as a variable-length quantity according to the format described +// above. +func serializeSizeVLQ(n uint64) int { + size := 1 + for ; n > 0x7f; n = (n >> 7) - 1 { + size++ + } + + return size +} + +// putVLQ serializes the provided number to a variable-length quantity according +// to the format described above and returns the number of bytes of the encoded +// value. The result is placed directly into the passed byte slice which must +// be at least large enough to handle the number of bytes returned by the +// serializeSizeVLQ function or it will panic. +func putVLQ(target []byte, n uint64) int { + offset := 0 + for ; ; offset++ { + // The high bit is set when another byte follows. + highBitMask := byte(0x80) + if offset == 0 { + highBitMask = 0x00 + } + + target[offset] = byte(n&0x7f) | highBitMask + if n <= 0x7f { + break + } + n = (n >> 7) - 1 + } + + // Reverse the bytes so it is MSB-encoded. + for i, j := 0, offset; i < j; i, j = i+1, j-1 { + target[i], target[j] = target[j], target[i] + } + + return offset + 1 +} + +// deserializeVLQ deserializes the provided variable-length quantity according +// to the format described above. It also returns the number of bytes +// deserialized. +func deserializeVLQ(serialized []byte) (uint64, int) { + var n uint64 + var size int + for _, val := range serialized { + size++ + n = (n << 7) | uint64(val&0x7f) + if val&0x80 != 0x80 { + break + } + n++ + } + + return n, size +} + +// ----------------------------------------------------------------------------- +// In order to reduce the size of stored scripts, a domain specific compression +// algorithm is used which recognizes standard scripts and stores them using +// less bytes than the original script. The compression algorithm used here was +// obtained from Bitcoin Core, so all credits for the algorithm go to it. +// +// The general serialized format is: +// +//