Add 1.9.4 website, add 1.9.4 release notes (#4726)

* Add 1.9.4 website, add 1.9.4 release notes

* Add versioned sidebars

* Bump more versions to 1.9.4

* update release notes
This commit is contained in:
Chris Stewart 2022-09-12 08:19:28 -05:00 committed by GitHub
parent 2d83210ba3
commit 0cfad33fae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1502 additions and 27 deletions

View file

@ -1,6 +1,5 @@
![Bitcoin-S logo](website/static/img/bitcoin-s-dark-logo.png)
[![Build Status](https://github.com/bitcoin-s/bitcoin-s/workflows/Release/badge.svg)](https://github.com/bitcoin-s/bitcoin-s/actions) [![Coverage Status](https://coveralls.io/repos/github/bitcoin-s/bitcoin-s/badge.svg?branch=master)](https://coveralls.io/github/bitcoin-s/bitcoin-s?branch=master) [![Maven Central](https://img.shields.io/badge/Maven%20Central-1.9.3
-brightgreen.svg)](https://mvnrepository.com/artifact/org.bitcoin-s) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/bitcoin-s-core)
[![Build Status](https://github.com/bitcoin-s/bitcoin-s/workflows/Release/badge.svg)](https://github.com/bitcoin-s/bitcoin-s/actions) [![Coverage Status](https://coveralls.io/repos/github/bitcoin-s/bitcoin-s/badge.svg?branch=master)](https://coveralls.io/github/bitcoin-s/bitcoin-s?branch=master) [![Maven Central](https://img.shields.io/badge/Maven%20Central-1.9.4-brightgreen.svg)](https://mvnrepository.com/artifact/org.bitcoin-s) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/bitcoin-s-core)
Feature-rich toolkit for making Bitcoin and Lightning applications on the JVM.
@ -44,52 +43,52 @@ This link is intended for setting up development of bitcoin-s. If you want to ju
### Adding bitcoin-s to your library
The latest release of bitcoin-s is `1.9.3`, here is how you can use the dependencies in your projects:
The latest release of bitcoin-s is `1.9.4`, here is how you can use the dependencies in your projects:
```
libraryDependencies += "org.bitcoin-s" % "bitcoin-s-secp256k1jni" % "1.9.3"
libraryDependencies += "org.bitcoin-s" % "bitcoin-s-secp256k1jni" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-core" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-core" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-crypto" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-crypto" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-chain" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-chain" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-oracle" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-oracle" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-oracle-explorer-client" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-oracle-explorer-client" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-app-commons" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-app-commons" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-db-commons" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-db-commons" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-fee-provider" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-fee-provider" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-bitcoind-rpc" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-bitcoind-rpc" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-eclair-rpc" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-eclair-rpc" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-lnd-rpc" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-lnd-rpc" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-key-manager" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-key-manager" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-node" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-node" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-node" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-node" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-wallet" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-wallet" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-wallet" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-wallet" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit-core" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit-core" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-zmq" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-zmq" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-tor" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-tor" % "1.9.4"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-cli" % "1.9.3"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-cli" % "1.9.4"
```

View file

@ -1,5 +1,5 @@
package org.bitcoins.node.constant
case object NodeConstants {
val userAgent = "/bitcoin-s:1.9.3/"
val userAgent = "/bitcoin-s:1.9.4/"
}

View file

@ -18,7 +18,7 @@ import scala.util.Properties
object CommonSettings {
val previousStableVersion: String = "1.9.3"
val previousStableVersion: String = "1.9.4"
private def isCI = {
Properties

View file

@ -0,0 +1,174 @@
# 1.9.4
This release is backwards compatible with the 1.9.x series of bitcoin-s
See the individual module sections for more information on lower level updates to the codebase.
Want to get started quickly? See our `docker-compose.yml` file. [See instructions here](https://github.com/bitcoin-s/bitcoin-s/#docker)
If you are a typescript developer, [you can access the backend via our typescript library](https://github.com/bitcoin-s/bitcoin-s-ts)
# Executive Summary
This is a bug fix release. In our 1.9.3 release we did not successfully publish all jars for the libraries.
For more information see: https://github.com/bitcoin-s/bitcoin-s/issues/4725
This release drops support for Scala 2.12.x, which fixes this bug. It also updates some dependencies.
## Running bitcoin-s
If you want to run the standalone server binary, after verifying gpg signatures, you
can `unzip bitcoin-s-server-1.9.4.zip` and then run it with `chmod +x ./bin/bitcoin-s-server && ./bin/bitcoin-s-server` to start the node. You will need to
configure the node properly first, you can find example
configurations [here](https://bitcoin-s.org/docs/config/configuration#example-configuration-file).
You can then unzip the `bitcoin-s-cli-1.9.4.zip` folder and start using the `bitcoin-s-cli` like this:
```bashrc
./bin/bitcoin-s-cli --help
Usage: bitcoin-s-cli [options] [<cmd>]
-n, --network <value> Select the active network.
--debug Print debugging information
--rpcport <value> The port to send our rpc request to on the server
-h, --help Display this help message and exit
```
For more information on what commands `bitcoin-s-cli` supports check the documentation, here is where to
start: https://bitcoin-s.org/docs/next/applications/server#server-endpoints
## Verifying signatures
This release is signed with [Chris's signing key](https://bitcoin-s.org/docs/next/security#disclosure) with
fingerprint `9234F4D6AF47C71B741A390F8976CA0AF71A7A2A`
To do the verification, first hash the executable using `sha256sum`. You should check that the result is listed in
the `SHA256SUMS.asc` file next to its file name. After doing that you can use `gpg --verify` to authenticate the
signature.
Example:
```
$ gpg -d SHA256SUMS.asc > SHA256SUMS.stripped
gpg: Signature made Mon 18 Apr 2022 02:19:54 PM CDT
gpg: using RSA key 9234F4D6AF47C71B741A390F8976CA0AF71A7A2A
gpg: Good signature from "Chris Stewart <stewart.chris1234@gmail.com>" [ultimate]
$ sha256sum -c SHA256SUMS.stripped
bitcoin-s_1.9.3-1_amd64.deb: OK
bitcoin-s-1.9.3.dmg: OK
bitcoin-s-bundle.msi: OK
bitcoin-s-cli-x86_64-apple-darwin: OK
bitcoin-s-cli-x86_64-pc-linux: OK
bitcoin-s-server-1.9.3.zip: OK
```
### Website
https://bitcoin-s.org/
### Releases
https://repo1.maven.org/maven2/org/bitcoin-s/
### Snapshot releases
https://oss.sonatype.org/content/repositories/snapshots/org/bitcoin-s/
## Contributors
# Modules
## app commons
2cfd6f3591 Allow for custom config file name (#4709)
## App server
7b7847885e Attempt to reduce redundant work on startup to speed up start up time (#4764)
7460dcd255 Parallelize running of individual migrations (#4761)
6b432ea509 Emit 2000th header received during IBD (#4719)
a36e55c892 Fix patterns I missed when updating logback (#4713)
## bitcoind rpc
0c05edd633 mask bitcoind password (#4763)
61d4882efd Implement retry of fetching bitcoind version when calling `clientF` (#4760)
## bundle
## Build
7d9d0c577f Run scalafmt (#4757)
7fe9bdbe35 re-add Compile / fork in server.sbt so we can run appServer from sbt console (#4730)
06844bcd13 Make docker publish use java 18 to avoid slick 3.4.0 issues (#4718)
d2fb3fc150 Revert "Make electron build use bitcoin-s-ts latest tag (#4701)" (#4711)
38725f0155 Make electron build use bitcoin-s-ts latest tag (#4701)
3ad43a8f86 ignore jakarta dependnecy in logback (#4707)
328e1653a9 Drop support for scalac `2.12.x` (#4704)
669eb03f93 2022 09 02 issue 4699 (#4700)
## chain
## Core
2f18f622ab Give BitcoinNetworks.knownNetworks proper type (#4766)
## Crypto
## db commons
## DLC node
16893f999e DLC connection checks and notifications (#4720)
## DLC wallet
26595ab3ac Fix bug where no exception was thrown if the acceptor did not have enough money (#4728)
## gui
## fee rate
## keymanager
## Lnd rpc
20ed1dcab0 Fix lnd default datadir (#4767)
8bbfbc89d7 Add handling so test lnd clients can be reached by docker (#4729)
1758197d58 Remove bitcoind as a dep for lnd (#4703)
## Lnurl
## node
fae1a53579 Bump `bitcoin-s.node.query-wait-time=120 seconds` (#4759)
## Oracle Explorer Client
## wallet
81cddc12df Remove checkRootAccount/downloadMissingUtxos (#4762)
2bf1c9d1a5 Try to debug what is happening on CI with zmq test (#4708)
2448fe13e8 Revert the unique outpoint index DB migration (#4652)
## testkit-core
## testkit
018a6e58ee Add [regtest] section to fixture config (#4717)
## tor
1571b85819 Bump tor timeout to 120 seconds (#4723)
## Website
## Dependencies
2d83210ba3 Update flyway-core to 9.2.3 (#4744)
12326c7f33 Update sqlite-jdbc to 3.39.3.0 (#4755)
6bfb669343 Update akka deps (#4724)
fd7bef3aa7 Try out slick 3.4.0-RC3 (#4620)
3ee4fe1138 Upgrade dependencies (#4705)

View file

@ -0,0 +1,59 @@
---
id: version-1.9.4-addresses
title: Generating Addresses
original_id: addresses
---
Almost all Bitcoin applications need to generate addresses
for their users somehow. There's a lot going on in getting
a correct bitcoin address, but our APIs make it possible to
to get started with all types of addresses in a matter of
minutes.
## Generating SegWit (bech32) addresses
Generating native SegWit addresses in the bech32 format
is something that all Bitcoin applications should enable,
as it makes the transaction fees less expensive, and also
makes the addresses more readable by humans. However, it
has seen slower than necessary adoption. With Bitcoin-S
you can generate bech32 addresses in four(!) lines of code
(not counting comments and imports), so now there's no
reason to keep using legacy transaction formats.
```scala
// this generates a random private key
val privkey = ECPrivateKey()
// privkey: ECPrivateKey = Masked(ECPrivateKey)
val pubkey = privkey.publicKey
// pubkey: org.bitcoins.crypto.ECPublicKey = ECPublicKey(02e34cdcd460cd8299fe9cafd89179c39a9e2983aa6860d95ad785c2ed18a10013)
val segwitAddress = {
// see https://bitcoin.org/en/glossary/pubkey-script
// for reading resources on the details of scriptPubKeys
// pay-to-witness-pubkey-hash scriptPubKey V0
val scriptPubKey = P2WPKHWitnessSPKV0(pubkey)
Bech32Address(scriptPubKey, TestNet3)
}
// segwitAddress: Bech32Address = tb1qfw3k6p04asktvrm7zakdq3lnh8x9a507snklww
println(segwitAddress.toString)
// tb1qfw3k6p04asktvrm7zakdq3lnh8x9a507snklww
```
## Generating legacy (base58) addresses
If you need to generate legacy addresses for backwards
compatability reasons, that's also a walk in the park.
Take a look:
```scala
// we're reusing the same private/public key pair
// from before. don't do this in an actual application!
val legacyAddress = P2PKHAddress(pubkey, TestNet3)
// legacyAddress: P2PKHAddress = mnQtkUDEUKac7cVRiCfcCvBikyUqYzgj2m
println(legacyAddress.toString)
// mnQtkUDEUKac7cVRiCfcCvBikyUqYzgj2m
```

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,145 @@
---
id: version-1.9.4-hd-keys
title: HD Key Generation
original_id: hd-keys
---
In modern Bitcoin wallets, users only need to write down
a sequence of words, and that sequence is a complete backup
of their wallet. This is thanks to what's called Hierarchical
Deterministic key generation. In short, every wallet using HD
key generation has a root seed for each wallet, and this
seed can be used to generate an arbitrary amount of later
private and public keys. This is done in a standardized manner,
so different wallets can operate with the same standard.
> If you want to jump into the details of how this work,
> you should check out
> [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki).
Bitcoin-S supports generating keys in this fashion. Here's a
full example of how to obtain a wallet seed, and then
use that to generate further private and public keys:
```scala
import scodec.bits._
import org.bitcoins.core.crypto._
import org.bitcoins.core.hd._
// the length of the entropy bit vector determine
// how long our phrase ends up being
// 256 bits of entropy results in 24 words
val entropy: BitVector = MnemonicCode.getEntropy256Bits
// entropy: BitVector = BitVector(256 bits, 0x269608303f30d6d02be81b3f2a059ddb14a61e39aff5d2d112a484b4974d43c5)
val mnemonicCode = MnemonicCode.fromEntropy(entropy)
// mnemonicCode: MnemonicCode = Masked(MnemonicCodeImpl)
mnemonicCode.words // the phrase the user should write down
// res0: Vector[String] = Vector(charge, raccoon, army, lazy, aspect, gym, quick, address, dish, expand, guess, renew, engine, audit, trade, wrong, spot, mass, powder, annual, enact, pluck, audit, peace) // the phrase the user should write down
// the password argument is an optional, extra security
// measure. all MnemonicCode instances will give you a
// valid BIP39 seed, but different passwords will give
// you different seeds. So you could have as many wallets
// from the same seed as you'd like, by simply giving them
// different passwords.
val bip39Seed = BIP39Seed.fromMnemonic(mnemonicCode,
password = "secret password")
// bip39Seed: BIP39Seed = Masked(BIP39SeedImpl)
val xpriv = ExtPrivateKey.fromBIP39Seed(ExtKeyVersion.SegWitMainNetPriv,
bip39Seed)
// xpriv: ExtPrivateKey = Masked(ExtPrivateKeyImpl)
val xpub = xpriv.extPublicKey
// xpub: ExtPublicKey = zpub6jftahH18ngZx3FovrPbtTU1x5yryL1S5f42bK9PLq5EMTPdTUFWQGpqMfaqi9kJfosg8XRuXMStaVTB9mtZfqozGYksnKgTUedMcxiTvim
// you can now use the generated xpriv to derive further
// private or public keys
// this can be done with BIP89 paths (called SegWitHDPath in bitcoin-s)
val segwitPath = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
// segwitPath: SegWitHDPath = m/84'/0'/0'/0/0
// alternatively:
val otherSegwitPath =
SegWitHDPath(HDCoinType.Bitcoin,
accountIndex = 0,
HDChainType.External,
addressIndex = 0)
// otherSegwitPath: SegWitHDPath = m/84'/0'/0'/0/0
segwitPath == otherSegwitPath
// res1: Boolean = true
```
## Generating new addresses without having access to the private key
One the coolest features of HD wallets is that it's possible
to generate addresses offline, without having access to the
private keys. This feature is commonly called watch-only
wallets, where a wallet can import information about all
your past and future transactions, without being able to
spend or steal any of your money.
Let's see an example of this:
```scala
import scala.util.Success
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.Bech32Address
import org.bitcoins.core.config.TestNet3
// first account -------┐
// bitcoin ----------┐ |
// segwit --------┐ | |
val accountPath = BIP32Path.fromString("m/84'/0'/0'")
// accountPath: BIP32Path = m/84'/0'/0'
val accountXpub = {
// this key is sensitive, keep away from prying eyes!
val accountXpriv = xpriv.deriveChildPrivKey(accountPath)
// this key is not sufficient to spend from, but we
// can generate addresses with it!
accountXpriv.extPublicKey
}
// accountXpub: ExtPublicKey = zpub6s5dzUak5UZuGtENZUvtjB89uFuhYqN9E38bB4Lp6yuR454cibJVWcsyvPYQtMyu5xeWadDWMKSPkTSD5Mye8RcU7fY7x43wvp6CrVFFJCT
// address no. 0 ---------------┐
// external address ----------┐ |
val firstAddressPath = SegWitHDPath.fromString("m/84'/0'/0'/0/0")
// firstAddressPath: SegWitHDPath = m/84'/0'/0'/0/0
val firstAccountAddress = {
// this is a bit quirky, but we're not interesting in
// deriving the complete path from our account xpub
// instead, we're only interested in the part after
// the account level (3rd level). the .diff() method
// achieves that
val Some(pathDiff) = accountPath.diff(firstAddressPath)
// deriving public keys from hardened extended keys
// is not possible, that's why .deriveChildPubKey()
// returns a Try[ExtPublicKey]. A hardened key is marked
// by a ' after the number in the notation we use above.
val Success(extPubKey) = accountXpub.deriveChildPubKey(pathDiff)
val pubkey = extPubKey.key
val scriptPubKey = P2WPKHWitnessSPKV0(pubkey)
Bech32Address(scriptPubKey, TestNet3)
}
// firstAccountAddress: Bech32Address = tb1q3askd35zqpt9vszkvvffxkdsycn3sky2pqz54c
// tada! We just generated an address you can send money to,
// without having access to the private key!
firstAccountAddress.value
// res2: String = tb1q3askd35zqpt9vszkvvffxkdsycn3sky2pqz54c
// you can now continue deriving addresses from the same public
// key, by imitating what we did above. To get the next
// HD path to generate an address at:
val nextAddressPath: SegWitHDPath = firstAddressPath.next
// nextAddressPath: SegWitHDPath = m/84'/0'/0'/0/1
```
### Signing things with HD keys
Please see [sign.md](../crypto/sign.md) for information on how to sign things with HD keys.

View file

@ -0,0 +1,158 @@
---
id: version-1.9.4-txbuilder
title: TxBuilder Example
original_id: txbuilder
---
Bitcoin-S features a transaction building API that allows you to construct and sign Bitcoin transactions. Here's an example of how to use it
```scala
implicit val ec: ExecutionContext = ExecutionContext.Implicits.global
// ec: ExecutionContext = scala.concurrent.impl.ExecutionContextImpl$$anon$3@6497e290[Running, parallelism = 16, size = 0, active = 0, running = 0, steals = 493, tasks = 0, submissions = 0]
// Initialize a transaction builder
val builder = RawTxBuilder()
// builder: RawTxBuilder = RawTxBuilder()
// generate a fresh private key that we are going to use in the scriptpubkey
val privKey = ECPrivateKey.freshPrivateKey
// privKey: ECPrivateKey = Masked(ECPrivateKey)
val pubKey = privKey.publicKey
// pubKey: ECPublicKey = ECPublicKey(038839cc58d1e077d426f550d13c0dc5bff744f749e4ea17f9c186ceb4e11ad130)
// this is the script that the TxBuilder is going to create a
// script signature that validly spends this scriptPubKey
val creditingSpk = P2PKHScriptPubKey(pubKey = privKey.publicKey)
// creditingSpk: P2PKHScriptPubKey = pkh(0ba1ff18b17397b9487188bf22c6b9f877d7831f)
val amount = 10000.satoshis
// amount: Satoshis = 10000 sats
// this is the UTXO we are going to be spending
val utxo =
TransactionOutput(value = amount, scriptPubKey = creditingSpk)
// utxo: TransactionOutput = TransactionOutput(10000 sats,pkh(0ba1ff18b17397b9487188bf22c6b9f877d7831f))
// the private key that locks the funds for the script we are spending too
val destinationPrivKey = ECPrivateKey.freshPrivateKey
// destinationPrivKey: ECPrivateKey = Masked(ECPrivateKey)
// the amount we are sending -- 5000 satoshis -- to the destinationSPK
val destinationAmount = 5000.satoshis
// destinationAmount: Satoshis = 5000 sats
// the script that corresponds to destination private key, this is what is receiving the money
val destinationSPK =
P2PKHScriptPubKey(pubKey = destinationPrivKey.publicKey)
// destinationSPK: P2PKHScriptPubKey = pkh(18bb8fe332dbabfad38ead5e200802da2470eb73)
// this is where we are sending money too
// we could add more destinations here if we
// wanted to batch transactions
val destinations = {
val destination0 = TransactionOutput(value = destinationAmount,
scriptPubKey = destinationSPK)
Vector(destination0)
}
// destinations: Vector[TransactionOutput] = Vector(TransactionOutput(5000 sats,pkh(18bb8fe332dbabfad38ead5e200802da2470eb73)))
// Add the destinations to the tx builder
builder ++= destinations
// res0: RawTxBuilder = RawTxBuilder()
// we have to fabricate a transaction that contains the
// UTXO we are trying to spend. If this were a real blockchain
// we would need to reference the UTXO set
val creditingTx = BaseTransaction(version = Int32.one,
inputs = Vector.empty,
outputs = Vector(utxo),
lockTime = UInt32.zero)
// creditingTx: BaseTransaction = BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(0ba1ff18b17397b9487188bf22c6b9f877d7831f))),UInt32Impl(0))
// this is the information we need from the crediting TX
// to properly "link" it in the transaction we are creating
val outPoint = TransactionOutPoint(creditingTx.txId, UInt32.zero)
// outPoint: TransactionOutPoint = TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0)
val input = TransactionInput(
outPoint,
EmptyScriptSignature,
sequenceNumber = UInt32.zero)
// input: TransactionInput = TransactionInputImpl(TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0),EmptyScriptSignature,UInt32Impl(0))
// Add a new input to our builder
builder += input
// res1: RawTxBuilder = RawTxBuilder()
// We can now generate a RawTxBuilderResult ready to be finalized
val builderResult = builder.result()
// builderResult: RawTxBuilderResult = RawTxBuilderResult(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0),EmptyScriptSignature,UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(18bb8fe332dbabfad38ead5e200802da2470eb73))),UInt32Impl(0))
// this contains the information needed to analyze our input during finalization
val inputInfo = P2PKHInputInfo(outPoint, amount, privKey.publicKey)
// inputInfo: P2PKHInputInfo = P2PKHInputInfo(TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0),10000 sats,ECPublicKey(038839cc58d1e077d426f550d13c0dc5bff744f749e4ea17f9c186ceb4e11ad130))
// this is how much we are going to pay as a fee to the network
// for this example, we are going to pay 1 satoshi per byte
val feeRate = SatoshisPerByte(1.satoshi)
// feeRate: SatoshisPerByte = 1 sats/byte
val changePrivKey = ECPrivateKey.freshPrivateKey
// changePrivKey: ECPrivateKey = Masked(ECPrivateKey)
val changeSPK = P2PKHScriptPubKey(pubKey = changePrivKey.publicKey)
// changeSPK: P2PKHScriptPubKey = pkh(43d5d39a854760e7e5382b326ca80d0bae46a7c5)
// We chose a finalizer that adds a change output to our tx based on a fee rate
val finalizer = StandardNonInteractiveFinalizer(
Vector(inputInfo),
feeRate,
changeSPK)
// finalizer: StandardNonInteractiveFinalizer = StandardNonInteractiveFinalizer(Vector(P2PKHInputInfo(TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0),10000 sats,ECPublicKey(038839cc58d1e077d426f550d13c0dc5bff744f749e4ea17f9c186ceb4e11ad130))),1 sats/byte,pkh(43d5d39a854760e7e5382b326ca80d0bae46a7c5))
// We can now finalize the tx builder result from earlier with this finalizer
val unsignedTx: Transaction = finalizer.buildTx(builderResult)
// unsignedTx: Transaction = BaseTransaction(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0),EmptyScriptSignature,UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(18bb8fe332dbabfad38ead5e200802da2470eb73)), TransactionOutput(4775 sats,pkh(43d5d39a854760e7e5382b326ca80d0bae46a7c5))),UInt32Impl(0))
// We now turn to signing the unsigned transaction
// this contains all the information we need to
// validly sign the UTXO above
val utxoInfo = ScriptSignatureParams(inputInfo = inputInfo,
prevTransaction = creditingTx,
signers = Vector(privKey),
hashType =
HashType.sigHashAll)
// utxoInfo: ScriptSignatureParams[P2PKHInputInfo] = ScriptSignatureParams(P2PKHInputInfo(TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0),10000 sats,ECPublicKey(038839cc58d1e077d426f550d13c0dc5bff744f749e4ea17f9c186ceb4e11ad130)),BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(0ba1ff18b17397b9487188bf22c6b9f877d7831f))),UInt32Impl(0)),Vector(Masked(ECPrivateKey)),SIGHASH_ALL(1))
// all of the UTXO spending information, since we only have
// one input, this is just one element
val utxoInfos: Vector[ScriptSignatureParams[InputInfo]] = Vector(utxoInfo)
// utxoInfos: Vector[ScriptSignatureParams[InputInfo]] = Vector(ScriptSignatureParams(P2PKHInputInfo(TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0),10000 sats,ECPublicKey(038839cc58d1e077d426f550d13c0dc5bff744f749e4ea17f9c186ceb4e11ad130)),BaseTransaction(Int32Impl(1),Vector(),Vector(TransactionOutput(10000 sats,pkh(0ba1ff18b17397b9487188bf22c6b9f877d7831f))),UInt32Impl(0)),Vector(Masked(ECPrivateKey)),SIGHASH_ALL(1)))
// Yay! Now we use the RawTxSigner object to sign the tx.
// The 'sign' method is going produce a validly signed transaction
// This is going to iterate through each of the UTXOs and use
// the corresponding ScriptSignatureParams to produce a validly
// signed input. This UTXO has:
// 1: one input
// 2: outputs (destination and change outputs)
// 3: a fee rate of 1 satoshi/byte
val signedTx: Transaction =
RawTxSigner.sign(
utx = unsignedTx,
utxoInfos = utxoInfos,
expectedFeeRate = feeRate
)
// signedTx: Transaction = BaseTransaction(Int32Impl(2),Vector(TransactionInputImpl(TransactionOutPoint(c644c58525144e921e4f78e59363f19f3f5a11a376ec00cd5d5dac14dbc88908:0),P2PKHScriptSignature(ECPublicKeyBytes(ByteVector(33 bytes, 0x038839cc58d1e077d426f550d13c0dc5bff744f749e4ea17f9c186ceb4e11ad130)), ECDigitalSignature(3044022040d3d0be3e208b68ab7ff12f151bb2eb4b6baf277afd7be69bb3d0b6e72e6e4d02203eb558668039a92cb8d5001cff6ec2fca0a8d7f67811311b230afa5d80351d2801)),UInt32Impl(0))),Vector(TransactionOutput(5000 sats,pkh(18bb8fe332dbabfad38ead5e200802da2470eb73)), TransactionOutput(4775 sats,pkh(43d5d39a854760e7e5382b326ca80d0bae46a7c5))),UInt32Impl(0))
```
```scala
signedTx.inputs.length
// res2: Int = 1
signedTx.outputs.length
// res3: Int = 2
//remember, you can call .hex on any bitcoin-s data structure to get the hex representation!
signedTx.hex
// res4: String = 02000000010889c8db14ac5d5dcd00ec76a3115a3f9ff16393e5784f1e924e142585c544c6000000006a473044022040d3d0be3e208b68ab7ff12f151bb2eb4b6baf277afd7be69bb3d0b6e72e6e4d02203eb558668039a92cb8d5001cff6ec2fca0a8d7f67811311b230afa5d80351d280121038839cc58d1e077d426f550d13c0dc5bff744f749e4ea17f9c186ceb4e11ad130000000000288130000000000001976a91418bb8fe332dbabfad38ead5e200802da2470eb7388aca7120000000000001976a91443d5d39a854760e7e5382b326ca80d0bae46a7c588ac00000000
```

View file

@ -0,0 +1,65 @@
---
id: version-1.9.4-sign
title: Sign API
original_id: sign
---
### The [`Sign` API](/api/org/bitcoins/crypto/Sign)
This is the API we define to sign things with. It takes in an arbitrary byte vector and returns a `Future[ECDigitalSignature]`. The reason we incorporate `Future`s here is for extensibility of this API. We would like to provide implementations of this API for hardware devices, which need to be asynchrnous since they may require user input.
From [Sign.scala](/api/org/bitcoins/crypto/Sign):
```scala
import scodec.bits._
import org.bitcoins.crypto._
import scala.concurrent._
import scala.concurrent.duration._
trait Sign {
def signFunction: ByteVector => Future[ECDigitalSignature]
def signFuture(bytes: ByteVector): Future[ECDigitalSignature] =
signFunction(bytes)
def sign(bytes: ByteVector): ECDigitalSignature = {
Await.result(signFuture(bytes), 30.seconds)
}
def publicKey: ECPublicKey
}
```
The `ByteVector` that is input to the `signFunction` should be the hash that is output from [`TransactionSignatureSerializer`](/api/org/bitcoins/core/crypto/TransactionSignatureSerializer)'s `hashForSignature` method. Our in-memory [`BaseECKey`](/api/org/bitcoins/crypto/BaseECKey) types implement the `Sign` API.
If you wanted to implement a new `Sign` api for a hardware wallet, you can easily pass it into the `TxBuilder`/`Signer` classes to allow for you to use those devices to sign with Bitcoin-S.
This API is currently used to sign ordinary transactions with our [`Signer`](/api/org/bitcoins/core/wallet/signer/Signer)s. The `Signer` subtypes (i.e. `P2PKHSigner`) implement the specific functionality needed to produce a valid digital signature for their corresponding script type.
### The [`ExtSign`](/api/org/bitcoins/crypto/Sign) API.
An [ExtKey](/api/org/bitcoins/core/crypto/ExtKey) is a data structure that can be used to generate more keys from a parent key. For more information look at [hd-keys.md](../core/hd-keys.md)
You can sign with `ExtPrivateKey` the same way you could with a normal `ECPrivateKey`.
```scala
import org.bitcoins.core.hd._
import org.bitcoins.core.crypto._
val extPrivKey = ExtPrivateKey(ExtKeyVersion.SegWitMainNetPriv)
// extPrivKey: ExtPrivateKey = Masked(ExtPrivateKeyImpl)
extPrivKey.sign(DoubleSha256Digest.empty.bytes)
// res0: ECDigitalSignature = ECDigitalSignature(3045022100dac821a2bbb1f964ebab10cc19bae172b8a207e8d20c3b0da7c1669dd329343602207eeadeb11dd783e724203ab84b08db9bda441138aec680cbde06c713c7e0d49e)
val path = BIP32Path(Vector(BIP32Node(0,false)))
// path: BIP32Path = m/0
extPrivKey.sign(DoubleSha256Digest.empty.bytes,path)
// res1: ECDigitalSignature = ECDigitalSignature(30440220339e864f5381dc9f643592ca7cba820efe8549184d5ac35ca3d78c87d734d356022078c3778e3e9b672ddcf90ba181d68536b9448f1924bffdd5d3ad01d93c841e9c)
```
With `ExtSign`, you can use `ExtPrivateKey` to sign transactions inside of `TxBuilder` since `UTXOSpendingInfo` takes in `Sign` as a parameter.
You can also provide a `path` to use to derive a child `ExtPrivateKey`, and then sign with that child private key

View file

@ -0,0 +1,127 @@
---
id: version-1.9.4-getting-started
title: Intro and Getting Started
original_id: getting-started
---
## Philosophy
Bitcoin-S is a loosely coupled set of cryptocurrency libraries for the JVM. They work well together, but also can be used
independently. This project's goal is NOT to be a full node implementation, rather a set of scalable cryptocurrency libraries
that use industry standard tools (rather than esoteric tech often found in cryptocurrency) where possible to make the lives of professional
software engineers, security engineers, devops engineers and accountants easier.
We are rapidly iterating on development with the goal of getting to a set of stable APIs that only change when the underlying bitcoin protocol changes.
If you are a professional working a cryptocurrency business and
have feedback on how to make your lives easier, please reach out on [slack](https://join.slack.com/t/suredbits/shared_invite/zt-eavycu0x-WQL7XOakzQo8tAy7jHHZUw),
[gitter](https://gitter.im/bitcoin-s-core/) or [twitter](https://twitter.com/Chris_Stewart_5/)!
## Getting prebuilt artifacts
### Java binaries
<details>
#### Latest release
Please see the release page on github, you can find it [here](https://github.com/bitcoin-s/bitcoin-s/releases)
#### Master builds
We build installers for mac, linux and windows everytime a PR is merged to master.
You can find the latest builds at this link:
https://github.com/bitcoin-s/bitcoin-s/actions/workflows/release.yml
Here is what the installers look like
![installers](/img/doc-imgs/github-artifacts.png)
</details>
### Docker
<details>
We publish docker images to docker hub on every PR merge and tag on github.
You can obtain the images for both the app server and oracle server on these
docker hub repos
[bitcoin-s-server docker hub repo](https://hub.docker.com/r/bitcoinscala/bitcoin-s-server/tags?page=1&ordering=last_updated)
[bitcoin-s-oracle-server docker hub repo](https://hub.docker.com/r/bitcoinscala/bitcoin-s-oracle-server/tags?page=1&ordering=last_updated)
</details>
### Library jars
<details>
Add this to your `build.sbt`:
```scala
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-bitcoind-rpc" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-core" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-chain" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-dlc-oracle" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-eclair-rpc" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-fee-provider" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-key-manager" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-lnd-rpc" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-node" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-oracle-explorer-client" % "1.9.2"
libraryDependencies += "org.bitcoin-s" % "bitcoin-s-secp256k1jni" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit-core" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-testkit" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-wallet" % "1.9.2"
libraryDependencies += "org.bitcoin-s" %% "bitcoin-s-zmq" % "1.9.2"
```
### Nightly builds
You can also run on the bleeding edge of Bitcoin-S, by
adding a snapshot build to your `build.sbt`. The most
recent snapshot published is `1.9.2-102-2a791b3f-20220728-1318-SNAPSHOT`.
To fetch snapshots, you will need to add the correct
resolver in your `build.sbt`:
```sbt
resolvers += Resolver.sonatypeRepo("snapshots")
```
The official maven repo for releases is
https://repo1.maven.org/maven2/org/bitcoin-s/
The repo for snapshots, which are published after everytime something is merged to master:
https://oss.sonatype.org/content/repositories/snapshots/org/bitcoin-s/
</details>
## Building JARs yourself
Please see [our setup docs](getting-setup.md)
## If you want to setup Bitcoin-S locally for development
Please see [our setup docs](getting-setup.md)

View file

@ -0,0 +1,124 @@
---
id: version-1.9.4-key-manager
title: Key Manager
original_id: key-manager
---
### Key Manager
The key manager module's goal is to encapsulate all private key interactions with the [wallet](../wallet/wallet.md) project.
As of this writing, there is only one type of `KeyManager` - [`BIP39KeyManager`](/api/org/bitcoins/keymanager/bip39/BIP39KeyManager).
The [`BIP39KeyManager`](/api/org/bitcoins/keymanager/bip39/BIP39KeyManager) stores a [`MnemonicCode`](/api/org/bitcoins/core/crypto/MnemonicCode) on disk which can be decrypted and used as a hot wallet.
Over the long run, we want to make it so that the wallet project needs to communicate with the key-manager to access private keys.
This means that ALL SIGNING should be done inside of the key-manager, and private keys should not leave the key manager.
This makes it easier to reason about the security characteristics of our private keys, and a way to provide a uniform interface for alternative key storage systems (hsm, cloud based key storage, etc) to be plugged into the bitcoin-s library.
#### Creating a key manager
The first thing you need create a key manager is some entropy.
A popular way for bitcoin wallet's to represent entropy is [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) which you [can use in bitcoin-s](/api/org/bitcoins/core/crypto/BIP39Seed)
You can generate a `MnemonicCode` in bitcoin-s with the following code
```scala
import org.bitcoins.core.crypto._
//get 256 bits of random entropy
val entropy = MnemonicCode.getEntropy256Bits
// entropy: scodec.bits.BitVector = BitVector(256 bits, 0x3ac53842f5136fbd1dd63fe6bfef38fb9cb7ed6fc099bac7b58cd93192d3ba04)
val mnemonic = MnemonicCode.fromEntropy(entropy)
// mnemonic: MnemonicCode = Masked(MnemonicCodeImpl)
//you can print that mnemonic seed with this
println(mnemonic.words)
// Vector(depart, clap, awful, tuition, dad, teach, jar, side, trade, youth, soda, warm, slice, wall, sample, basket, river, diet, glimpse, raven, bomb, hawk, trend, normal)
```
Now that we have a `MnemonicCode` that was securely generated, we need to now create `KeyManagerParams` which tells us how to generate
generate specific kinds of addresses for wallets.
`KeyManagerParams` takes 3 parameters:
1. `seedPath` there is where we store the `MnemonicCode` on your file system
2. [`purpose`](/api/org/bitcoins/core/hd/HDPurpose) which represents what type of utxo this `KeyManager` is associated with. The specification for this is in [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki)
3. [`network`](/api/org/bitcoins/core/config/NetworkParameters) what cryptocurrency network this key manager is associated with
This controls how the root key is defined. The combination of `purpose` and `network` determine how the root `ExtKey` is serialized. For more information on how this works please see [hd-keys](../core/hd-keys.md)
Now we can construct a native segwit key manager for the regtest network!
```scala
//this will create a temp directory with the prefix 'key-manager-example` that will
//have a file in it called "encrypted-bitcoin-s-seed.json"
val seedPath = Files.createTempDirectory("key-manager-example").resolve(WalletStorage.ENCRYPTED_SEED_FILE_NAME)
// seedPath: Path = /tmp/key-manager-example4979278246283051324/encrypted-bitcoin-s-seed.json
//let's create a native segwit key manager
val purpose = HDPurposes.SegWit
// purpose: HDPurpose = m/84'
//let's choose regtest as our network
val network = RegTest
// network: RegTest.type = RegTest
val kmParams = KeyManagerParams(seedPath, purpose, network)
// kmParams: KeyManagerParams = KeyManagerParams(/tmp/key-manager-example4979278246283051324/encrypted-bitcoin-s-seed.json,m/84',RegTest)
val aesPasswordOpt = Some(AesPassword.fromString("password"))
// aesPasswordOpt: Some[AesPassword] = Some(Masked(AesPassword))
val km = BIP39KeyManager.initializeWithMnemonic(aesPasswordOpt, mnemonic, None, kmParams)
// km: Either[KeyManagerInitializeError, BIP39KeyManager] = Right(org.bitcoins.keymanager.bip39.BIP39KeyManager@fc07502)
val rootXPub = km.right.get.getRootXPub
// rootXPub: ExtPublicKey = vpub5SLqN2bLY4WeZCQKz3e9Zv1YfBdjhv25U5TqsXSwNSkMDyhZDScDzJsb8biHA6cM9nEfMf2kzqjdhLoBGW6zjqo3PwWJuAD6VPRvbiQ7r8M
println(rootXPub)
// vpub5SLqN2bLY4WeZCQKz3e9Zv1YfBdjhv25U5TqsXSwNSkMDyhZDScDzJsb8biHA6cM9nEfMf2kzqjdhLoBGW6zjqo3PwWJuAD6VPRvbiQ7r8M
```
Which should print something that looks like this
`vpub5SLqN2bLY4WeXxMqwJHJFBEwxSscGB2uDUnsTS3edVjZEwTrQDFDNqoR2xLqARQPabGaXsHSTenTRcqm2EnB9MpuC4vSk3LqSgNmGGZtuq7`
which is a native segwit `ExtPubKey` for the regtest network!
You can always change the `network` or `purpose` to support different things. You do _not_ need to initialize the key manager
again after initializing it once. You can use the same `mnemonic` for different networks, which you control `KeyManagerParams`.
```scala
//let's create a nested segwit key manager for mainnet
val mainnetKmParams = KeyManagerParams(seedPath, HDPurposes.SegWit, MainNet)
// mainnetKmParams: KeyManagerParams = KeyManagerParams(/tmp/key-manager-example4979278246283051324/encrypted-bitcoin-s-seed.json,m/84',MainNet)
//we do not need to all `initializeWithMnemonic()` again as we have saved the seed to dis
val mainnetKeyManager = BIP39KeyManager.fromMnemonic(mnemonic, mainnetKmParams, None, Instant.now, false)
// mainnetKeyManager: BIP39KeyManager = org.bitcoins.keymanager.bip39.BIP39KeyManager@a35587b
val mainnetXpub = mainnetKeyManager.getRootXPub
// mainnetXpub: ExtPublicKey = zpub6jftahH18ngZxPAoKUneQGPZM4DXUPz58XYj172UtUFsSNxUE5GUUZW9DRYd9jE2nLhtMZQzqV9qEVFS9Hm3vnXSsJJ1EoV3aHgWA6YLika
println(mainnetXpub)
// zpub6jftahH18ngZxPAoKUneQGPZM4DXUPz58XYj172UtUFsSNxUE5GUUZW9DRYd9jE2nLhtMZQzqV9qEVFS9Hm3vnXSsJJ1EoV3aHgWA6YLika
```
Which gives us something that looks like this
`zpub6jftahH18ngZw98KGjRo5XcxeKTQ2eztsvskb1dC9XF5TLimQquTs6Ry7nBBA425D9joXmfgJJCexmJ1u2SELJZJfRi95gcnXadLpZzYb5c`
which is a p2sh wrapped segwit `ExtPubKey` for the bitcoin main network!
#### Creating a key manager from existing mnemonic
To create a `KeyManager` from existing mnemonic you need to specify the `seedPath` and then construct the `KeyManagerParams` that you would like.
Finally you call `KeyManager.fromParams()` that reads the mnemonic from disk and create's the key manager

View file

@ -0,0 +1,92 @@
---
id: version-1.9.4-secp256k1
title: Secp256k1
original_id: secp256k1
---
[Libsecp256k1](https://github.com/bitcoin-core/secp256k1) is used to preform cryptographic operations on the secp256k1 curve.
This is the curve that bitcoin uses. There is a _signficant_ speedup when using this library compared to java crypto libraries
like bouncy castle.
In bitcoin-s, we support native binaries for libsecp256k1
1. [linux 32 bit](../../secp256k1jni/natives/linux_32)
2. [linux 64 bit](../../secp256k1jni/natives/linux_64)
3. [mac osx 64 bit](../../secp256k1jni/natives/osx_64)
4. [windows 64 bit](../../secp256k1jni/natives/windows_64)
Bitcoin-s uses a zero dependency library called [`native-lib-loader`](https://github.com/scijava/native-lib-loader).
That does the appropriate loading of the library onto your classpath to be accessed.
### Using libsecp256k1
To tell if you have access to libsecp256k1 you can do the following
```scala
val isEnabled = org.bitcoin.Secp256k1Context.isEnabled()
println(s"Secp256k1Context.isEnabled=${isEnabled}")
```
If libsecp256k1 is enabled, you can use [NativeSecp256k1](/api/org/bitcoin/NativeSecp256k1)
with static method defined in the class.
```scala
val privKey = ECPrivateKey.freshPrivateKey
val pubKey = privKey.publicKey
val dataToSign = DoubleSha256Digest.empty
val signature = NativeSecp256k1.sign(dataToSign.bytes.toArray, privKey.bytes.toArray)
val verify = NativeSecp256k1.verify(dataToSign.bytes.toArray, signature, pubKey.bytes.toArray)
println(s"Verified with NativeSecp256k1 signature=${verify}")
//you can also just directly sign with the ECKey interface:
val signature2 = privKey.sign(dataToSign)
val verified2 = pubKey.verify(dataToSign, signature2)
println(s"Verified with NativeSecp256k1 again=${verified2}")
```
### When libsecp256k1 isn't available, or you want to turn it off
There are two reasons you wouldn't want to use libsecp256k1
1. You don't trust the pre-compiled binaries we are using
2. Your OS/arch is not supported
There are two ways you can circumvent libsecp256k1
1. Set `DISABLE_SECP256K1=true` in your environment variables. This will force `CryptoContext.default` to return false which will make Bitcoin-S act like `Secp256k1Context.isEnabled()` has returned false.
2. Call Bouncy castle methods in `ECKey`.
Here is an example of calling bouncy castle methods in `ECKey`
```scala
val privKey = ECPrivateKey.freshPrivateKey
// privKey: ECPrivateKey = Masked(ECPrivateKey)
// calls bouncy castle indirectly via CryptoContext
val publicKey = privKey.publicKey
// publicKey: ECPublicKey = ECPublicKey(02fa4039b52b752dcaf6606e16889fc162543f717b910a8bd838d89c89f954bd07)
val dataToSign = DoubleSha256Digest.empty
// dataToSign: DoubleSha256Digest = DoubleSha256Digest(0000000000000000000000000000000000000000000000000000000000000000)
// calls bouncy castle indirectly via CryptoContext
val signature = privKey.sign(dataToSign.bytes)
// signature: ECDigitalSignature = ECDigitalSignature(3045022100dcc054efc50702aa10442f974b0bc4a55fcdf10f712e32c10a935272aaeff5610220139fab013ceb9184e9f363ea1d5066c93513f9e89cfac7abd0a449f2821be6a2)
// calls bouncy castle indirectly via CryptoContext
val verified = publicKey.verify(dataToSign.bytes, signature)
// verified: Boolean = true
println(s"Verified with bouncy castle=${verified}")
// Verified with bouncy castle=true
```
### Building libsecp256k1
[See instructions here](add-to-jni.md#adding-to-bitcoin-s)

View file

@ -0,0 +1,103 @@
---
title: Wallet Sync
id: version-1.9.4-wallet-sync
original_id: wallet-sync
---
## High level wallet state
Our wallet infrastructure has a specific table called `state_descriptors`.
This tracks chain state for our wallet.
Here is an example of the contents of this table
>sqlite> select * from state_descriptors;
SyncHeight|0000000000000000000134aa9e949ea1d053042b8dfa59bdc73b0322a88f009e 665741
If you look carefully in the second column, you will see a string encoding indicating
what the wallet state is. In this case, the last block hash seen by the wallet is
>0000000000000000000134aa9e949ea1d053042b8dfa59bdc73b0322a88f009e
and height
>665741
If you have access to a wallet, you can call
[`wallet.getSyncDescriptorOpt`](https://github.com/bitcoin-s/bitcoin-s/blob/36b5fc142715f8ab3ad053465d53dc29ab319790/wallet/src/main/scala/org/bitcoins/wallet/Wallet.scala#L160) to get access to this information
#### Wallet state from the cli
Alternatively, you can retrieve this information with `bitcoin-s-cli`
```
./bitcoin-s-cli walletinfo
{
"wallet": {
"keymanager": {
"rootXpub": "..."
},
"xpub": "...",
"hdPath": "...",
"height": 1906239,
"blockHash": "00000000dcf1066b8cd764a6104a9b5e95a55cd31adf9107974b2581ac90fdb9"
}
}
```
## Syncing a wallet
Bitcoin-s provides a utility object called [`WalletSync`](https://github.com/bitcoin-s/bitcoin-s/blob/f3e81d027dfdda79e26642d5c29d381874ee72da/wallet/src/main/scala/org/bitcoins/wallet/sync/WalletSync.scala#L10)
that provides useful utilities for syncing a bitcoin-s wallet.
### Syncing wallet for with access to full blocks
Inside of `WalletSync` we have a method called [`WalletSync.syncFullBlocks`](https://github.com/bitcoin-s/bitcoin-s/blob/f3e81d027dfdda79e26642d5c29d381874ee72da/wallet/src/main/scala/org/bitcoins/wallet/sync/WalletSync.scala#L18)
This method takes 4 parameters
- a [Wallet](https://github.com/bitcoin-s/bitcoin-s/blob/36b5fc142715f8ab3ad053465d53dc29ab319790/wallet/src/main/scala/org/bitcoins/wallet/Wallet.scala#L46) to sync
- `getBlockHeaderFunc` is a function to retrieve a block header based on a blockHash
- `getBestBlockHashFunc` is a function to retrieve the best block hash for our blockchain
- `getBlockFunc` is a function to retrieve a full [`Block`](https://github.com/bitcoin-s/bitcoin-s/blob/8a148357d560a40bf21e7c0e3f4074cd276534fe/core/src/main/scala/org/bitcoins/core/protocol/blockchain/Block.scala#L18) that corresponds to a block hash
Given these for things, we can use [`WalletSync.syncFullBlocks`](https://github.com/bitcoin-s/bitcoin-s/blob/f3e81d027dfdda79e26642d5c29d381874ee72da/wallet/src/main/scala/org/bitcoins/wallet/sync/WalletSync.scala#L18) to sync our entire wallet.
Here is a code example
```scala
implicit val system: ActorSystem = ActorSystem(s"wallet-sync-example")
implicit val ec: ExecutionContext = system.dispatcher
// this reads authentication credentials and
// connection details from the default data
// directory on your platform
val client = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))
//yay! Now we have a started bitcoind.
//We will use this as our datasource for syncing our wallet
val bitcoindRpcClientF: Future[BitcoindRpcClient] = client.start()
//wait for bitcoind to get started
val bitcoind = Await.result(bitcoindRpcClientF, 10.seconds)
val getBestBlockHashFunc = () => bitcoind.getBestBlockHash
val getBlockHeaderFunc = { hash: DoubleSha256DigestBE => bitcoind.getBlockHeaderRaw(hash) }
val getBlockFunc = {hash: DoubleSha256DigestBE => bitcoind.getBlockRaw(hash) }
//yay! We are now all setup. Using our 3 functions above and a wallet, we can now sync
//a fresh wallet
implicit val walletAppConfig = WalletAppConfig.fromDefaultDatadir()
val feeRateProvider: FeeRateApi = MempoolSpaceProvider.fromBlockTarget(6, proxyParams = None)
val wallet = Wallet(bitcoind, bitcoind, feeRateProvider)
//yay! we have a synced wallet
val syncedWalletF = WalletSync.syncFullBlocks(wallet,
getBlockHeaderFunc,
getBestBlockHashFunc,
getBlockFunc)
```

View file

@ -0,0 +1,101 @@
{
"version-1.9.2-docs": {
"Getting Started": [
"version-1.9.2-getting-started",
"version-1.9.2-bips"
],
"Getting Setup": [
"version-1.9.2-getting-setup",
"version-1.9.2-ui-setup"
],
"Applications": [
"version-1.9.2-applications/cli",
"version-1.9.2-applications/server",
"version-1.9.2-applications/gui",
"version-1.9.2-applications/server-systemd"
],
"Chain": [
"version-1.9.2-chain/chain",
"version-1.9.2-chain/filter-sync",
"version-1.9.2-chain/chain-query-api"
],
"Configuration": [
"version-1.9.2-config/configuration"
],
"Core Module": [
"version-1.9.2-core/core-intro",
"version-1.9.2-core/addresses",
"version-1.9.2-core/hd-keys",
"version-1.9.2-core/adding-spks",
"version-1.9.2-core/spending-info",
"version-1.9.2-core/psbts",
"version-1.9.2-core/dlc",
"version-1.9.2-core/txbuilder",
"version-1.9.2-core/lightning-network"
],
"Crypto Module": [
"version-1.9.2-crypto/crypto-intro",
"version-1.9.2-crypto/sign",
"version-1.9.2-crypto/adaptor-signatures"
],
"Fee Provider": [
"version-1.9.2-fee-provider/fee-provider"
],
"Key Manager": [
"version-1.9.2-key-manager/server-key-manager",
"version-1.9.2-key-manager/key-manager"
],
"Node": [
"version-1.9.2-node/node",
"version-1.9.2-node/node-api"
],
"Wallet": [
"version-1.9.2-wallet/wallet",
"version-1.9.2-wallet/wallet-callbacks",
"version-1.9.2-wallet/wallet-get-address",
"version-1.9.2-wallet/address-tagging",
"version-1.9.2-wallet/dlc",
"version-1.9.2-wallet/wallet-rescan",
"version-1.9.2-wallet/wallet-sync",
"version-1.9.2-wallet/wallet-rpc",
"version-1.9.2-wallet/backups",
"version-1.9.2-wallet/wallet-election-example",
"version-1.9.2-wallet/wallet-price-example",
"version-1.9.2-wallet/wallet-sports-betting-example"
],
"Tor": [
"version-1.9.2-tor/tor"
],
"RPC Clients": [
"version-1.9.2-rpc/rpc-clients-intro",
"version-1.9.2-rpc/rpc-eclair",
"version-1.9.2-rpc/rpc-bitcoind",
"version-1.9.2-rpc/lnd-rpc"
],
"Secp256k1": [
"version-1.9.2-secp256k1/secp256k1",
"version-1.9.2-secp256k1/jni-modify"
],
"Testkit": [
"version-1.9.2-testkit/testkit",
"version-1.9.2-testkit/testkit-core"
],
"DLC Oracle": [
"version-1.9.2-oracle/build-oracle-server",
"version-1.9.2-oracle/oracle-server",
"version-1.9.2-oracle/oracle-election-example",
"version-1.9.2-oracle/oracle-price-example",
"version-1.9.2-oracle/oracle-sports-betting-example"
],
"Oracle Explorer Client": [
"version-1.9.2-oracle-explorer-client/oracle-explorer-client"
],
"Contributing": [
"version-1.9.2-contributing",
"version-1.9.2-contributing-website"
],
"Security": [
"version-1.9.2-security"
]
}
}

View file

@ -0,0 +1,102 @@
{
"version-1.9.4-docs": {
"Getting Started": [
"version-1.9.4-getting-started",
"version-1.9.4-bips"
],
"Getting Setup": [
"version-1.9.4-getting-setup",
"version-1.9.4-ui-setup"
],
"Applications": [
"version-1.9.4-applications/cli",
"version-1.9.4-applications/server",
"version-1.9.4-applications/gui",
"version-1.9.4-applications/server-systemd"
],
"Chain": [
"version-1.9.4-chain/chain",
"version-1.9.4-chain/filter-sync",
"version-1.9.4-chain/chain-query-api"
],
"Configuration": [
"version-1.9.4-config/configuration"
],
"Core Module": [
"version-1.9.4-core/core-intro",
"version-1.9.4-core/addresses",
"version-1.9.4-core/hd-keys",
"version-1.9.4-core/adding-spks",
"version-1.9.4-core/spending-info",
"version-1.9.4-core/psbts",
"version-1.9.4-core/dlc",
"version-1.9.4-core/txbuilder",
"version-1.9.4-core/lightning-network"
],
"Crypto Module": [
"version-1.9.4-crypto/crypto-intro",
"version-1.9.4-crypto/sign",
"version-1.9.4-crypto/adaptor-signatures",
"version-1.9.4-crypto/musig"
],
"Fee Provider": [
"version-1.9.4-fee-provider/fee-provider"
],
"Key Manager": [
"version-1.9.4-key-manager/server-key-manager",
"version-1.9.4-key-manager/key-manager"
],
"Node": [
"version-1.9.4-node/node",
"version-1.9.4-node/node-api"
],
"Wallet": [
"version-1.9.4-wallet/wallet",
"version-1.9.4-wallet/wallet-callbacks",
"version-1.9.4-wallet/wallet-get-address",
"version-1.9.4-wallet/address-tagging",
"version-1.9.4-wallet/dlc",
"version-1.9.4-wallet/wallet-rescan",
"version-1.9.4-wallet/wallet-sync",
"version-1.9.4-wallet/wallet-rpc",
"version-1.9.4-wallet/backups",
"version-1.9.4-wallet/wallet-election-example",
"version-1.9.4-wallet/wallet-price-example",
"version-1.9.4-wallet/wallet-sports-betting-example"
],
"Tor": [
"version-1.9.4-tor/tor"
],
"RPC Clients": [
"version-1.9.4-rpc/rpc-clients-intro",
"version-1.9.4-rpc/rpc-eclair",
"version-1.9.4-rpc/rpc-bitcoind",
"version-1.9.4-rpc/lnd-rpc"
],
"Secp256k1": [
"version-1.9.4-secp256k1/secp256k1",
"version-1.9.4-secp256k1/jni-modify"
],
"Testkit": [
"version-1.9.4-testkit/testkit",
"version-1.9.4-testkit/testkit-core"
],
"DLC Oracle": [
"version-1.9.4-oracle/build-oracle-server",
"version-1.9.4-oracle/oracle-server",
"version-1.9.4-oracle/oracle-election-example",
"version-1.9.4-oracle/oracle-price-example",
"version-1.9.4-oracle/oracle-sports-betting-example"
],
"Oracle Explorer Client": [
"version-1.9.4-oracle-explorer-client/oracle-explorer-client"
],
"Contributing": [
"version-1.9.4-contributing",
"version-1.9.4-contributing-website"
],
"Security": [
"version-1.9.4-security"
]
}
}

View file

@ -1,4 +1,5 @@
[
"1.9.4",
"1.9.3",
"1.9.2",
"1.9.1",