mirror of
https://github.com/ACINQ/eclair.git
synced 2025-03-13 11:35:47 +01:00
Add support for the signet
test network (#2387)
This commit is contained in:
parent
8f2028f600
commit
323aeec09c
16 changed files with 113 additions and 48 deletions
44
README.md
44
README.md
|
@ -115,18 +115,18 @@ eclair.node-color=49daaa
|
|||
|
||||
Here are some of the most common options:
|
||||
|
||||
name | description | default value
|
||||
-----------------------------|---------------------------------------------------------------------------------------|--------------
|
||||
eclair.chain | Which blockchain to use: *regtest*, *testnet* or *mainnet* | mainnet
|
||||
eclair.server.port | Lightning TCP port | 9735
|
||||
eclair.api.enabled | Enable/disable the API | false. By default the API is disabled. If you want to enable it, you must set a password.
|
||||
eclair.api.port | API HTTP port | 8080
|
||||
eclair.api.password | API password (BASIC) | "" (must be set if the API is enabled)
|
||||
eclair.bitcoind.rpcuser | Bitcoin Core RPC user | foo
|
||||
eclair.bitcoind.rpcpassword | Bitcoin Core RPC password | bar
|
||||
eclair.bitcoind.zmqblock | Bitcoin Core ZMQ block address | "tcp://127.0.0.1:29000"
|
||||
eclair.bitcoind.zmqtx | Bitcoin Core ZMQ tx address | "tcp://127.0.0.1:29000"
|
||||
eclair.bitcoind.wallet | Bitcoin Core wallet name | ""
|
||||
name | description | default value
|
||||
-----------------------------|----------------------------------------------------------------------|--------------
|
||||
eclair.chain | Which blockchain to use: *regtest*, *testnet*, *signet* or *mainnet* | mainnet
|
||||
eclair.server.port | Lightning TCP port | 9735
|
||||
eclair.api.enabled | Enable/disable the API | false. By default the API is disabled. If you want to enable it, you must set a password.
|
||||
eclair.api.port | API HTTP port | 8080
|
||||
eclair.api.password | API password (BASIC) | "" (must be set if the API is enabled)
|
||||
eclair.bitcoind.rpcuser | Bitcoin Core RPC user | foo
|
||||
eclair.bitcoind.rpcpassword | Bitcoin Core RPC password | bar
|
||||
eclair.bitcoind.zmqblock | Bitcoin Core ZMQ block address | "tcp://127.0.0.1:29000"
|
||||
eclair.bitcoind.zmqtx | Bitcoin Core ZMQ tx address | "tcp://127.0.0.1:29000"
|
||||
eclair.bitcoind.wallet | Bitcoin Core wallet name | ""
|
||||
|
||||
Quotes are not required unless the value contains special characters. Full syntax guide [here](https://github.com/lightbend/config/blob/master/HOCON.md).
|
||||
|
||||
|
@ -187,7 +187,7 @@ created. See [Managing Wallets](https://github.com/bitcoin/bitcoin/blob/master/d
|
|||
For Eclair, the files that you need to backup are located in your data directory. You must backup:
|
||||
|
||||
* your seeds (`node_seed.dat` and `channel_seed.dat`)
|
||||
* your channel database (`eclair.sqlite.bak` under directory `mainnet`, `testnet` or `regtest` depending on which chain you're running on)
|
||||
* your channel database (`eclair.sqlite.bak` under directory `mainnet`, `testnet`, `signet` or `regtest` depending on which chain you're running on)
|
||||
|
||||
Your seeds never change once they have been created, but your channels will change whenever you receive or send payments. Eclair will
|
||||
create and maintain a snapshot of its database, named `eclair.sqlite.bak`, in your data directory, and update it when needed. This file is
|
||||
|
@ -248,7 +248,7 @@ If you need support for these plugins, head over to their respective github repo
|
|||
|
||||
## Testnet usage
|
||||
|
||||
Eclair is configured to run on mainnet by default, but you can still run it on testnet (or regtest): start your Bitcoin node in
|
||||
Eclair is configured to run on mainnet by default, but you can still run it on testnet (or regtest/signet): start your Bitcoin node in
|
||||
testnet mode (add `testnet=1` in `bitcoin.conf` or start with `-testnet`), and change Eclair's chain parameter and Bitcoin RPC port:
|
||||
|
||||
```conf
|
||||
|
@ -256,17 +256,33 @@ eclair.chain=testnet
|
|||
eclair.bitcoind.rpcport=18332
|
||||
```
|
||||
|
||||
For regtest, add `regtest=1` in `bitcoin.conf` or start with `-regtest`, and modify `eclair.conf`:
|
||||
|
||||
```conf
|
||||
eclair.chain = "regtest"
|
||||
eclair.bitcoind.rpcport=18443
|
||||
```
|
||||
|
||||
For signet, add `signet=1` in `bitcoin.conf` or start with `-signet`, and modify `eclair.conf`:
|
||||
|
||||
```conf
|
||||
eclair.chain = "signet"
|
||||
eclair.bitcoind.rpcport=38332
|
||||
```
|
||||
|
||||
You may also want to take advantage of the new configuration sections in `bitcoin.conf` to manage parameters that are network specific,
|
||||
so you can easily run your Bitcoin node on both mainnet and testnet. For example you could use:
|
||||
|
||||
```conf
|
||||
server=1
|
||||
txindex=1
|
||||
|
||||
[main]
|
||||
rpcuser=<your-mainnet-rpc-user-here>
|
||||
rpcpassword=<your-mainnet-rpc-password-here>
|
||||
zmqpubhashblock=tcp://127.0.0.1:29000
|
||||
zmqpubrawtx=tcp://127.0.0.1:29000
|
||||
|
||||
[test]
|
||||
rpcuser=<your-testnet-rpc-user-here>
|
||||
rpcpassword=<your-testnet-rpc-password-here>
|
||||
|
|
|
@ -47,21 +47,21 @@ related to routing configuration, and include it from `eclair.conf`.
|
|||
|
||||
Here are some of the most common options:
|
||||
|
||||
name | description | default value
|
||||
-----------------------------|--------------------------------------------------------------------|--------------
|
||||
eclair.chain | Which blockchain to use: *regtest*, *testnet* or *mainnet* | mainnet
|
||||
eclair.server.port | Lightning TCP port | 9735
|
||||
eclair.api.port | API HTTP port | 8080
|
||||
eclair.api.enabled | Enables the JSON API | false
|
||||
eclair.api.password | Password protecting the API (BASIC auth) | _no default_
|
||||
eclair.bitcoind.auth | Bitcoin Core RPC authentication method: *password* or *safecookie* | password
|
||||
eclair.bitcoind.rpcuser | Bitcoin Core RPC user | foo
|
||||
eclair.bitcoind.rpcpassword | Bitcoin Core RPC password | bar
|
||||
eclair.bitcoind.cookie | Bitcoin Core RPC cookie path | ${user.home}"/.bitcoin/.cookie"
|
||||
eclair.bitcoind.zmqblock | Bitcoin Core ZMQ block address | "tcp://127.0.0.1:29000"
|
||||
eclair.bitcoind.zmqtx | Bitcoin Core ZMQ tx address | "tcp://127.0.0.1:29000"
|
||||
eclair.bitcoind.wallet | Bitcoin Core wallet name | ""
|
||||
eclair.server.public-ips | List of node public ip | _no default_
|
||||
name | description | default value
|
||||
-----------------------------|----------------------------------------------------------------------|--------------
|
||||
eclair.chain | Which blockchain to use: *regtest*, *testnet*, *signet* or *mainnet* | mainnet
|
||||
eclair.server.port | Lightning TCP port | 9735
|
||||
eclair.api.port | API HTTP port | 8080
|
||||
eclair.api.enabled | Enables the JSON API | false
|
||||
eclair.api.password | Password protecting the API (BASIC auth) | _no default_
|
||||
eclair.bitcoind.auth | Bitcoin Core RPC authentication method: *password* or *safecookie* | password
|
||||
eclair.bitcoind.rpcuser | Bitcoin Core RPC user | foo
|
||||
eclair.bitcoind.rpcpassword | Bitcoin Core RPC password | bar
|
||||
eclair.bitcoind.cookie | Bitcoin Core RPC cookie path | ${user.home}"/.bitcoin/.cookie"
|
||||
eclair.bitcoind.zmqblock | Bitcoin Core ZMQ block address | "tcp://127.0.0.1:29000"
|
||||
eclair.bitcoind.zmqtx | Bitcoin Core ZMQ tx address | "tcp://127.0.0.1:29000"
|
||||
eclair.bitcoind.wallet | Bitcoin Core wallet name | ""
|
||||
eclair.server.public-ips | List of node public ip | _no default_
|
||||
|
||||
→ see [`reference.conf`](https://github.com/ACINQ/eclair/blob/master/eclair-core/src/main/resources/reference.conf) for full reference. There are many more options!
|
||||
|
||||
|
|
|
@ -147,6 +147,15 @@ If the mempool becomes congested and the feerate is too low, the commitment tran
|
|||
|
||||
You can now specify a DNS host name as one of your `server.public-ips` addresses (see PR [#911](https://github.com/lightning/bolts/pull/911)). Note: you can not specify more than one DNS host name.
|
||||
|
||||
#### Support for testing on the signet network
|
||||
|
||||
To test Eclair with bitcoind configured for signet, set the following values in `eclair.conf`:
|
||||
|
||||
```conf
|
||||
eclair.chain = "signet"
|
||||
eclair.bitcoind.rpcport=38332
|
||||
```
|
||||
|
||||
## Verifying signatures
|
||||
|
||||
You will need `gpg` and our release signing key 7A73FE77DE2C4027. Note that you can get it:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
eclair {
|
||||
datadir = ${user.home}"/.eclair"
|
||||
|
||||
chain = "mainnet" // "regtest" for regtest, "testnet" for testnet, "mainnet" for mainnet
|
||||
chain = "mainnet" // "regtest" for regtest, "testnet" for testnet, "mainnet" for mainnet, "signet" for signet
|
||||
|
||||
server {
|
||||
public-ips = [] // external ips, will be announced on the network
|
||||
|
|
|
@ -163,6 +163,7 @@ object NodeParams extends Logging {
|
|||
private val chain2Hash: Map[String, ByteVector32] = Map(
|
||||
"regtest" -> Block.RegtestGenesisBlock.hash,
|
||||
"testnet" -> Block.TestnetGenesisBlock.hash,
|
||||
"signet" -> Block.SignetGenesisBlock.hash,
|
||||
"mainnet" -> Block.LivenetGenesisBlock.hash
|
||||
)
|
||||
|
||||
|
|
|
@ -185,6 +185,7 @@ class Setup(val datadir: File,
|
|||
_ <- chain match {
|
||||
case "mainnet" => bitcoinClient.invoke("getrawtransaction", "2157b554dcfda405233906e461ee593875ae4b1b97615872db6a25130ecc1dd6") // coinbase of #500000
|
||||
case "testnet" => bitcoinClient.invoke("getrawtransaction", "8f38a0dd41dc0ae7509081e262d791f8d53ed6f884323796d5ec7b0966dd3825") // coinbase of #1500000
|
||||
case "signet" => bitcoinClient.invoke("getrawtransaction", "ff1027486b628b2d160859205a3401fb2ee379b43527153b0b50a92c17ee7955") // coinbase of #5000
|
||||
case "regtest" => Future.successful(())
|
||||
}
|
||||
} yield (progress, ibd, chainHash, bitcoinVersion, unspentAddresses, blocks, headers)
|
||||
|
|
|
@ -20,8 +20,8 @@ import akka.actor.ActorSystem
|
|||
import akka.actor.typed.scaladsl.{ActorContext, Behaviors}
|
||||
import akka.actor.typed.{ActorRef, Behavior}
|
||||
import akka.pattern.after
|
||||
import fr.acinq.bitcoin.scalacompat.{Block, ByteVector32}
|
||||
import fr.acinq.bitcoin.BlockHeader
|
||||
import fr.acinq.bitcoin.scalacompat.{Block, ByteVector32}
|
||||
import fr.acinq.eclair.blockchain.watchdogs.BlockchainWatchdog.{BlockHeaderAt, LatestHeaders}
|
||||
import fr.acinq.eclair.blockchain.watchdogs.Monitoring.{Metrics, Tags}
|
||||
import fr.acinq.eclair.tor.Socks5ProxyParams
|
||||
|
@ -225,12 +225,14 @@ object ExplorerApi {
|
|||
override val baseUris = if (useTorEndpoints) {
|
||||
Map(
|
||||
Block.TestnetGenesisBlock.hash -> uri"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/testnet/api",
|
||||
Block.LivenetGenesisBlock.hash -> uri"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/api"
|
||||
Block.LivenetGenesisBlock.hash -> uri"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/api",
|
||||
Block.SignetGenesisBlock.hash -> uri"http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/signet/api"
|
||||
)
|
||||
} else {
|
||||
Map(
|
||||
Block.TestnetGenesisBlock.hash -> uri"https://mempool.space/testnet/api",
|
||||
Block.LivenetGenesisBlock.hash -> uri"https://mempool.space/api"
|
||||
Block.LivenetGenesisBlock.hash -> uri"https://mempool.space/api",
|
||||
Block.SignetGenesisBlock.hash -> uri"https://mempool.space/signet/api"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ package fr.acinq.eclair.crypto.keymanager
|
|||
|
||||
import com.google.common.cache.{CacheBuilder, CacheLoader, LoadingCache}
|
||||
import fr.acinq.bitcoin.scalacompat.Crypto.{PrivateKey, PublicKey}
|
||||
import fr.acinq.bitcoin.scalacompat.DeterministicWallet.{derivePrivateKey, _}
|
||||
import fr.acinq.bitcoin.scalacompat.DeterministicWallet._
|
||||
import fr.acinq.bitcoin.scalacompat.{Block, ByteVector32, ByteVector64, Crypto, DeterministicWallet}
|
||||
import fr.acinq.eclair.crypto.Generators
|
||||
import fr.acinq.eclair.crypto.Monitoring.{Metrics, Tags}
|
||||
|
@ -32,7 +32,7 @@ import scodec.bits.ByteVector
|
|||
|
||||
object LocalChannelKeyManager {
|
||||
def keyBasePath(chainHash: ByteVector32): List[Long] = (chainHash: @unchecked) match {
|
||||
case Block.RegtestGenesisBlock.hash | Block.TestnetGenesisBlock.hash => DeterministicWallet.hardened(46) :: DeterministicWallet.hardened(1) :: Nil
|
||||
case Block.RegtestGenesisBlock.hash | Block.TestnetGenesisBlock.hash | Block.SignetGenesisBlock.hash => DeterministicWallet.hardened(46) :: DeterministicWallet.hardened(1) :: Nil
|
||||
case Block.LivenetGenesisBlock.hash => DeterministicWallet.hardened(47) :: DeterministicWallet.hardened(1) :: Nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ object LocalNodeKeyManager {
|
|||
// Note that the node path and the above channel path are on different branches so even if the
|
||||
// node key is compromised there is no way to retrieve the wallet keys
|
||||
def keyBasePath(chainHash: ByteVector32): List[Long] = (chainHash: @unchecked) match {
|
||||
case Block.RegtestGenesisBlock.hash | Block.TestnetGenesisBlock.hash => DeterministicWallet.hardened(46) :: DeterministicWallet.hardened(0) :: Nil
|
||||
case Block.RegtestGenesisBlock.hash | Block.TestnetGenesisBlock.hash | Block.SignetGenesisBlock.hash => DeterministicWallet.hardened(46) :: DeterministicWallet.hardened(0) :: Nil
|
||||
case Block.LivenetGenesisBlock.hash => DeterministicWallet.hardened(47) :: DeterministicWallet.hardened(0) :: Nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,9 +92,9 @@ package object eclair {
|
|||
}
|
||||
|
||||
Try(decodeBase58(address)) match {
|
||||
case Success((Base58.Prefix.PubkeyAddressTestnet, pubKeyHash)) if chainHash == Block.TestnetGenesisBlock.hash || chainHash == Block.RegtestGenesisBlock.hash => Script.pay2pkh(pubKeyHash)
|
||||
case Success((Base58.Prefix.PubkeyAddressTestnet, pubKeyHash)) if chainHash == Block.TestnetGenesisBlock.hash || chainHash == Block.RegtestGenesisBlock.hash || chainHash == Block.SignetGenesisBlock.hash => Script.pay2pkh(pubKeyHash)
|
||||
case Success((Base58.Prefix.PubkeyAddress, pubKeyHash)) if chainHash == Block.LivenetGenesisBlock.hash => Script.pay2pkh(pubKeyHash)
|
||||
case Success((Base58.Prefix.ScriptAddressTestnet, scriptHash)) if chainHash == Block.TestnetGenesisBlock.hash || chainHash == Block.RegtestGenesisBlock.hash => OP_HASH160 :: OP_PUSHDATA(scriptHash) :: OP_EQUAL :: Nil
|
||||
case Success((Base58.Prefix.ScriptAddressTestnet, scriptHash)) if chainHash == Block.TestnetGenesisBlock.hash || chainHash == Block.RegtestGenesisBlock.hash || chainHash == Block.SignetGenesisBlock.hash => OP_HASH160 :: OP_PUSHDATA(scriptHash) :: OP_EQUAL :: Nil
|
||||
case Success((Base58.Prefix.ScriptAddress, scriptHash)) if chainHash == Block.LivenetGenesisBlock.hash => OP_HASH160 :: OP_PUSHDATA(scriptHash) :: OP_EQUAL :: Nil
|
||||
case Success(_) => throw new IllegalArgumentException("base58 address does not match our blockchain")
|
||||
case Failure(base58error) =>
|
||||
|
@ -102,7 +102,7 @@ package object eclair {
|
|||
case Success((_, version, _)) if version != 0.toByte => throw new IllegalArgumentException(s"invalid version $version in bech32 address")
|
||||
case Success((_, _, bin)) if bin.length != 20 && bin.length != 32 => throw new IllegalArgumentException("hash length in bech32 address must be either 20 or 32 bytes")
|
||||
case Success(("bc", _, bin)) if chainHash == Block.LivenetGenesisBlock.hash => OP_0 :: OP_PUSHDATA(bin) :: Nil
|
||||
case Success(("tb", _, bin)) if chainHash == Block.TestnetGenesisBlock.hash => OP_0 :: OP_PUSHDATA(bin) :: Nil
|
||||
case Success(("tb", _, bin)) if chainHash == Block.TestnetGenesisBlock.hash || chainHash == Block.SignetGenesisBlock.hash => OP_0 :: OP_PUSHDATA(bin) :: Nil
|
||||
case Success(("bcrt", _, bin)) if chainHash == Block.RegtestGenesisBlock.hash => OP_0 :: OP_PUSHDATA(bin) :: Nil
|
||||
case Success(_) => throw new IllegalArgumentException("bech32 address does not match our blockchain")
|
||||
case Failure(bech32error) => throw new IllegalArgumentException(s"$address is neither a valid Base58 address ($base58error) nor a valid Bech32 address ($bech32error)")
|
||||
|
|
|
@ -32,7 +32,7 @@ import scala.util.{Failure, Success, Try}
|
|||
* Lightning Bolt 11 invoice
|
||||
* see https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
|
||||
*
|
||||
* @param prefix currency prefix; lnbc for bitcoin, lntb for bitcoin testnet
|
||||
* @param prefix currency prefix; lnbc for bitcoin, lntb for bitcoin testnet, lntbs for bitcoin signet
|
||||
* @param amount_opt amount to pay (empty string means no amount is specified)
|
||||
* @param createdAt invoice timestamp (UNIX format)
|
||||
* @param nodeId id of the node emitting the invoice
|
||||
|
@ -136,6 +136,7 @@ object Bolt11Invoice {
|
|||
|
||||
val prefixes = Map(
|
||||
Block.RegtestGenesisBlock.hash -> "lnbcrt",
|
||||
Block.SignetGenesisBlock.hash -> "lntbs",
|
||||
Block.TestnetGenesisBlock.hash -> "lntb",
|
||||
Block.LivenetGenesisBlock.hash -> "lnbc"
|
||||
)
|
||||
|
@ -292,11 +293,12 @@ object Bolt11Invoice {
|
|||
f.version match {
|
||||
case 17 if prefix == "lnbc" => Base58Check.encode(Base58.Prefix.PubkeyAddress, data.toArray)
|
||||
case 18 if prefix == "lnbc" => Base58Check.encode(Base58.Prefix.ScriptAddress, data.toArray)
|
||||
case 17 if prefix == "lntb" || prefix == "lnbcrt" => Base58Check.encode(Base58.Prefix.PubkeyAddressTestnet, data.toArray)
|
||||
case 18 if prefix == "lntb" || prefix == "lnbcrt" => Base58Check.encode(Base58.Prefix.ScriptAddressTestnet, data.toArray)
|
||||
case 17 if prefix == "lntb" || prefix == "lnbcrt" || prefix == "lntbs" => Base58Check.encode(Base58.Prefix.PubkeyAddressTestnet, data.toArray)
|
||||
case 18 if prefix == "lntb" || prefix == "lnbcrt" || prefix == "lntbs" => Base58Check.encode(Base58.Prefix.ScriptAddressTestnet, data.toArray)
|
||||
case version if prefix == "lnbc" => Bech32.encodeWitnessAddress("bc", version, data.toArray)
|
||||
case version if prefix == "lntb" => Bech32.encodeWitnessAddress("tb", version, data.toArray)
|
||||
case version if prefix == "lnbcrt" => Bech32.encodeWitnessAddress("bcrt", version, data.toArray)
|
||||
case version if prefix == "lntbs" => Bech32.encodeWitnessAddress("tb", version, data.toArray)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
|
||||
package fr.acinq.eclair
|
||||
|
||||
import com.google.common.net.InetAddresses
|
||||
import fr.acinq.bitcoin.{Base58, Base58Check, Bech32}
|
||||
import fr.acinq.bitcoin.scalacompat.Crypto.PrivateKey
|
||||
import fr.acinq.bitcoin.scalacompat.{Block, ByteVector32, Crypto, Script}
|
||||
import fr.acinq.bitcoin.{Base58, Base58Check, Bech32}
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import scodec.bits._
|
||||
|
||||
|
@ -52,6 +51,7 @@ class PackageSpec extends AnyFunSuite {
|
|||
// valid chain
|
||||
assert(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.PubkeyAddressTestnet, pub.hash160), Block.TestnetGenesisBlock.hash) == Script.pay2pkh(pub))
|
||||
assert(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.PubkeyAddressTestnet, pub.hash160), Block.RegtestGenesisBlock.hash) == Script.pay2pkh(pub))
|
||||
assert(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.PubkeyAddressTestnet, pub.hash160), Block.SignetGenesisBlock.hash) == Script.pay2pkh(pub))
|
||||
assert(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.PubkeyAddress, pub.hash160), Block.LivenetGenesisBlock.hash) == Script.pay2pkh(pub))
|
||||
|
||||
// wrong chain
|
||||
|
@ -60,6 +60,7 @@ class PackageSpec extends AnyFunSuite {
|
|||
}
|
||||
assert(Try(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.PubkeyAddress, pub.hash160), Block.TestnetGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.PubkeyAddress, pub.hash160), Block.RegtestGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.PubkeyAddress, pub.hash160), Block.SignetGenesisBlock.hash)).isFailure)
|
||||
|
||||
// p2sh
|
||||
val script = Script.write(Script.pay2wpkh(pub))
|
||||
|
@ -67,12 +68,14 @@ class PackageSpec extends AnyFunSuite {
|
|||
// valid chain
|
||||
assert(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.ScriptAddressTestnet, Crypto.hash160(script)), Block.TestnetGenesisBlock.hash) == Script.pay2sh(script))
|
||||
assert(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.ScriptAddressTestnet, Crypto.hash160(script)), Block.RegtestGenesisBlock.hash) == Script.pay2sh(script))
|
||||
assert(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.ScriptAddressTestnet, Crypto.hash160(script)), Block.SignetGenesisBlock.hash) == Script.pay2sh(script))
|
||||
assert(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.ScriptAddress, Crypto.hash160(script)), Block.LivenetGenesisBlock.hash) == Script.pay2sh(script))
|
||||
|
||||
// wrong chain
|
||||
assert(Try(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.ScriptAddressTestnet, Crypto.hash160(script)), Block.LivenetGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.ScriptAddress, Crypto.hash160(script)), Block.TestnetGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.ScriptAddress, Crypto.hash160(script)), Block.RegtestGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Base58Check.encode(Base58.Prefix.ScriptAddress, Crypto.hash160(script)), Block.SignetGenesisBlock.hash)).isFailure)
|
||||
}
|
||||
|
||||
test("decode bech32 addresses") {
|
||||
|
@ -83,21 +86,25 @@ class PackageSpec extends AnyFunSuite {
|
|||
assert(addressToPublicKeyScript(Bech32.encodeWitnessAddress("bc", 0, pub.hash160), Block.LivenetGenesisBlock.hash) == Script.pay2wpkh(pub))
|
||||
assert(addressToPublicKeyScript(Bech32.encodeWitnessAddress("tb", 0, pub.hash160), Block.TestnetGenesisBlock.hash) == Script.pay2wpkh(pub))
|
||||
assert(addressToPublicKeyScript(Bech32.encodeWitnessAddress("bcrt", 0, pub.hash160), Block.RegtestGenesisBlock.hash) == Script.pay2wpkh(pub))
|
||||
assert(addressToPublicKeyScript(Bech32.encodeWitnessAddress("tb", 0, pub.hash160), Block.SignetGenesisBlock.hash) == Script.pay2wpkh(pub))
|
||||
|
||||
// wrong version
|
||||
assert(Try(addressToPublicKeyScript(Bech32.encodeWitnessAddress("bc", 1, pub.hash160), Block.LivenetGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Bech32.encodeWitnessAddress("tb", 1, pub.hash160), Block.TestnetGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Bech32.encodeWitnessAddress("bcrt", 1, pub.hash160), Block.RegtestGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Bech32.encodeWitnessAddress("tb", 1, pub.hash160), Block.SignetGenesisBlock.hash)).isFailure)
|
||||
|
||||
// wrong chain
|
||||
assert(Try(addressToPublicKeyScript(Bech32.encodeWitnessAddress("bc", 0, pub.hash160), Block.TestnetGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Bech32.encodeWitnessAddress("tb", 0, pub.hash160), Block.LivenetGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Bech32.encodeWitnessAddress("bcrt", 0, pub.hash160), Block.LivenetGenesisBlock.hash)).isFailure)
|
||||
assert(Try(addressToPublicKeyScript(Bech32.encodeWitnessAddress("tb", 0, pub.hash160), Block.LivenetGenesisBlock.hash)).isFailure)
|
||||
|
||||
val script = Script.write(Script.pay2wpkh(pub))
|
||||
assert(addressToPublicKeyScript(Bech32.encodeWitnessAddress("bc", 0, Crypto.sha256(script)), Block.LivenetGenesisBlock.hash) == Script.pay2wsh(script))
|
||||
assert(addressToPublicKeyScript(Bech32.encodeWitnessAddress("tb", 0, Crypto.sha256(script)), Block.TestnetGenesisBlock.hash) == Script.pay2wsh(script))
|
||||
assert(addressToPublicKeyScript(Bech32.encodeWitnessAddress("bcrt", 0, Crypto.sha256(script)), Block.RegtestGenesisBlock.hash) == Script.pay2wsh(script))
|
||||
assert(addressToPublicKeyScript(Bech32.encodeWitnessAddress("tb", 0, Crypto.sha256(script)), Block.SignetGenesisBlock.hash) == Script.pay2wsh(script))
|
||||
}
|
||||
|
||||
test("fail to decode invalid addresses") {
|
||||
|
|
|
@ -38,6 +38,7 @@ class BlockchainWatchdogSpec extends ScalaTestWithActorTestKit(ConfigFactory.loa
|
|||
// and comment these:
|
||||
val nodeParamsLivenet = removeBlockcypher(TestConstants.Alice.nodeParams.copy(chainHash = Block.LivenetGenesisBlock.hash))
|
||||
val nodeParamsTestnet = removeBlockcypher(TestConstants.Alice.nodeParams.copy(chainHash = Block.TestnetGenesisBlock.hash))
|
||||
val nodeParamsSignet = removeBlockcypher(TestConstants.Alice.nodeParams.copy(chainHash = Block.SignetGenesisBlock.hash))
|
||||
|
||||
|
||||
test("fetch block headers from four sources on mainnet", TestTags.ExternalApi) {
|
||||
|
@ -75,6 +76,19 @@ class BlockchainWatchdogSpec extends ScalaTestWithActorTestKit(ConfigFactory.loa
|
|||
testKit.stop(watchdog)
|
||||
}
|
||||
|
||||
test("fetch block headers from one source on signet", TestTags.ExternalApi) {
|
||||
val eventListener = TestProbe[DangerousBlocksSkew]()
|
||||
system.eventStream ! EventStream.Subscribe(eventListener.ref)
|
||||
val watchdog = testKit.spawn(BlockchainWatchdog(nodeParamsSignet, 1 second))
|
||||
watchdog ! WrappedCurrentBlockHeight(BlockHeight(5000))
|
||||
|
||||
val event = eventListener.expectMessageType[DangerousBlocksSkew]
|
||||
|
||||
eventListener.expectNoMessage(100 millis)
|
||||
assert(event.recentHeaders.source == "mempool.space")
|
||||
testKit.stop(watchdog)
|
||||
}
|
||||
|
||||
test("fetch block headers when we don't receive blocks", TestTags.ExternalApi) {
|
||||
val eventListener = TestProbe[DangerousBlocksSkew]()
|
||||
system.eventStream ! EventStream.Subscribe(eventListener.ref)
|
||||
|
|
|
@ -23,14 +23,13 @@ import fr.acinq.bitcoin.scalacompat.{Block, ByteVector32}
|
|||
import fr.acinq.eclair.FeatureSupport.{Mandatory, Optional}
|
||||
import fr.acinq.eclair.Features.{BasicMultiPartPayment, ChannelRangeQueries, PaymentSecret, VariableLengthOnion}
|
||||
import fr.acinq.eclair.TestConstants._
|
||||
import fr.acinq.eclair.RealShortChannelId
|
||||
import fr.acinq.eclair._
|
||||
import fr.acinq.eclair.crypto.TransportHandler
|
||||
import fr.acinq.eclair.message.OnionMessages.{Recipient, buildMessage}
|
||||
import fr.acinq.eclair.router.Router._
|
||||
import fr.acinq.eclair.router.RoutingSyncSpec
|
||||
import fr.acinq.eclair.wire.protocol
|
||||
import fr.acinq.eclair.wire.protocol._
|
||||
import fr.acinq.eclair.{RealShortChannelId, _}
|
||||
import org.scalatest.funsuite.FixtureAnyFunSuiteLike
|
||||
import org.scalatest.{Outcome, ParallelTestExecution}
|
||||
import scodec.bits._
|
||||
|
@ -198,7 +197,7 @@ class PeerConnectionSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike wi
|
|||
probe.send(peerConnection, PeerConnection.InitializeConnection(peer.ref, nodeParams.chainHash, nodeParams.features.initFeatures(), doSync = true))
|
||||
transport.expectMsgType[TransportHandler.Listener]
|
||||
transport.expectMsgType[protocol.Init]
|
||||
transport.send(peerConnection, protocol.Init(Bob.nodeParams.features.initFeatures(), TlvStream(InitTlv.Networks(Block.LivenetGenesisBlock.hash :: Block.SegnetGenesisBlock.hash :: Nil))))
|
||||
transport.send(peerConnection, protocol.Init(Bob.nodeParams.features.initFeatures(), TlvStream(InitTlv.Networks(Block.LivenetGenesisBlock.hash :: Block.SignetGenesisBlock.hash :: Nil))))
|
||||
transport.expectMsgType[TransportHandler.ReadAck]
|
||||
probe.expectTerminated(transport.ref)
|
||||
origin.expectMsg(PeerConnection.ConnectionResult.InitializationFailed("incompatible networks"))
|
||||
|
|
|
@ -207,6 +207,20 @@ class Bolt11InvoiceSpec extends AnyFunSuite {
|
|||
assert(invoice.sign(priv).toString == ref)
|
||||
}
|
||||
|
||||
test("Parse a signet invoice") {
|
||||
val ref = "lntbs2500u1p30ukj3pp5flaka84tayag36uj06k58tn5zukel0paskxwmc0gppc6t6utmp3sdq809hkcmcsp5uv40j7x3dx6sqfrefmj6lu933zakwedejyl4rsakv2lzg53fqxlsmqz9gxqrrsscqp79q2sqqqqqysgqmq30dcj5l8lc02e6pxq0wmagy5qafc05hv6e0yd6ftudes2awa8psu63tuf39dch0dk3hdckfd64g2v3y58tnpma68fxfyqr4vw22wsqm4jkrn"
|
||||
val Success(invoice) = Bolt11Invoice.fromString(ref)
|
||||
assert(invoice.prefix == "lntbs")
|
||||
assert(invoice.amount_opt.contains(250000000 msat))
|
||||
assert(invoice.paymentHash.bytes == hex"4ffb6e9eabe93a88eb927ead43ae74172d9fbc3d858cede1e80871a5eb8bd863")
|
||||
assert(invoice.features == Features(VariableLengthOnion -> Mandatory, PaymentSecret -> Mandatory, BasicMultiPartPayment -> Optional, PaymentMetadata -> Optional ))
|
||||
assert(invoice.createdAt == TimestampSecond(1660836433))
|
||||
assert(invoice.nodeId == PublicKey(hex"02e899d99662f2e64ea0eeaecb53c4628fa40a22d7185076e42e8a3d67fcb7b8e6"))
|
||||
assert(invoice.description == Left("yolo"))
|
||||
assert(invoice.fallbackAddress().isEmpty)
|
||||
assert(invoice.tags.size == 7)
|
||||
}
|
||||
|
||||
test("On mainnet, with fallback address 1RustyRX2oai4EYYDpQGWvEL62BBGqN9T with extra routing info to go via nodes 029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255 then 039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255") {
|
||||
val ref = "lnbc20m1pvjluezsp5zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygspp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzq9qrsgqdfjcdk6w3ak5pca9hwfwfh63zrrz06wwfya0ydlzpgzxkn5xagsqz7x9j4jwe7yj7vaf2k9lqsdk45kts2fd0fkr28am0u4w95tt2nsq76cqw0"
|
||||
val Success(invoice) = Bolt11Invoice.fromString(ref)
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -72,7 +72,7 @@
|
|||
<akka.version>2.6.18</akka.version>
|
||||
<akka.http.version>10.2.7</akka.http.version>
|
||||
<sttp.version>3.4.1</sttp.version>
|
||||
<bitcoinlib.version>0.23</bitcoinlib.version>
|
||||
<bitcoinlib.version>0.24</bitcoinlib.version>
|
||||
<guava.version>31.1-jre</guava.version>
|
||||
<kamon.version>2.4.6</kamon.version>
|
||||
</properties>
|
||||
|
|
Loading…
Add table
Reference in a new issue