Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions docs/release-notes/release-notes-0.7.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
- [An integration test flake was
fixed](https://github.com/lightninglabs/taproot-assets/pull/1651).

- Fixed two send related bugs that would lead to either a `invalid transfer
asset witness` or `unable to fund address send: error funding packet: unable
- Fixed two send related bugs that would lead to either a `invalid transfer
asset witness` or `unable to fund address send: error funding packet: unable
to list eligible coins: unable to query commitments: mismatch of managed utxo
and constructed tap commitment root` error when sending assets.
The [PR that fixed the two
Expand All @@ -36,7 +36,7 @@
tombstone outputs on a full-value send (by using interactive transfers for V2
addresses).

- [Updated](https://github.com/lightninglabs/taproot-assets/pull/1774)
- [Updated](https://github.com/lightninglabs/taproot-assets/pull/1774)
`BuyOrderRequest` and `SellOrderRequest` proto docs to mark `peer_pub_key` as
required. Previously, the field was incorrectly documented as optional.
This change corrects the documentation to match the current implementation.
Expand Down Expand Up @@ -179,20 +179,21 @@
- [Rename](https://github.com/lightninglabs/taproot-assets/pull/1682) the
`MintAsset` RPC message field from `universe_commitments` to
`enable_supply_commitments`.

- [Enhanced RFQ accepted quote messages with asset identification fields](https://github.com/lightninglabs/taproot-assets/pull/1805):
The `PeerAcceptedBuyQuote` and `PeerAcceptedSellQuote` proto messages
now include asset ID and asset group pub key fields (via the `AssetSpecBytes`
message), allowing clients to directly associate quotes with their
corresponding assets without manual tracking.

- The `SubscribeSendEvents` RPC now supports [historical event replay of
- The `SubscribeSendEvents` RPC now supports [historical event replay of
completed sends with efficient database-level
filtering](https://github.com/lightninglabs/taproot-assets/pull/1685).
- [Add universe RPC endpoint FetchSupplyLeaves](https://github.com/lightninglabs/taproot-assets/pull/1693)
that allows users to fetch the supply leaves of a universe supply commitment.
This is useful for verification.

- A [new field `unconfirmed_transfers` was added to the response of the
- A [new field `unconfirmed_transfers` was added to the response of the
`ListBalances` RPC
method](https://github.com/lightninglabs/taproot-assets/pull/1691) to indicate
that unconfirmed asset-related transactions don't count toward the balance.
Expand All @@ -204,9 +205,9 @@
- The `AddrReceives` RPC now supports timestamp filtering with
[new `StartTimestamp` and `EndTimestamp` fields](https://github.com/lightninglabs/taproot-assets/pull/1794).

- The [FetchSupplyLeaves RPC endpoint](https://github.com/lightninglabs/taproot-assets/pull/1829)
is now accessible without authentication when the universe server is
configured with public read access. This matches the behavior of the
- The [FetchSupplyLeaves RPC endpoint](https://github.com/lightninglabs/taproot-assets/pull/1829)
is now accessible without authentication when the universe server is
configured with public read access. This matches the behavior of the
existing FetchSupplyCommit RPC endpoint.

- [PR#1839](https://github.com/lightninglabs/taproot-assets/pull/1839) The
Expand Down Expand Up @@ -239,7 +240,7 @@
includes unset and zero-valued proto fields (e.g. transaction output indexes).
This ensures consistent output shape across all proto messages.

- The `tapcli addrs receives` command now supports
- The `tapcli addrs receives` command now supports
[new `--start_timestamp` and `--end_timestamp` flags](https://github.com/lightninglabs/taproot-assets/pull/1794).

- The `tapcli addrs receives` command now has new flags `--limit`, `--offset` and
Expand Down
12 changes: 12 additions & 0 deletions docs/release-notes/release-notes-0.8.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@

## RPC Updates

- [TLS connections with price oracles will now be constructed by
default](https://github.com/lightninglabs/taproot-assets/pull/1775), using
the operating system's root CA list for certificate verification.
`experimental.rfq.priceoracletls` (default `true`) can be set to `false`
to disable TLS entirely. For certificate-level configuration,
`experimental.rfq.priceoracletlsnosystemcas` (default `false`) can be set
to `true` to disable use of the OS's root CA list, and
`experimental.rfq.priceoracletlscertpath` allows a custom (root CA or
self-signed) certificate to be used.
`experimental.rfq.priceoracletlsinsecure` can be used to skip certificate
verification (default `false`).

- [PR#1841](https://github.com/lightninglabs/taproot-assets/pull/1841): Remove
the defaultMacaroonWhitelist map and inline its entries directly
into the conditional logic within MacaroonWhitelist. This ensures that
Expand Down
1 change: 1 addition & 0 deletions itest/tapd_harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ func newTapdHarness(t *testing.T, ht *harnessTest, cfg tapdConfig,
case len(opts.oracleServerAddress) > 0:
tapCfg.Experimental.Rfq.PriceOracleAddress =
opts.oracleServerAddress
tapCfg.Experimental.Rfq.PriceOracleTLSInsecure = true

default:
// Set the experimental config for the RFQ service.
Expand Down
8 changes: 8 additions & 0 deletions rfq/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ const (
type CliConfig struct {
PriceOracleAddress string `long:"priceoracleaddress" description:"Price oracle gRPC server address (rfqrpc://<hostname>:<port>). To use the integrated mock, use the following value: use_mock_price_oracle_service_promise_to_not_use_on_mainnet"`

PriceOracleTLSDisable bool `long:"priceoracletlsdisable" description:"Disable TLS for price oracle communication."`

PriceOracleTLSInsecure bool `long:"priceoracletlsinsecure" description:"Disable price oracle certificate verification."`

PriceOracleTLSNoSystemCAs bool `long:"priceoracletlsnosystemcas" description:"Disable use of the operating system's list of root CA's when verifiying price oracle certificates."`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: s/verifiying/verifying


PriceOracleTLSCertPath string `long:"priceoracletlscertpath" description:"Path to a PEM-encoded x509 certificate to use when constructing a TLS connection with a price oracle."`

SendPriceHint bool `long:"sendpricehint" description:"Send a price hint from the local price oracle to the RFQ peer when requesting a quote. For privacy reasons, this should only be turned on for self-hosted or trusted price oracles."`

PriceOracleSendPeerId bool `long:"priceoraclesendpeerid" description:"Send the peer ID (public key of the peer) to the price oracle when requesting a price rate. For privacy reasons, this should only be turned on for self-hosted or trusted price oracles."`
Expand Down
71 changes: 7 additions & 64 deletions rfq/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package rfq

import (
"context"
"crypto/tls"
"fmt"
"math"
"net/url"
Expand All @@ -16,9 +15,6 @@ import (
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
)

// PriceQueryIntent is an enum that represents the intent of a price rate
Expand Down Expand Up @@ -187,84 +183,31 @@ type RpcPriceOracle struct {
rawConn *grpc.ClientConn
}

// clientKeepaliveDialOption configures bidirectional health probing to prevent
// idle RFQ connections from being silently terminated by network intermediaries
// (NATs, load balancers) or aggressive server timeouts. Without active
// keepalive, the first price query after an idle period would fail with
// "connection reset by peer" and require a retry.
var clientKeepaliveDialOption = grpc.WithKeepaliveParams(
keepalive.ClientParameters{
// Ping server after 30 seconds of inactivity.
Time: 30 * time.Second,

// Wait 20 seconds for ping response.
Timeout: 20 * time.Second,

// Permit keepalive pings even when there are no active
// streams. This is critical for long-lived connections with
// infrequent RFQ requests.
PermitWithoutStream: true,
},
)

// serverDialOpts returns the set of server options needed to connect to the
// price oracle RPC server using a TLS connection.
func serverDialOpts() ([]grpc.DialOption, error) {
var opts []grpc.DialOption

tlsConfig := tls.Config{InsecureSkipVerify: true}
transportCredentials := credentials.NewTLS(&tlsConfig)

opts = append(opts, grpc.WithTransportCredentials(transportCredentials))

opts = append(opts, clientKeepaliveDialOption)

return opts, nil
}

// insecureServerDialOpts returns the set of server options needed to connect to
// the price oracle RPC server using a TLS connection.
func insecureServerDialOpts() ([]grpc.DialOption, error) {
var opts []grpc.DialOption

// Skip TLS certificate verification.
opts = append(opts, grpc.WithTransportCredentials(
insecure.NewCredentials(),
))

opts = append(opts, clientKeepaliveDialOption)

return opts, nil
}

// NewRpcPriceOracle creates a new RPC price oracle handle given the address
// of the price oracle RPC server.
func NewRpcPriceOracle(addrStr string, dialInsecure bool) (*RpcPriceOracle,
func NewRpcPriceOracle(addrStr string, tlsConfig *TLSConfig) (*RpcPriceOracle,
error) {

addr, err := ParsePriceOracleAddress(addrStr)
if err != nil {
return nil, err
}

// Connect to the RPC server.
dialOpts, err := serverDialOpts()
// Create transport credentials and dial options from the supplied TLS
// config.
transportCredentials, err := configureTransportCredentials(tlsConfig)
if err != nil {
return nil, err
}

// Allow connecting to a non-TLS (h2c, http over cleartext) gRPC server,
// should be used for testing only.
if dialInsecure {
dialOpts, err = insecureServerDialOpts()
if err != nil {
return nil, err
}
dialOpts := []grpc.DialOption{
grpc.WithTransportCredentials(transportCredentials),
}

// Formulate the server address dial string.
serverAddr := fmt.Sprintf("%s:%s", addr.Hostname(), addr.Port())

// Connect to the RPC server.
conn, err := grpc.Dial(serverAddr, dialOpts...)
if err != nil {
return nil, err
Expand Down
12 changes: 10 additions & 2 deletions rfq/oracle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ func runQuerySalePriceTest(t *testing.T, tc *testCaseQuerySalePrice) {

// Create a new RPC price oracle client and connect to the mock service.
serviceAddr := fmt.Sprintf("rfqrpc://%s", testServiceAddress)
client, err := NewRpcPriceOracle(serviceAddr, true)
insecureTLS := &TLSConfig{Enabled: false}
client, err := NewRpcPriceOracle(serviceAddr, insecureTLS)
require.NoError(t, err)

// Query for an ask price.
Expand Down Expand Up @@ -239,6 +240,13 @@ type testCaseQueryPurchasePrice struct {
assetGroupKey *btcec.PublicKey
}

// insecureTLS returns a TLSConfig with TLS disabled.
func insecureTLS() *TLSConfig {
return &TLSConfig{
Enabled: false,
}
}

// runQueryPurchasePriceTest runs the RPC price oracle client QueryBuyPrice
// test.
func runQueryPurchasePriceTest(t *testing.T, tc *testCaseQueryPurchasePrice) {
Expand All @@ -251,7 +259,7 @@ func runQueryPurchasePriceTest(t *testing.T, tc *testCaseQueryPurchasePrice) {

// Create a new RPC price oracle client and connect to the mock service.
serviceAddr := fmt.Sprintf("rfqrpc://%s", testServiceAddress)
client, err := NewRpcPriceOracle(serviceAddr, true)
client, err := NewRpcPriceOracle(serviceAddr, insecureTLS())
require.NoError(t, err)

// Query for an ask price.
Expand Down
68 changes: 68 additions & 0 deletions rfq/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package rfq

import (
"crypto/tls"
"crypto/x509"

"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)

// TLSConfig represents TLS configuration options for oracle connections.
type TLSConfig struct {
// Enabled indicates that we should use TLS.
Enabled bool

// InsecureSkipVerify disables certificate verification.
InsecureSkipVerify bool

// TrustSystemRootCAs indicates whether or not to use the operating
// system's root certificate authority list.
TrustSystemRootCAs bool

// CustomCertificates contains PEM data for additional root CA and
// self-signed certificates to trust.
CustomCertificates []byte
}

// configureTransportCredentials configures the TLS transport credentials to
// be used for RPC connections.
func configureTransportCredentials(
config *TLSConfig) (credentials.TransportCredentials, error) {

// If TLS is disabled, return insecure credentials.
if !config.Enabled {
return insecure.NewCredentials(), nil
}

// If we're to skip certificate verification, then return TLS
// credentials with certificate verification disabled.
if config.InsecureSkipVerify {
creds := credentials.NewTLS(&tls.Config{
InsecureSkipVerify: true,
})
return creds, nil
}

// Initialize the certificate pool.
certPool, err := constructCertPool(config.TrustSystemRootCAs)
if err != nil {
return nil, err
}

// If we have any custom certificates, add them to the certificate
// pool.
certPool.AppendCertsFromPEM(config.CustomCertificates)

// Return the constructed transport credentials.
return credentials.NewClientTLSFromCert(certPool, ""), nil
}

// constructCertPool is a helper for constructing an initial certificate pool,
// depending on whether or not we should trust the system root CA list.
func constructCertPool(trustSystem bool) (*x509.CertPool, error) {
if trustSystem {
return x509.SystemCertPool()
}
return x509.NewCertPool(), nil
}
Loading
Loading