Merge pull request #506 from halseth/dynamic-channel-params

Dynamic and user definable channel params
This commit is contained in:
Olaoluwa Osuntokun 2018-01-12 15:38:12 -08:00 committed by GitHub
commit db06a8a7ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1074 additions and 572 deletions

@ -18,7 +18,6 @@ import (
"github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/chainview"
"github.com/roasbeef/btcd/chaincfg/chainhash"
"github.com/roasbeef/btcd/rpcclient"
@ -27,28 +26,11 @@ import (
"github.com/roasbeef/btcwallet/walletdb"
)
// defaultBitcoinForwardingPolicy is the default forwarding policy used for
// Bitcoin channels.
var defaultBitcoinForwardingPolicy = htlcswitch.ForwardingPolicy{
MinHTLC: lnwire.NewMSatFromSatoshis(1),
BaseFee: lnwire.NewMSatFromSatoshis(1),
FeeRate: 1,
TimeLockDelta: 144,
}
// defaultLitecoinForwardingPolicy is the default forwarding policy used for
// Litecoin channels.
var defaultLitecoinForwardingPolicy = htlcswitch.ForwardingPolicy{
MinHTLC: lnwire.NewMSatFromSatoshis(1),
BaseFee: 1,
FeeRate: 1,
TimeLockDelta: 576,
}
// defaultChannelConstraints is the default set of channel constraints that are
// meant to be used when initially funding a channel.
//
// TODO(roasbeef): have one for both chains
// TODO(halseth): make configurable at startup?
var defaultChannelConstraints = channeldb.ChannelConstraints{
DustLimit: lnwallet.DefaultDustLimit(),
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
@ -119,12 +101,22 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
switch registeredChains.PrimaryChain() {
case bitcoinChain:
cc.routingPolicy = defaultBitcoinForwardingPolicy
cc.routingPolicy = htlcswitch.ForwardingPolicy{
MinHTLC: cfg.Bitcoin.MinHTLC,
BaseFee: cfg.Bitcoin.BaseFee,
FeeRate: cfg.Bitcoin.FeeRate,
TimeLockDelta: cfg.Bitcoin.TimeLockDelta,
}
cc.feeEstimator = lnwallet.StaticFeeEstimator{
FeeRate: 50,
}
case litecoinChain:
cc.routingPolicy = defaultLitecoinForwardingPolicy
cc.routingPolicy = htlcswitch.ForwardingPolicy{
MinHTLC: cfg.Litecoin.MinHTLC,
BaseFee: cfg.Litecoin.BaseFee,
FeeRate: cfg.Litecoin.FeeRate,
TimeLockDelta: cfg.Litecoin.TimeLockDelta,
}
cc.feeEstimator = lnwallet.StaticFeeEstimator{
FeeRate: 100,
}

@ -431,6 +431,11 @@ var openChannelCommand = cli.Command{
"must be explicitly told about it to be able " +
"to route through it",
},
cli.Int64Flag{
Name: "min_htlc_msat",
Usage: "(optional) the minimum value we will require " +
"for incoming HTLCs on the channel",
},
},
Action: actionDecorator(openChannel),
}
@ -456,8 +461,9 @@ func openChannel(ctx *cli.Context) error {
}
req := &lnrpc.OpenChannelRequest{
TargetConf: int32(ctx.Int64("conf_target")),
SatPerByte: ctx.Int64("sat_per_byte"),
TargetConf: int32(ctx.Int64("conf_target")),
SatPerByte: ctx.Int64("sat_per_byte"),
MinHtlcMsat: ctx.Int64("min_htlc_msat"),
}
switch {
@ -1970,7 +1976,7 @@ var feeReportCommand = cli.Command{
Usage: "display the current fee policies of all active channels",
Description: `
Returns the current fee policies of all active channels.
Fee policies can be updated using the updateFees command.`,
Fee policies can be updated using the updatechanpolicy command.`,
Action: actionDecorator(feeReport),
}
@ -1989,13 +1995,13 @@ func feeReport(ctx *cli.Context) error {
return nil
}
var updateFeesCommand = cli.Command{
Name: "updatefees",
Usage: "update the fee policy for all channels, or a single channel",
ArgsUsage: "base_fee_msat fee_rate [channel_point]",
var updateChannelPolicyCommand = cli.Command{
Name: "updatechanpolicy",
Usage: "update the channel policy for all channels, or a single channel",
ArgsUsage: "base_fee_msat fee_rate time_lock_delta [channel_point]",
Description: `
Updates the fee policy for all channels, or just a particular channel
identified by it's channel point. The fee update will be committed, and
Updates the channel policy for all channels, or just a particular channel
identified by its channel point. The update will be committed, and
broadcast to the rest of the network within the next batch.
Channel points are encoded as: funding_txid:output_index`,
Flags: []cli.Flag{
@ -2011,6 +2017,11 @@ var updateFeesCommand = cli.Command{
"proportionally based on the value of each " +
"forwarded HTLC, the lowest possible rate is 0.000001",
},
cli.Int64Flag{
Name: "time_lock_delta",
Usage: "the CLTV delta that will be applied to all " +
"forwarded HTLCs",
},
cli.StringFlag{
Name: "chan_point",
Usage: "The channel whose fee policy should be " +
@ -2018,18 +2029,19 @@ var updateFeesCommand = cli.Command{
"will be updated. Takes the form of: txid:output_index",
},
},
Action: actionDecorator(updateFees),
Action: actionDecorator(updateChannelPolicy),
}
func updateFees(ctx *cli.Context) error {
func updateChannelPolicy(ctx *cli.Context) error {
ctxb := context.Background()
client, cleanUp := getClient(ctx)
defer cleanUp()
var (
baseFee int64
feeRate float64
err error
baseFee int64
feeRate float64
timeLockDelta int64
err error
)
args := ctx.Args()
@ -2060,10 +2072,26 @@ func updateFees(ctx *cli.Context) error {
return fmt.Errorf("fee_rate argument missing")
}
switch {
case ctx.IsSet("time_lock_delta"):
timeLockDelta = ctx.Int64("time_lock_delta")
case args.Present():
timeLockDelta, err = strconv.ParseInt(args.First(), 10, 64)
if err != nil {
return fmt.Errorf("unable to decode time_lock_delta: %v",
err)
}
args = args.Tail()
default:
return fmt.Errorf("time_lock_delta argument missing")
}
var (
chanPoint *lnrpc.ChannelPoint
chanPointStr string
)
switch {
case ctx.IsSet("chan_point"):
chanPointStr = ctx.String("chan_point")
@ -2093,22 +2121,23 @@ func updateFees(ctx *cli.Context) error {
}
}
req := &lnrpc.FeeUpdateRequest{
BaseFeeMsat: baseFee,
FeeRate: feeRate,
req := &lnrpc.PolicyUpdateRequest{
BaseFeeMsat: baseFee,
FeeRate: feeRate,
TimeLockDelta: uint32(timeLockDelta),
}
if chanPoint != nil {
req.Scope = &lnrpc.FeeUpdateRequest_ChanPoint{
req.Scope = &lnrpc.PolicyUpdateRequest_ChanPoint{
ChanPoint: chanPoint,
}
} else {
req.Scope = &lnrpc.FeeUpdateRequest_Global{
req.Scope = &lnrpc.PolicyUpdateRequest_Global{
Global: true,
}
}
resp, err := client.UpdateFees(ctxb, req)
resp, err := client.UpdateChannelPolicy(ctxb, req)
if err != nil {
return err
}

@ -193,7 +193,7 @@ func main() {
signMessageCommand,
verifyMessageCommand,
feeReportCommand,
updateFeesCommand,
updateChannelPolicyCommand,
}
if err := app.Run(os.Args); err != nil {

@ -38,9 +38,22 @@ const (
defaultPeerPort = 9735
defaultRPCHost = "localhost"
defaultMaxPendingChannels = 1
defaultNumChanConfs = 3
defaultNoEncryptWallet = false
defaultTrickleDelay = 30 * 1000
// minTimeLockDelta is the minimum timelock we require for incoming
// HTLCs on our channels.
minTimeLockDelta = 4
defaultBitcoinMinHTLCMSat = 1000
defaultBitcoinBaseFeeMSat = 1000
defaultBitcoinFeeRate = 1
defaultBitcoinTimeLockDelta = 144
defaultLitecoinMinHTLCMSat = 1000
defaultLitecoinBaseFeeMSat = 1000
defaultLitecoinFeeRate = 1
defaultLitecoinTimeLockDelta = 576
)
var (
@ -74,6 +87,13 @@ type chainConfig struct {
TestNet3 bool `long:"testnet" description:"Use the test network"`
SimNet bool `long:"simnet" description:"Use the simulation test network"`
RegTest bool `long:"regtest" description:"Use the regression test network"`
DefaultNumChanConfs int `long:"defaultchanconfs" description:"The default number of confirmations a channel must have before it's considered open. If this is not set, we will scale the value according to the channel size."`
DefaultRemoteDelay int `long:"defaultremotedelay" description:"The default number of blocks we will require our channel counterparty to wait before accessing its funds in case of unilateral close. If this is not set, we will scale the value according to the channel size."`
MinHTLC lnwire.MilliSatoshi `long:"minhtlc" description:"The smallest HTLC we are willing to forward on our channels, in millisatoshi"`
BaseFee lnwire.MilliSatoshi `long:"basefee" description:"The base fee in millisatoshi we will charge for forwarding payments on our channels"`
FeeRate lnwire.MilliSatoshi `long:"feerate" description:"The fee rate used when forwarding payments on our channels. The total fee charged is basefee + (amount * feerate / 1000000), where amount is the forwarded amount."`
TimeLockDelta uint32 `long:"timelockdelta" description:"The CLTV delta we will subtract from a forwarded HTLC's timelock value"`
}
type neutrinoConfig struct {
@ -127,8 +147,6 @@ type config struct {
Litecoin *chainConfig `group:"Litecoin" namespace:"litecoin"`
Bitcoin *chainConfig `group:"Bitcoin" namespace:"bitcoin"`
DefaultNumChanConfs int `long:"defaultchanconfs" description:"The default number of confirmations a channel must have before it's considered open."`
NeutrinoMode *neutrinoConfig `group:"neutrino" namespace:"neutrino"`
Autopilot *autoPilotConfig `group:"autopilot" namespace:"autopilot"`
@ -150,27 +168,34 @@ type config struct {
// 4) Parse CLI options and overwrite/add any specified options
func loadConfig() (*config, error) {
defaultCfg := config{
ConfigFile: defaultConfigFile,
DataDir: defaultDataDir,
DebugLevel: defaultLogLevel,
TLSCertPath: defaultTLSCertPath,
TLSKeyPath: defaultTLSKeyPath,
AdminMacPath: defaultAdminMacPath,
ReadMacPath: defaultReadMacPath,
LogDir: defaultLogDir,
PeerPort: defaultPeerPort,
RPCPort: defaultRPCPort,
RESTPort: defaultRESTPort,
MaxPendingChannels: defaultMaxPendingChannels,
DefaultNumChanConfs: defaultNumChanConfs,
NoEncryptWallet: defaultNoEncryptWallet,
ConfigFile: defaultConfigFile,
DataDir: defaultDataDir,
DebugLevel: defaultLogLevel,
TLSCertPath: defaultTLSCertPath,
TLSKeyPath: defaultTLSKeyPath,
AdminMacPath: defaultAdminMacPath,
ReadMacPath: defaultReadMacPath,
LogDir: defaultLogDir,
PeerPort: defaultPeerPort,
RPCPort: defaultRPCPort,
RESTPort: defaultRESTPort,
MaxPendingChannels: defaultMaxPendingChannels,
NoEncryptWallet: defaultNoEncryptWallet,
Bitcoin: &chainConfig{
RPCHost: defaultRPCHost,
RPCCert: defaultBtcdRPCCertFile,
RPCHost: defaultRPCHost,
RPCCert: defaultBtcdRPCCertFile,
MinHTLC: defaultBitcoinMinHTLCMSat,
BaseFee: defaultBitcoinBaseFeeMSat,
FeeRate: defaultBitcoinFeeRate,
TimeLockDelta: defaultBitcoinTimeLockDelta,
},
Litecoin: &chainConfig{
RPCHost: defaultRPCHost,
RPCCert: defaultLtcdRPCCertFile,
RPCHost: defaultRPCHost,
RPCCert: defaultLtcdRPCCertFile,
MinHTLC: defaultLitecoinMinHTLCMSat,
BaseFee: defaultLitecoinBaseFeeMSat,
FeeRate: defaultLitecoinFeeRate,
TimeLockDelta: defaultLitecoinTimeLockDelta,
},
Autopilot: &autoPilotConfig{
MaxChannels: 5,
@ -256,6 +281,11 @@ func loadConfig() (*config, error) {
return nil, fmt.Errorf(str, funcName)
}
if cfg.Litecoin.TimeLockDelta < minTimeLockDelta {
return nil, fmt.Errorf("timelockdelta must be at least %v",
minTimeLockDelta)
}
// The litecoin chain is the current active chain. However
// throughout the codebase we required chiancfg.Params. So as a
// temporary hack, we'll mutate the default net params for
@ -305,6 +335,11 @@ func loadConfig() (*config, error) {
return nil, err
}
if cfg.Bitcoin.TimeLockDelta < minTimeLockDelta {
return nil, fmt.Errorf("timelockdelta must be at least %v",
minTimeLockDelta)
}
if !cfg.NeutrinoMode.Active {
// If needed, we'll attempt to automatically configure
// the RPC control plan for the target btcd node.

@ -42,13 +42,13 @@ type networkMsg struct {
err chan error
}
// feeUpdateRequest is a request that is sent to the server when a caller
// wishes to update the fees for a particular set of channels. New UpdateFee
// messages will be crafted to be sent out during the next broadcast epoch and
// the fee updates committed to the lower layer.
type feeUpdateRequest struct {
// chanPolicyUpdateRequest is a request that is sent to the server when a caller
// wishes to update the channel policy (fees e.g.) for a particular set of
// channels. New ChannelUpdate messages will be crafted to be sent out during
// the next broadcast epoch and the fee updates committed to the lower layer.
type chanPolicyUpdateRequest struct {
targetChans []wire.OutPoint
newSchema routing.FeeSchema
newSchema routing.ChannelPolicy
errResp chan error
}
@ -175,9 +175,9 @@ type AuthenticatedGossiper struct {
// networkHandler.
networkMsgs chan *networkMsg
// feeUpdates is a channel that requests to update the fee schedule of
// a set of channels is sent over.
feeUpdates chan *feeUpdateRequest
// chanPolicyUpdates is a channel that requests to update the forwarding
// policy of a set of channels is sent over.
chanPolicyUpdates chan *chanPolicyUpdateRequest
// bestHeight is the height of the block at the tip of the main chain
// as we know it.
@ -202,7 +202,7 @@ func New(cfg Config, selfKey *btcec.PublicKey) (*AuthenticatedGossiper, error) {
cfg: &cfg,
networkMsgs: make(chan *networkMsg),
quit: make(chan struct{}),
feeUpdates: make(chan *feeUpdateRequest),
chanPolicyUpdates: make(chan *chanPolicyUpdateRequest),
prematureAnnouncements: make(map[uint32][]*networkMsg),
prematureChannelUpdates: make(map[uint64][]*networkMsg),
waitingProofs: storage,
@ -296,24 +296,24 @@ func (d *AuthenticatedGossiper) SynchronizeNode(pub *btcec.PublicKey) error {
return d.cfg.SendToPeer(pub, announceMessages...)
}
// PropagateFeeUpdate signals the AuthenticatedGossiper to update the fee
// schema for the specified channels. If no channels are specified, then the
// fee update will be applied to all outgoing channels from the source node.
// Fee updates are done in two stages: first, the AuthenticatedGossiper ensures
// the updated has been committed by dependant sub-systems, then it signs and
// broadcasts new updates to the network.
func (d *AuthenticatedGossiper) PropagateFeeUpdate(newSchema routing.FeeSchema,
chanPoints ...wire.OutPoint) error {
// PropagateChanPolicyUpdate signals the AuthenticatedGossiper to update the
// channel forwarding policies for the specified channels. If no channels are
// specified, then the update will be applied to all outgoing channels from the
// source node. Policy updates are done in two stages: first, the
// AuthenticatedGossiper ensures the update has been committed by dependant
// sub-systems, then it signs and broadcasts new updates to the network.
func (d *AuthenticatedGossiper) PropagateChanPolicyUpdate(
newSchema routing.ChannelPolicy, chanPoints ...wire.OutPoint) error {
errChan := make(chan error, 1)
feeUpdate := &feeUpdateRequest{
policyUpdate := &chanPolicyUpdateRequest{
targetChans: chanPoints,
newSchema: newSchema,
errResp: errChan,
}
select {
case d.feeUpdates <- feeUpdate:
case d.chanPolicyUpdates <- policyUpdate:
return <-errChan
case <-d.quit:
return fmt.Errorf("AuthenticatedGossiper shutting down")
@ -823,17 +823,18 @@ func (d *AuthenticatedGossiper) networkHandler() {
for {
select {
// A new fee update has arrived. We'll commit it to the
// A new policy update has arrived. We'll commit it to the
// sub-systems below us, then craft, sign, and broadcast a new
// ChannelUpdate for the set of affected clients.
case feeUpdate := <-d.feeUpdates:
case policyUpdate := <-d.chanPolicyUpdates:
// First, we'll now create new fully signed updates for
// the affected channels and also update the underlying
// graph with the new state.
newChanUpdates, err := d.processFeeChanUpdate(feeUpdate)
newChanUpdates, err := d.processChanPolicyUpdate(policyUpdate)
if err != nil {
log.Errorf("Unable to craft fee updates: %v", err)
feeUpdate.errResp <- err
log.Errorf("Unable to craft policy updates: %v",
err)
policyUpdate.errResp <- err
continue
}
@ -842,7 +843,7 @@ func (d *AuthenticatedGossiper) networkHandler() {
// start of the next epoch.
announcements.AddMsgs(newChanUpdates...)
feeUpdate.errResp <- nil
policyUpdate.errResp <- nil
case announcement := <-d.networkMsgs:
// Channel annoucnement signatures are the only message
@ -1072,18 +1073,19 @@ func (d *AuthenticatedGossiper) retransmitStaleChannels() error {
return nil
}
// processFeeChanUpdate generates a new set of channel updates with the new fee
// schema applied for each specified channel identified by its channel point.
// In the case that no channel points are specified, then the fee update will
// processChanPolicyUpdate generates a new set of channel updates with the new
// channel policy applied for each specified channel identified by its channel
// point. In the case that no channel points are specified, then the update will
// be applied to all channels. Finally, the backing ChannelGraphSource is
// updated with the latest information reflecting the applied fee updates.
// updated with the latest information reflecting the applied updates.
//
// TODO(roasbeef): generalize into generic for any channel update
func (d *AuthenticatedGossiper) processFeeChanUpdate(feeUpdate *feeUpdateRequest) ([]networkMsg, error) {
func (d *AuthenticatedGossiper) processChanPolicyUpdate(
policyUpdate *chanPolicyUpdateRequest) ([]networkMsg, error) {
// First, we'll construct a set of all the channels that need to be
// updated.
chansToUpdate := make(map[wire.OutPoint]struct{})
for _, chanPoint := range feeUpdate.targetChans {
for _, chanPoint := range policyUpdate.targetChans {
chansToUpdate[chanPoint] = struct{}{}
}
@ -1104,11 +1106,14 @@ func (d *AuthenticatedGossiper) processFeeChanUpdate(feeUpdate *feeUpdateRequest
}
// Apply the new fee schema to the edge.
edge.FeeBaseMSat = feeUpdate.newSchema.BaseFee
edge.FeeBaseMSat = policyUpdate.newSchema.BaseFee
edge.FeeProportionalMillionths = lnwire.MilliSatoshi(
feeUpdate.newSchema.FeeRate,
policyUpdate.newSchema.FeeRate,
)
// Apply the new TimeLockDelta.
edge.TimeLockDelta = uint16(policyUpdate.newSchema.TimeLockDelta)
// Re-sign and update the backing ChannelGraphSource, and
// retrieve our ChannelUpdate to broadcast.
_, chanUpdate, err := d.updateChannel(info, edge)
@ -1981,12 +1986,18 @@ func (d *AuthenticatedGossiper) sendAnnSigReliably(
func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
edge *channeldb.ChannelEdgePolicy) (*lnwire.ChannelAnnouncement, *lnwire.ChannelUpdate, error) {
edge.LastUpdate = time.Now()
// Make sure timestamp is always increased, such that our update
// gets propagated.
timestamp := time.Now().Unix()
if timestamp <= edge.LastUpdate.Unix() {
timestamp = edge.LastUpdate.Unix() + 1
}
edge.LastUpdate = time.Unix(timestamp, 0)
chanUpdate := &lnwire.ChannelUpdate{
Signature: edge.Signature,
ChainHash: info.ChainHash,
ShortChannelID: lnwire.NewShortChanIDFromInt(edge.ChannelID),
Timestamp: uint32(edge.LastUpdate.Unix()),
Timestamp: uint32(timestamp),
Flags: edge.Flags,
TimeLockDelta: edge.TimeLockDelta,
HtlcMinimumMsat: edge.MinHTLC,

@ -32,8 +32,6 @@ const (
// TODO(roasbeef): tune
msgBufferSize = 50
defaultCsvDelay = 4
// maxFundingAmount is a soft-limit of the maximum channel size
// accepted within the Lightning Protocol Currently. This limit is
// currently defined in BOLT-0002, and serves as an initial
@ -43,6 +41,13 @@ const (
// TODO(roasbeef): add command line param to modify
maxFundingAmount = btcutil.Amount(1 << 24)
// minRemoteDelay and maxRemoteDelay is the extremes of the CSV delay
// we will require the remote to use for its commitment transaction.
// The actual delay we will require will be somewhere between these
// values, depending on channel size.
minRemoteDelay = 144
maxRemoteDelay = 2016
// maxWaitNumBlocksFundingConf is the maximum number of blocks to wait
// for the funding transaction to be confirmed before forgetting about
// the channel. 288 blocks is ~48 hrs
@ -2101,6 +2106,8 @@ func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey *btcec.Pu
chanFlags = 1
}
// We announce the channel with the default values. Some of
// these values can later be changed by crafting a new ChannelUpdate.
chanUpdateAnn := &lnwire.ChannelUpdate{
ShortChannelID: shortChanID,
ChainHash: chainHash,
@ -2252,6 +2259,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
remoteAmt = msg.remoteFundingAmt
capacity = localAmt + remoteAmt
ourDustLimit = lnwallet.DefaultDustLimit()
minHtlc = msg.minHtlc
)
fndgLog.Infof("Initiating fundingRequest(localAmt=%v, remoteAmt=%v, "+
@ -2321,9 +2329,14 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
// delay we require given the total amount of funds within the channel.
remoteCsvDelay := f.cfg.RequiredRemoteDelay(capacity)
// If no minimum HTLC value was specified, use the default one.
if minHtlc == 0 {
minHtlc = f.cfg.DefaultRoutingPolicy.MinHTLC
}
// Once the reservation has been created, and indexed, queue a funding
// request to the remote peer, kicking off the funding workflow.
reservation.RegisterMinHTLC(f.cfg.DefaultRoutingPolicy.MinHTLC)
reservation.RegisterMinHTLC(minHtlc)
ourContribution := reservation.OurContribution()
// Finally, we'll use the current value of the channels and our default

@ -264,8 +264,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
},
NumRequiredConfs: func(chanAmt btcutil.Amount,
pushAmt lnwire.MilliSatoshi) uint16 {
return uint16(cfg.DefaultNumChanConfs)
return 3
},
RequiredRemoteDelay: func(amt btcutil.Amount) uint16 {
return 4

@ -39,7 +39,9 @@ const (
// the error possibly carrying along a ChannelUpdate message that includes the
// latest policy.
type ForwardingPolicy struct {
// MinHTLC is the smallest HTLC that is to be forwarded.
// MinHTLC is the smallest HTLC that is to be forwarded. This is
// set when a channel is first opened, and will be static for the
// lifetime of the channel.
MinHTLC lnwire.MilliSatoshi
// BaseFee is the base fee, expressed in milli-satoshi that must be
@ -604,9 +606,6 @@ out:
// with a "null" field in the new policy, we'll
// only update to the set sub policy if the new
// value isn't uninitialized.
if req.policy.MinHTLC != 0 {
l.cfg.FwrdingPolicy.MinHTLC = req.policy.MinHTLC
}
if req.policy.BaseFee != 0 {
l.cfg.FwrdingPolicy.BaseFee = req.policy.BaseFee
}

71
lnd.go

@ -298,16 +298,71 @@ func lndMain() error {
return nil, fmt.Errorf("unable to find channel")
},
DefaultRoutingPolicy: activeChainControl.routingPolicy,
NumRequiredConfs: func(chanAmt btcutil.Amount, pushAmt lnwire.MilliSatoshi) uint16 {
// TODO(roasbeef): add configurable mapping
// * simple switch initially
// * assign coefficient, etc
return uint16(cfg.DefaultNumChanConfs)
NumRequiredConfs: func(chanAmt btcutil.Amount,
pushAmt lnwire.MilliSatoshi) uint16 {
// For large channels we increase the number
// of confirmations we require for the
// channel to be considered open. As it is
// always the responder that gets to choose
// value, the pushAmt is value being pushed
// to us. This means we have more to lose
// in the case this gets re-orged out, and
// we will require more confirmations before
// we consider it open.
// TODO(halseth): Use Litecoin params in case
// of LTC channels.
// In case the user has explicitly specified
// a default value for the number of
// confirmations, we use it.
defaultConf := uint16(cfg.Bitcoin.DefaultNumChanConfs)
if defaultConf != 0 {
return defaultConf
}
// If not we return a value scaled linearly
// between 3 and 6, depending on channel size.
// TODO(halseth): Use 1 as minimum?
minConf := uint64(3)
maxConf := uint64(6)
maxChannelSize := uint64(
lnwire.NewMSatFromSatoshis(maxFundingAmount))
stake := lnwire.NewMSatFromSatoshis(chanAmt) + pushAmt
conf := maxConf * uint64(stake) / maxChannelSize
if conf < minConf {
conf = minConf
}
if conf > maxConf {
conf = maxConf
}
return uint16(conf)
},
RequiredRemoteDelay: func(chanAmt btcutil.Amount) uint16 {
// TODO(roasbeef): add additional hooks for
// configuration
return 4
// We scale the remote CSV delay (the time the
// remote have to claim funds in case of a unilateral
// close) linearly from minRemoteDelay blocks
// for small channels, to maxRemoteDelay blocks
// for channels of size maxFundingAmount.
// TODO(halseth): Litecoin parameter for LTC.
// In case the user has explicitly specified
// a default value for the remote delay, we
// use it.
defaultDelay := uint16(cfg.Bitcoin.DefaultRemoteDelay)
if defaultDelay > 0 {
return defaultDelay
}
// If not we scale according to channel size.
delay := uint16(maxRemoteDelay *
chanAmt / maxFundingAmount)
if delay < minRemoteDelay {
delay = minRemoteDelay
}
if delay > maxRemoteDelay {
delay = maxRemoteDelay
}
return delay
},
})
if err != nil {

@ -467,6 +467,290 @@ func testBasicChannelFunding(net *lntest.NetworkHarness, t *harnessTest) {
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, false)
}
// testUpdateChannelPolicy tests that policy updates made to a channel
// gets propagated to other nodes in the network.
func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
timeout := time.Duration(time.Second * 5)
ctxb := context.Background()
// Launch notification clients for all nodes, such that we can
// get notified when they discover new channels and updates
// in the graph.
aliceUpdates, aQuit := subscribeGraphNotifications(t, ctxb, net.Alice)
defer close(aQuit)
bobUpdates, bQuit := subscribeGraphNotifications(t, ctxb, net.Bob)
defer close(bQuit)
chanAmt := maxFundingAmount
pushAmt := btcutil.Amount(100000)
// Create a channel Alice->Bob.
ctxt, _ := context.WithTimeout(ctxb, timeout)
chanPoint := openChannelAndAssert(ctxt, t, net, net.Alice, net.Bob,
chanAmt, pushAmt)
ctxt, _ = context.WithTimeout(ctxb, time.Second*15)
err := net.Alice.WaitForNetworkChannelOpen(ctxt, chanPoint)
if err != nil {
t.Fatalf("alice didn't report channel: %v", err)
}
err = net.Bob.WaitForNetworkChannelOpen(ctxt, chanPoint)
if err != nil {
t.Fatalf("bob didn't report channel: %v", err)
}
// Create Carol and a new channel Bob->Carol.
carol, err := net.NewNode(nil)
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
carolUpdates, cQuit := subscribeGraphNotifications(t, ctxb, carol)
defer close(cQuit)
if err := net.ConnectNodes(ctxb, carol, net.Bob); err != nil {
t.Fatalf("unable to connect dave to alice: %v", err)
}
ctxt, _ = context.WithTimeout(ctxb, timeout)
chanPoint2 := openChannelAndAssert(ctxt, t, net, net.Bob, carol,
chanAmt, pushAmt)
ctxt, _ = context.WithTimeout(ctxb, time.Second*15)
err = net.Bob.WaitForNetworkChannelOpen(ctxt, chanPoint2)
if err != nil {
t.Fatalf("bob didn't report channel: %v", err)
}
err = carol.WaitForNetworkChannelOpen(ctxt, chanPoint2)
if err != nil {
t.Fatalf("carol didn't report channel: %v", err)
}
// Update the fees for the channel Alice->Bob, and make sure
// all nodes learn about it.
const feeBase = 1000000
baseFee := int64(1500)
feeRate := int64(12)
timeLockDelta := uint32(66)
req := &lnrpc.PolicyUpdateRequest{
BaseFeeMsat: baseFee,
FeeRate: float64(feeRate),
TimeLockDelta: timeLockDelta,
}
req.Scope = &lnrpc.PolicyUpdateRequest_ChanPoint{
ChanPoint: chanPoint,
}
_, err = net.Alice.UpdateChannelPolicy(ctxb, req)
if err != nil {
t.Fatalf("unable to get alice's balance: %v", err)
}
// txStr returns the string representation of the channel's
// funding tx.
txStr := func(chanPoint *lnrpc.ChannelPoint) string {
fundingTxID, err := chainhash.NewHash(chanPoint.FundingTxid)
if err != nil {
return ""
}
cp := wire.OutPoint{
Hash: *fundingTxID,
Index: chanPoint.OutputIndex,
}
return cp.String()
}
// A closure that is used to wait for a channel updates that matches
// the channel policy update done by Alice.
waitForChannelUpdate := func(graphUpdates chan *lnrpc.GraphTopologyUpdate,
chanPoints ...*lnrpc.ChannelPoint) {
// Create a map containing all the channel points we are
// waiting for updates for.
cps := make(map[string]bool)
for _, chanPoint := range chanPoints {
cps[txStr(chanPoint)] = true
}
Loop:
for {
select {
case graphUpdate := <-graphUpdates:
if len(graphUpdate.ChannelUpdates) == 0 {
continue
}
chanUpdate := graphUpdate.ChannelUpdates[0]
fundingTxStr := txStr(chanUpdate.ChanPoint)
if _, ok := cps[fundingTxStr]; !ok {
continue
}
if chanUpdate.AdvertisingNode != net.Alice.PubKeyStr {
continue
}
policy := chanUpdate.RoutingPolicy
if policy.FeeBaseMsat != baseFee {
continue
}
if policy.FeeRateMilliMsat != feeRate*feeBase {
continue
}
if policy.TimeLockDelta != timeLockDelta {
continue
}
// We got a policy update that matched the
// values and channel point of what we
// expected, delete it from the map.
delete(cps, fundingTxStr)
// If we have no more channel points we are
// waiting for, break out of the loop.
if len(cps) == 0 {
break Loop
}
case <-time.After(20 * time.Second):
t.Fatalf("did not receive channel update")
}
}
}
// Wait for all nodes to have seen the policy update done by Alice.
waitForChannelUpdate(aliceUpdates, chanPoint)
waitForChannelUpdate(bobUpdates, chanPoint)
waitForChannelUpdate(carolUpdates, chanPoint)
// assertChannelPolicy asserts that the passed node's known channel
// policy for the passed chanPoint is consistent with Alice's current
// expected policy values.
assertChannelPolicy := func(node *lntest.HarnessNode,
chanPoint *lnrpc.ChannelPoint) {
// Get a DescribeGraph from the node.
descReq := &lnrpc.ChannelGraphRequest{}
chanGraph, err := node.DescribeGraph(ctxb, descReq)
if err != nil {
t.Fatalf("unable to query for alice's routing table: %v",
err)
}
edgeFound := false
for _, e := range chanGraph.Edges {
if e.ChanPoint == txStr(chanPoint) {
edgeFound = true
if e.Node1Pub == net.Alice.PubKeyStr {
if e.Node1Policy.FeeBaseMsat != baseFee {
t.Fatalf("expected base fee "+
"%v, got %v", baseFee,
e.Node1Policy.FeeBaseMsat)
}
if e.Node1Policy.FeeRateMilliMsat != feeRate*feeBase {
t.Fatalf("expected fee rate "+
"%v, got %v", feeRate*feeBase,
e.Node1Policy.FeeRateMilliMsat)
}
if e.Node1Policy.TimeLockDelta != timeLockDelta {
t.Fatalf("expected time lock "+
"delta %v, got %v",
timeLockDelta,
e.Node1Policy.TimeLockDelta)
}
} else {
if e.Node2Policy.FeeBaseMsat != baseFee {
t.Fatalf("expected base fee "+
"%v, got %v", baseFee,
e.Node2Policy.FeeBaseMsat)
}
if e.Node2Policy.FeeRateMilliMsat != feeRate*feeBase {
t.Fatalf("expected fee rate "+
"%v, got %v", feeRate*feeBase,
e.Node2Policy.FeeRateMilliMsat)
}
if e.Node2Policy.TimeLockDelta != timeLockDelta {
t.Fatalf("expected time lock "+
"delta %v, got %v",
timeLockDelta,
e.Node2Policy.TimeLockDelta)
}
}
}
}
if !edgeFound {
t.Fatalf("did not find edge")
}
}
// Check that all nodes now know about Alice's updated policy.
assertChannelPolicy(net.Alice, chanPoint)
assertChannelPolicy(net.Bob, chanPoint)
assertChannelPolicy(carol, chanPoint)
// Open channel to Carol.
if err := net.ConnectNodes(ctxb, net.Alice, carol); err != nil {
t.Fatalf("unable to connect dave to alice: %v", err)
}
ctxt, _ = context.WithTimeout(ctxb, timeout)
chanPoint3 := openChannelAndAssert(ctxt, t, net, net.Alice, carol,
chanAmt, pushAmt)
ctxt, _ = context.WithTimeout(ctxb, time.Second*15)
err = net.Alice.WaitForNetworkChannelOpen(ctxt, chanPoint3)
if err != nil {
t.Fatalf("alice didn't report channel: %v", err)
}
err = carol.WaitForNetworkChannelOpen(ctxt, chanPoint3)
if err != nil {
t.Fatalf("bob didn't report channel: %v", err)
}
// Make a global update, and check that both channels'
// new policies get propagated.
baseFee = int64(800)
feeRate = int64(123)
timeLockDelta = uint32(22)
req = &lnrpc.PolicyUpdateRequest{
BaseFeeMsat: baseFee,
FeeRate: float64(feeRate),
TimeLockDelta: timeLockDelta,
}
req.Scope = &lnrpc.PolicyUpdateRequest_Global{}
_, err = net.Alice.UpdateChannelPolicy(ctxb, req)
if err != nil {
t.Fatalf("unable to get alice's balance: %v", err)
}
// Wait for all nodes to have seen the policy updates
// for both of Alice's channels.
waitForChannelUpdate(aliceUpdates, chanPoint, chanPoint3)
waitForChannelUpdate(bobUpdates, chanPoint, chanPoint3)
waitForChannelUpdate(carolUpdates, chanPoint, chanPoint3)
// And finally check that all nodes remembers the policy
// update they received.
assertChannelPolicy(net.Alice, chanPoint)
assertChannelPolicy(net.Bob, chanPoint)
assertChannelPolicy(carol, chanPoint)
assertChannelPolicy(net.Alice, chanPoint3)
assertChannelPolicy(net.Bob, chanPoint3)
assertChannelPolicy(carol, chanPoint3)
// Close the channels.
ctxt, _ = context.WithTimeout(ctxb, timeout)
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, false)
ctxt, _ = context.WithTimeout(ctxb, timeout)
closeChannelAndAssert(ctxt, t, net, net.Bob, chanPoint2, false)
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint3, false)
ctxt, _ = context.WithTimeout(ctxb, timeout)
// Clean up carol's node.
if err := net.ShutdownNode(carol); err != nil {
t.Fatalf("unable to shutdown carol: %v", err)
}
}
// testOpenChannelAfterReorg tests that in the case where we have an open
// channel where the funding tx gets reorged out, the channel will no
// longer be present in the node's routing table.
@ -793,7 +1077,7 @@ func testChannelFundingPersistence(net *lntest.NetworkHarness, t *harnessTest) {
// confirmation before it's open, with the current set of defaults,
// we'll need to create a new node instance.
const numConfs = 5
carolArgs := []string{fmt.Sprintf("--defaultchanconfs=%v", numConfs)}
carolArgs := []string{fmt.Sprintf("--bitcoin.defaultchanconfs=%v", numConfs)}
carol, err := net.NewNode(carolArgs)
if err != nil {
t.Fatalf("unable to create new node: %v", err)
@ -1095,7 +1379,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) {
// TODO(roasbeef): should check default value in config here
// instead, or make delay a param
defaultCSV := uint32(4)
defaultCLTV := defaultBitcoinForwardingPolicy.TimeLockDelta
defaultCLTV := uint32(defaultBitcoinTimeLockDelta)
// Since we'd like to test failure scenarios with outstanding htlcs,
// we'll introduce another node into our test network: Carol.
@ -3878,28 +4162,22 @@ out:
}
}
func testGraphTopologyNotifications(net *lntest.NetworkHarness, t *harnessTest) {
const chanAmt = maxFundingAmount
timeout := time.Duration(time.Second * 5)
ctxb := context.Background()
// We'll first start by establishing a notification client to Alice which
// will send us notifications upon detected changes in the channel graph.
// subscribeGraphNotifications subscribes to channel graph updates and launches
// a goroutine that forwards these to the returned channel.
func subscribeGraphNotifications(t *harnessTest, ctxb context.Context,
node *lntest.HarnessNode) (chan *lnrpc.GraphTopologyUpdate, chan struct{}) {
// We'll first start by establishing a notification client which will
// send us notifications upon detected changes in the channel graph.
req := &lnrpc.GraphTopologySubscription{}
topologyClient, err := net.Alice.SubscribeChannelGraph(ctxb, req)
topologyClient, err := node.SubscribeChannelGraph(ctxb, req)
if err != nil {
t.Fatalf("unable to create topology client: %v", err)
}
// Open a new channel between Alice and Bob.
ctxt, _ := context.WithTimeout(ctxb, timeout)
chanPoint := openChannelAndAssert(ctxt, t, net, net.Alice, net.Bob,
chanAmt, 0)
// We'll launch a goroutine that'll be responsible for proxying all
// notifications recv'd from the client into the channel below.
quit := make(chan struct{})
graphUpdates := make(chan *lnrpc.GraphTopologyUpdate, 4)
graphUpdates := make(chan *lnrpc.GraphTopologyUpdate, 20)
go func() {
for {
select {
@ -3916,7 +4194,8 @@ func testGraphTopologyNotifications(net *lntest.NetworkHarness, t *harnessTest)
if err == io.EOF {
return
} else if err != nil {
t.Fatalf("unable to recv graph update: %v", err)
t.Fatalf("unable to recv graph update: %v",
err)
}
select {
@ -3927,6 +4206,21 @@ func testGraphTopologyNotifications(net *lntest.NetworkHarness, t *harnessTest)
}
}
}()
return graphUpdates, quit
}
func testGraphTopologyNotifications(net *lntest.NetworkHarness, t *harnessTest) {
const chanAmt = maxFundingAmount
timeout := time.Duration(time.Second * 5)
ctxb := context.Background()
// Let Alice subscribe to graph notifications.
graphUpdates, quit := subscribeGraphNotifications(t, ctxb, net.Alice)
// Open a new channel between Alice and Bob.
ctxt, _ := context.WithTimeout(ctxb, timeout)
chanPoint := openChannelAndAssert(ctxt, t, net, net.Alice, net.Bob,
chanAmt, 0)
// The channel opening above should've triggered a few notifications
// sent to the notification client. We'll expect two channel updates,
@ -4680,6 +4974,10 @@ var testsCases = []*testCase{
name: "basic funding flow",
test: testBasicChannelFunding,
},
{
name: "update channel policy",
test: testUpdateChannelPolicy,
},
{
name: "open channel reorg test",
test: testOpenChannelAfterReorg,

@ -98,8 +98,8 @@ It has these top-level messages:
FeeReportRequest
ChannelFeeReport
FeeReportResponse
FeeUpdateRequest
FeeUpdateResponse
PolicyUpdateRequest
PolicyUpdateResponse
*/
package lnrpc
@ -1555,6 +1555,8 @@ type OpenChannelRequest struct {
SatPerByte int64 `protobuf:"varint,7,opt,name=sat_per_byte,json=satPerByte" json:"sat_per_byte,omitempty"`
// / Whether this channel should be private, not announced to the greater network.
Private bool `protobuf:"varint,8,opt,name=private" json:"private,omitempty"`
// / The minimum value in millisatoshi we will require for incoming HTLCs on the channel.
MinHtlcMsat int64 `protobuf:"varint,9,opt,name=min_htlc_msat" json:"min_htlc_msat,omitempty"`
}
func (m *OpenChannelRequest) Reset() { *m = OpenChannelRequest{} }
@ -1618,6 +1620,13 @@ func (m *OpenChannelRequest) GetPrivate() bool {
return false
}
func (m *OpenChannelRequest) GetMinHtlcMsat() int64 {
if m != nil {
return m.MinHtlcMsat
}
return 0
}
type OpenStatusUpdate struct {
// Types that are valid to be assigned to Update:
// *OpenStatusUpdate_ChanPending
@ -3477,111 +3486,120 @@ func (m *FeeReportResponse) GetChannelFees() []*ChannelFeeReport {
return nil
}
type FeeUpdateRequest struct {
type PolicyUpdateRequest struct {
// Types that are valid to be assigned to Scope:
// *FeeUpdateRequest_Global
// *FeeUpdateRequest_ChanPoint
Scope isFeeUpdateRequest_Scope `protobuf_oneof:"scope"`
// *PolicyUpdateRequest_Global
// *PolicyUpdateRequest_ChanPoint
Scope isPolicyUpdateRequest_Scope `protobuf_oneof:"scope"`
// / The base fee charged regardless of the number of milli-satoshis sent.
BaseFeeMsat int64 `protobuf:"varint,3,opt,name=base_fee_msat" json:"base_fee_msat,omitempty"`
// / The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6.
FeeRate float64 `protobuf:"fixed64,4,opt,name=fee_rate" json:"fee_rate,omitempty"`
// / The required timelock delta for HTLCs forwarded over the channel.
TimeLockDelta uint32 `protobuf:"varint,5,opt,name=time_lock_delta" json:"time_lock_delta,omitempty"`
}
func (m *FeeUpdateRequest) Reset() { *m = FeeUpdateRequest{} }
func (m *FeeUpdateRequest) String() string { return proto.CompactTextString(m) }
func (*FeeUpdateRequest) ProtoMessage() {}
func (*FeeUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{90} }
func (m *PolicyUpdateRequest) Reset() { *m = PolicyUpdateRequest{} }
func (m *PolicyUpdateRequest) String() string { return proto.CompactTextString(m) }
func (*PolicyUpdateRequest) ProtoMessage() {}
func (*PolicyUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{90} }
type isFeeUpdateRequest_Scope interface {
isFeeUpdateRequest_Scope()
type isPolicyUpdateRequest_Scope interface {
isPolicyUpdateRequest_Scope()
}
type FeeUpdateRequest_Global struct {
type PolicyUpdateRequest_Global struct {
Global bool `protobuf:"varint,1,opt,name=global,oneof"`
}
type FeeUpdateRequest_ChanPoint struct {
type PolicyUpdateRequest_ChanPoint struct {
ChanPoint *ChannelPoint `protobuf:"bytes,2,opt,name=chan_point,oneof"`
}
func (*FeeUpdateRequest_Global) isFeeUpdateRequest_Scope() {}
func (*FeeUpdateRequest_ChanPoint) isFeeUpdateRequest_Scope() {}
func (*PolicyUpdateRequest_Global) isPolicyUpdateRequest_Scope() {}
func (*PolicyUpdateRequest_ChanPoint) isPolicyUpdateRequest_Scope() {}
func (m *FeeUpdateRequest) GetScope() isFeeUpdateRequest_Scope {
func (m *PolicyUpdateRequest) GetScope() isPolicyUpdateRequest_Scope {
if m != nil {
return m.Scope
}
return nil
}
func (m *FeeUpdateRequest) GetGlobal() bool {
if x, ok := m.GetScope().(*FeeUpdateRequest_Global); ok {
func (m *PolicyUpdateRequest) GetGlobal() bool {
if x, ok := m.GetScope().(*PolicyUpdateRequest_Global); ok {
return x.Global
}
return false
}
func (m *FeeUpdateRequest) GetChanPoint() *ChannelPoint {
if x, ok := m.GetScope().(*FeeUpdateRequest_ChanPoint); ok {
func (m *PolicyUpdateRequest) GetChanPoint() *ChannelPoint {
if x, ok := m.GetScope().(*PolicyUpdateRequest_ChanPoint); ok {
return x.ChanPoint
}
return nil
}
func (m *FeeUpdateRequest) GetBaseFeeMsat() int64 {
func (m *PolicyUpdateRequest) GetBaseFeeMsat() int64 {
if m != nil {
return m.BaseFeeMsat
}
return 0
}
func (m *FeeUpdateRequest) GetFeeRate() float64 {
func (m *PolicyUpdateRequest) GetFeeRate() float64 {
if m != nil {
return m.FeeRate
}
return 0
}
func (m *PolicyUpdateRequest) GetTimeLockDelta() uint32 {
if m != nil {
return m.TimeLockDelta
}
return 0
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*FeeUpdateRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _FeeUpdateRequest_OneofMarshaler, _FeeUpdateRequest_OneofUnmarshaler, _FeeUpdateRequest_OneofSizer, []interface{}{
(*FeeUpdateRequest_Global)(nil),
(*FeeUpdateRequest_ChanPoint)(nil),
func (*PolicyUpdateRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _PolicyUpdateRequest_OneofMarshaler, _PolicyUpdateRequest_OneofUnmarshaler, _PolicyUpdateRequest_OneofSizer, []interface{}{
(*PolicyUpdateRequest_Global)(nil),
(*PolicyUpdateRequest_ChanPoint)(nil),
}
}
func _FeeUpdateRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*FeeUpdateRequest)
func _PolicyUpdateRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*PolicyUpdateRequest)
// scope
switch x := m.Scope.(type) {
case *FeeUpdateRequest_Global:
case *PolicyUpdateRequest_Global:
t := uint64(0)
if x.Global {
t = 1
}
b.EncodeVarint(1<<3 | proto.WireVarint)
b.EncodeVarint(t)
case *FeeUpdateRequest_ChanPoint:
case *PolicyUpdateRequest_ChanPoint:
b.EncodeVarint(2<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.ChanPoint); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("FeeUpdateRequest.Scope has unexpected type %T", x)
return fmt.Errorf("PolicyUpdateRequest.Scope has unexpected type %T", x)
}
return nil
}
func _FeeUpdateRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*FeeUpdateRequest)
func _PolicyUpdateRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*PolicyUpdateRequest)
switch tag {
case 1: // scope.global
if wire != proto.WireVarint {
return true, proto.ErrInternalBadWireType
}
x, err := b.DecodeVarint()
m.Scope = &FeeUpdateRequest_Global{x != 0}
m.Scope = &PolicyUpdateRequest_Global{x != 0}
return true, err
case 2: // scope.chan_point
if wire != proto.WireBytes {
@ -3589,21 +3607,21 @@ func _FeeUpdateRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *pro
}
msg := new(ChannelPoint)
err := b.DecodeMessage(msg)
m.Scope = &FeeUpdateRequest_ChanPoint{msg}
m.Scope = &PolicyUpdateRequest_ChanPoint{msg}
return true, err
default:
return false, nil
}
}
func _FeeUpdateRequest_OneofSizer(msg proto.Message) (n int) {
m := msg.(*FeeUpdateRequest)
func _PolicyUpdateRequest_OneofSizer(msg proto.Message) (n int) {
m := msg.(*PolicyUpdateRequest)
// scope
switch x := m.Scope.(type) {
case *FeeUpdateRequest_Global:
case *PolicyUpdateRequest_Global:
n += proto.SizeVarint(1<<3 | proto.WireVarint)
n += 1
case *FeeUpdateRequest_ChanPoint:
case *PolicyUpdateRequest_ChanPoint:
s := proto.Size(x.ChanPoint)
n += proto.SizeVarint(2<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
@ -3615,13 +3633,13 @@ func _FeeUpdateRequest_OneofSizer(msg proto.Message) (n int) {
return n
}
type FeeUpdateResponse struct {
type PolicyUpdateResponse struct {
}
func (m *FeeUpdateResponse) Reset() { *m = FeeUpdateResponse{} }
func (m *FeeUpdateResponse) String() string { return proto.CompactTextString(m) }
func (*FeeUpdateResponse) ProtoMessage() {}
func (*FeeUpdateResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{91} }
func (m *PolicyUpdateResponse) Reset() { *m = PolicyUpdateResponse{} }
func (m *PolicyUpdateResponse) String() string { return proto.CompactTextString(m) }
func (*PolicyUpdateResponse) ProtoMessage() {}
func (*PolicyUpdateResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{91} }
func init() {
proto.RegisterType((*CreateWalletRequest)(nil), "lnrpc.CreateWalletRequest")
@ -3718,8 +3736,8 @@ func init() {
proto.RegisterType((*FeeReportRequest)(nil), "lnrpc.FeeReportRequest")
proto.RegisterType((*ChannelFeeReport)(nil), "lnrpc.ChannelFeeReport")
proto.RegisterType((*FeeReportResponse)(nil), "lnrpc.FeeReportResponse")
proto.RegisterType((*FeeUpdateRequest)(nil), "lnrpc.FeeUpdateRequest")
proto.RegisterType((*FeeUpdateResponse)(nil), "lnrpc.FeeUpdateResponse")
proto.RegisterType((*PolicyUpdateRequest)(nil), "lnrpc.PolicyUpdateRequest")
proto.RegisterType((*PolicyUpdateResponse)(nil), "lnrpc.PolicyUpdateResponse")
proto.RegisterEnum("lnrpc.NewAddressRequest_AddressType", NewAddressRequest_AddressType_name, NewAddressRequest_AddressType_value)
}
@ -4033,10 +4051,10 @@ type LightningClient interface {
// FeeReport allows the caller to obtain a report detailing the current fee
// schedule enforced by the node globally for each channel.
FeeReport(ctx context.Context, in *FeeReportRequest, opts ...grpc.CallOption) (*FeeReportResponse, error)
// * lncli: `updatefees`
// UpdateFees allows the caller to update the fee schedule for all channels
// globally, or a particular channel.
UpdateFees(ctx context.Context, in *FeeUpdateRequest, opts ...grpc.CallOption) (*FeeUpdateResponse, error)
// * lncli: `updatechanpolicy`
// UpdateChannelPolicy allows the caller to update the fee schedule and
// channel policies for all channels globally, or a particular channel.
UpdateChannelPolicy(ctx context.Context, in *PolicyUpdateRequest, opts ...grpc.CallOption) (*PolicyUpdateResponse, error)
}
type lightningClient struct {
@ -4517,9 +4535,9 @@ func (c *lightningClient) FeeReport(ctx context.Context, in *FeeReportRequest, o
return out, nil
}
func (c *lightningClient) UpdateFees(ctx context.Context, in *FeeUpdateRequest, opts ...grpc.CallOption) (*FeeUpdateResponse, error) {
out := new(FeeUpdateResponse)
err := grpc.Invoke(ctx, "/lnrpc.Lightning/UpdateFees", in, out, c.cc, opts...)
func (c *lightningClient) UpdateChannelPolicy(ctx context.Context, in *PolicyUpdateRequest, opts ...grpc.CallOption) (*PolicyUpdateResponse, error) {
out := new(PolicyUpdateResponse)
err := grpc.Invoke(ctx, "/lnrpc.Lightning/UpdateChannelPolicy", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
@ -4719,10 +4737,10 @@ type LightningServer interface {
// FeeReport allows the caller to obtain a report detailing the current fee
// schedule enforced by the node globally for each channel.
FeeReport(context.Context, *FeeReportRequest) (*FeeReportResponse, error)
// * lncli: `updatefees`
// UpdateFees allows the caller to update the fee schedule for all channels
// globally, or a particular channel.
UpdateFees(context.Context, *FeeUpdateRequest) (*FeeUpdateResponse, error)
// * lncli: `updatechanpolicy`
// UpdateChannelPolicy allows the caller to update the fee schedule and
// channel policies for all channels globally, or a particular channel.
UpdateChannelPolicy(context.Context, *PolicyUpdateRequest) (*PolicyUpdateResponse, error)
}
func RegisterLightningServer(s *grpc.Server, srv LightningServer) {
@ -5418,20 +5436,20 @@ func _Lightning_FeeReport_Handler(srv interface{}, ctx context.Context, dec func
return interceptor(ctx, in, info, handler)
}
func _Lightning_UpdateFees_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(FeeUpdateRequest)
func _Lightning_UpdateChannelPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PolicyUpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(LightningServer).UpdateFees(ctx, in)
return srv.(LightningServer).UpdateChannelPolicy(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/lnrpc.Lightning/UpdateFees",
FullMethod: "/lnrpc.Lightning/UpdateChannelPolicy",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LightningServer).UpdateFees(ctx, req.(*FeeUpdateRequest))
return srv.(LightningServer).UpdateChannelPolicy(ctx, req.(*PolicyUpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
@ -5565,8 +5583,8 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{
Handler: _Lightning_FeeReport_Handler,
},
{
MethodName: "UpdateFees",
Handler: _Lightning_UpdateFees_Handler,
MethodName: "UpdateChannelPolicy",
Handler: _Lightning_UpdateChannelPolicy_Handler,
},
},
Streams: []grpc.StreamDesc{
@ -5608,309 +5626,310 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("rpc.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 4855 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x7b, 0xcd, 0x8f, 0x1c, 0x49,
0x56, 0xb8, 0xb3, 0xba, 0xfa, 0xa3, 0x5e, 0x55, 0xf5, 0x47, 0x74, 0xbb, 0xbb, 0x5c, 0xf6, 0x78,
0xed, 0xd8, 0xd1, 0x4c, 0xff, 0xfc, 0x1b, 0xdc, 0x76, 0x2f, 0x3b, 0xcc, 0x8e, 0x81, 0x91, 0xbf,
0x7b, 0xd8, 0x1e, 0x4f, 0x6f, 0xb6, 0x67, 0x06, 0x76, 0x85, 0x8a, 0xec, 0xaa, 0xe8, 0xea, 0x5c,
0x67, 0x65, 0xe6, 0x64, 0x46, 0x75, 0xbb, 0xd6, 0x58, 0x82, 0x05, 0x21, 0x21, 0x81, 0xf6, 0x00,
0x02, 0xed, 0x61, 0xb9, 0x70, 0x81, 0x03, 0xfc, 0x03, 0x48, 0xfc, 0x01, 0x2b, 0x21, 0x90, 0xf6,
0x84, 0xc4, 0x0d, 0x4e, 0xcb, 0x99, 0x3b, 0x7a, 0xf1, 0x95, 0x11, 0x99, 0xd9, 0xb6, 0x97, 0x5d,
0xb8, 0x55, 0xbc, 0x78, 0xf9, 0x22, 0xe2, 0xc5, 0x8b, 0xf7, 0x5d, 0xd0, 0xca, 0xd2, 0xe1, 0xcd,
0x34, 0x4b, 0x78, 0x42, 0xe6, 0xa3, 0x38, 0x4b, 0x87, 0xfd, 0x2b, 0xe3, 0x24, 0x19, 0x47, 0x6c,
0x27, 0x48, 0xc3, 0x9d, 0x20, 0x8e, 0x13, 0x1e, 0xf0, 0x30, 0x89, 0x73, 0x89, 0x44, 0x6f, 0xc3,
0xfa, 0xfd, 0x8c, 0x05, 0x9c, 0x7d, 0x11, 0x44, 0x11, 0xe3, 0x3e, 0xfb, 0x72, 0xca, 0x72, 0x4e,
0xfa, 0xb0, 0x94, 0x06, 0x79, 0x7e, 0x96, 0x64, 0xa3, 0x9e, 0x77, 0xcd, 0xdb, 0xee, 0xf8, 0x66,
0x4c, 0x37, 0x61, 0xc3, 0xfd, 0x24, 0x4f, 0x93, 0x38, 0x67, 0x48, 0xea, 0xb3, 0x38, 0x4a, 0x86,
0xcf, 0x7e, 0x26, 0x52, 0xee, 0x27, 0x8a, 0xd4, 0x0f, 0x1b, 0xd0, 0x7e, 0x9a, 0x05, 0x71, 0x1e,
0x0c, 0x71, 0xb3, 0xa4, 0x07, 0x8b, 0xfc, 0xf9, 0xe0, 0x24, 0xc8, 0x4f, 0x04, 0x89, 0x96, 0xaf,
0x87, 0x64, 0x13, 0x16, 0x82, 0x49, 0x32, 0x8d, 0x79, 0xaf, 0x71, 0xcd, 0xdb, 0x9e, 0xf3, 0xd5,
0x88, 0xbc, 0x07, 0x6b, 0xf1, 0x74, 0x32, 0x18, 0x26, 0xf1, 0x71, 0x98, 0x4d, 0xe4, 0x91, 0x7b,
0x73, 0xd7, 0xbc, 0xed, 0x79, 0xbf, 0x3a, 0x41, 0xae, 0x02, 0x1c, 0xe1, 0x36, 0xe4, 0x12, 0x4d,
0xb1, 0x84, 0x05, 0x21, 0x14, 0x3a, 0x6a, 0xc4, 0xc2, 0xf1, 0x09, 0xef, 0xcd, 0x0b, 0x42, 0x0e,
0x0c, 0x69, 0xf0, 0x70, 0xc2, 0x06, 0x39, 0x0f, 0x26, 0x69, 0x6f, 0x41, 0xec, 0xc6, 0x82, 0x88,
0xf9, 0x84, 0x07, 0xd1, 0xe0, 0x98, 0xb1, 0xbc, 0xb7, 0xa8, 0xe6, 0x0d, 0x84, 0xbc, 0x03, 0xcb,
0x23, 0x96, 0xf3, 0x41, 0x30, 0x1a, 0x65, 0x2c, 0xcf, 0x59, 0xde, 0x5b, 0xba, 0x36, 0xb7, 0xdd,
0xf2, 0x4b, 0x50, 0xda, 0x83, 0xcd, 0xc7, 0x8c, 0x5b, 0xdc, 0xc9, 0x15, 0xa7, 0xe9, 0x3e, 0x10,
0x0b, 0xfc, 0x80, 0xf1, 0x20, 0x8c, 0x72, 0xf2, 0x3e, 0x74, 0xb8, 0x85, 0xdc, 0xf3, 0xae, 0xcd,
0x6d, 0xb7, 0x77, 0xc9, 0x4d, 0x21, 0x1d, 0x37, 0xad, 0x0f, 0x7c, 0x07, 0x8f, 0xfe, 0x8b, 0x07,
0xed, 0x43, 0x16, 0x8f, 0xf4, 0x3d, 0x12, 0x68, 0xe2, 0x4e, 0xd4, 0x1d, 0x8a, 0xdf, 0xe4, 0x2b,
0xd0, 0x16, 0xbb, 0xcb, 0x79, 0x16, 0xc6, 0x63, 0x71, 0x05, 0x2d, 0x1f, 0x10, 0x74, 0x28, 0x20,
0x64, 0x15, 0xe6, 0x82, 0x09, 0x17, 0x8c, 0x9f, 0xf3, 0xf1, 0x27, 0xb9, 0x0e, 0x9d, 0x34, 0x98,
0x4d, 0x58, 0xcc, 0x0b, 0x66, 0x77, 0xfc, 0xb6, 0x82, 0xed, 0x21, 0xb7, 0x6f, 0xc2, 0xba, 0x8d,
0xa2, 0xa9, 0xcf, 0x0b, 0xea, 0x6b, 0x16, 0xa6, 0x5a, 0xe4, 0x5d, 0x58, 0xd1, 0xf8, 0x99, 0xdc,
0xac, 0x60, 0x7f, 0xcb, 0x5f, 0x56, 0x60, 0xcd, 0xa0, 0x3f, 0xf7, 0xa0, 0x23, 0x8f, 0x24, 0xe5,
0x8c, 0xbc, 0x0d, 0x5d, 0xfd, 0x25, 0xcb, 0xb2, 0x24, 0x53, 0xd2, 0xe5, 0x02, 0xc9, 0x0d, 0x58,
0xd5, 0x80, 0x34, 0x63, 0xe1, 0x24, 0x18, 0x33, 0x71, 0xd4, 0x8e, 0x5f, 0x81, 0x93, 0xdd, 0x82,
0x62, 0x96, 0x4c, 0x39, 0x13, 0x47, 0x6f, 0xef, 0x76, 0x14, 0xbb, 0x7d, 0x84, 0xf9, 0x2e, 0x0a,
0xfd, 0xbe, 0x07, 0x9d, 0xfb, 0x27, 0x41, 0x1c, 0xb3, 0xe8, 0x20, 0x09, 0x63, 0x8e, 0xe2, 0x76,
0x3c, 0x8d, 0x47, 0x61, 0x3c, 0x1e, 0xf0, 0xe7, 0xa1, 0x7e, 0x36, 0x0e, 0x0c, 0x37, 0x65, 0x8f,
0x91, 0x49, 0x8a, 0xff, 0x15, 0x38, 0xd2, 0x4b, 0xa6, 0x3c, 0x9d, 0xf2, 0x41, 0x18, 0x8f, 0xd8,
0x73, 0xb1, 0xa7, 0xae, 0xef, 0xc0, 0xe8, 0xaf, 0xc3, 0xea, 0x3e, 0xca, 0x71, 0x1c, 0xc6, 0xe3,
0xbb, 0x52, 0xd8, 0xf0, 0x71, 0xa5, 0xd3, 0xa3, 0x67, 0x6c, 0xa6, 0xf8, 0xa2, 0x46, 0x28, 0x0a,
0x27, 0x49, 0xce, 0xd5, 0x7a, 0xe2, 0x37, 0xfd, 0x77, 0x0f, 0x56, 0x90, 0xb7, 0x9f, 0x04, 0xf1,
0x4c, 0x8b, 0xcc, 0x3e, 0x74, 0x90, 0xd4, 0xd3, 0xe4, 0xae, 0x7c, 0xa2, 0x52, 0xf4, 0xb6, 0x15,
0x2f, 0x4a, 0xd8, 0x37, 0x6d, 0xd4, 0x87, 0x31, 0xcf, 0x66, 0xbe, 0xf3, 0x35, 0x0a, 0x1b, 0x0f,
0xb2, 0x31, 0xe3, 0xe2, 0xf1, 0xaa, 0xc7, 0x0c, 0x12, 0x74, 0x3f, 0x89, 0x8f, 0xc9, 0x35, 0xe8,
0xe4, 0x01, 0x1f, 0xa4, 0x2c, 0x1b, 0x1c, 0xcd, 0x38, 0x13, 0x02, 0x33, 0xe7, 0x43, 0x1e, 0xf0,
0x03, 0x96, 0xdd, 0x9b, 0x71, 0xd6, 0xff, 0x08, 0xd6, 0x2a, 0xab, 0xa0, 0x8c, 0x16, 0x47, 0xc4,
0x9f, 0x64, 0x03, 0xe6, 0x4f, 0x83, 0x68, 0xca, 0x94, 0x4e, 0x91, 0x83, 0x0f, 0x1b, 0x1f, 0x78,
0xf4, 0x1d, 0x58, 0x2d, 0xb6, 0xad, 0x84, 0x88, 0x40, 0xd3, 0xdc, 0x52, 0xcb, 0x17, 0xbf, 0xe9,
0xef, 0x7b, 0x12, 0xf1, 0x7e, 0x12, 0x9a, 0xf7, 0x89, 0x88, 0xf8, 0x8c, 0x35, 0x22, 0xfe, 0x3e,
0x57, 0x7f, 0xfd, 0xfc, 0x87, 0xa5, 0xef, 0xc2, 0x9a, 0xb5, 0x85, 0x57, 0x6c, 0xf6, 0xaf, 0x3c,
0x58, 0x7b, 0xc2, 0xce, 0xd4, 0xad, 0xeb, 0xdd, 0x7e, 0x00, 0x4d, 0x3e, 0x4b, 0x99, 0xc0, 0x5c,
0xde, 0x7d, 0x5b, 0x5d, 0x5a, 0x05, 0xef, 0xa6, 0x1a, 0x3e, 0x9d, 0xa5, 0xcc, 0x17, 0x5f, 0xd0,
0x4f, 0xa1, 0x6d, 0x01, 0xc9, 0x16, 0xac, 0x7f, 0xf1, 0xf1, 0xd3, 0x27, 0x0f, 0x0f, 0x0f, 0x07,
0x07, 0x9f, 0xdd, 0xfb, 0xe6, 0xc3, 0xdf, 0x1a, 0xec, 0xdd, 0x3d, 0xdc, 0x5b, 0xbd, 0x40, 0x36,
0x81, 0x3c, 0x79, 0x78, 0xf8, 0xf4, 0xe1, 0x03, 0x07, 0xee, 0x91, 0x15, 0x68, 0xdb, 0x80, 0x06,
0xed, 0x43, 0xef, 0x09, 0x3b, 0xfb, 0x22, 0xe4, 0x31, 0xcb, 0x73, 0x77, 0x79, 0x7a, 0x13, 0x88,
0xbd, 0x27, 0x75, 0xcc, 0x1e, 0x2c, 0x2a, 0x8d, 0xa9, 0x0d, 0x86, 0x1a, 0xd2, 0x77, 0x80, 0x1c,
0x86, 0xe3, 0xf8, 0x13, 0x96, 0xe7, 0xc1, 0x98, 0xe9, 0xc3, 0xae, 0xc2, 0xdc, 0x24, 0x1f, 0xab,
0x87, 0x86, 0x3f, 0xe9, 0xd7, 0x60, 0xdd, 0xc1, 0x53, 0x84, 0xaf, 0x40, 0x2b, 0x0f, 0xc7, 0x71,
0xc0, 0xa7, 0x19, 0x53, 0xa4, 0x0b, 0x00, 0x7d, 0x04, 0x1b, 0x9f, 0xb3, 0x2c, 0x3c, 0x9e, 0xbd,
0x8e, 0xbc, 0x4b, 0xa7, 0x51, 0xa6, 0xf3, 0x10, 0x2e, 0x96, 0xe8, 0xa8, 0xe5, 0xa5, 0x64, 0xaa,
0xfb, 0x5b, 0xf2, 0xe5, 0xc0, 0x7a, 0xa7, 0x0d, 0xfb, 0x9d, 0xd2, 0xcf, 0x80, 0xdc, 0x4f, 0xe2,
0x98, 0x0d, 0xf9, 0x01, 0x63, 0x99, 0xde, 0xcc, 0xff, 0xb7, 0xc4, 0xb0, 0xbd, 0xbb, 0xa5, 0x2e,
0xb6, 0xfc, 0xf8, 0x95, 0x7c, 0x12, 0x68, 0xa6, 0x2c, 0x9b, 0x08, 0xc2, 0x4b, 0xbe, 0xf8, 0x4d,
0x77, 0x60, 0xdd, 0x21, 0x5b, 0xf0, 0x3c, 0x65, 0x2c, 0x1b, 0xa8, 0xdd, 0xcd, 0xfb, 0x7a, 0x48,
0x6f, 0xc3, 0xc5, 0x07, 0x61, 0x3e, 0xac, 0x6e, 0x05, 0x3f, 0x99, 0x1e, 0x0d, 0x8a, 0xe7, 0xa7,
0x87, 0x68, 0xe5, 0xca, 0x9f, 0x28, 0xdf, 0xe0, 0x8f, 0x3c, 0x68, 0xee, 0x3d, 0xdd, 0xbf, 0x8f,
0x8e, 0x45, 0x18, 0x0f, 0x93, 0x09, 0xda, 0x06, 0xc9, 0x0e, 0x33, 0x3e, 0xf7, 0x59, 0x5d, 0x81,
0x96, 0x30, 0x29, 0x68, 0xb8, 0xc5, 0xa3, 0xea, 0xf8, 0x05, 0x00, 0x9d, 0x06, 0xf6, 0x3c, 0x0d,
0x33, 0xe1, 0x15, 0x68, 0x5b, 0xdf, 0x14, 0xca, 0xb2, 0x3a, 0x41, 0x7f, 0xda, 0x84, 0xee, 0xdd,
0x21, 0x0f, 0x4f, 0x99, 0x52, 0xde, 0x62, 0x55, 0x01, 0x50, 0xfb, 0x51, 0x23, 0x34, 0x33, 0x19,
0x9b, 0x24, 0x9c, 0x0d, 0x9c, 0x6b, 0x72, 0x81, 0x88, 0x35, 0x94, 0x84, 0x06, 0x29, 0x9a, 0x01,
0xb1, 0xbf, 0x96, 0xef, 0x02, 0x91, 0x65, 0x08, 0x40, 0x2e, 0xe3, 0xce, 0x9a, 0xbe, 0x1e, 0x22,
0x3f, 0x86, 0x41, 0x1a, 0x0c, 0x43, 0x3e, 0x53, 0xda, 0xc0, 0x8c, 0x91, 0x76, 0x94, 0x0c, 0x83,
0x68, 0x70, 0x14, 0x44, 0x41, 0x3c, 0x64, 0xca, 0x3f, 0x71, 0x81, 0xe8, 0x82, 0xa8, 0x2d, 0x69,
0x34, 0xe9, 0xa6, 0x94, 0xa0, 0xe8, 0xca, 0x0c, 0x93, 0xc9, 0x24, 0xe4, 0xe8, 0xb9, 0xf4, 0x96,
0xa4, 0xe6, 0x29, 0x20, 0xe2, 0x24, 0x72, 0x74, 0x26, 0x79, 0xd8, 0x92, 0xab, 0x39, 0x40, 0xa4,
0x72, 0xcc, 0x98, 0xd0, 0x60, 0xcf, 0xce, 0x7a, 0x20, 0xa9, 0x14, 0x10, 0xbc, 0x8d, 0x69, 0x9c,
0x33, 0xce, 0x23, 0x36, 0x32, 0x1b, 0x6a, 0x0b, 0xb4, 0xea, 0x04, 0xb9, 0x05, 0xeb, 0xd2, 0x99,
0xca, 0x03, 0x9e, 0xe4, 0x27, 0x61, 0x3e, 0xc8, 0x59, 0xcc, 0x7b, 0x1d, 0x81, 0x5f, 0x37, 0x45,
0x3e, 0x80, 0xad, 0x12, 0x38, 0x63, 0x43, 0x16, 0x9e, 0xb2, 0x51, 0xaf, 0x2b, 0xbe, 0x3a, 0x6f,
0x9a, 0x5c, 0x83, 0x36, 0xfa, 0x90, 0xd3, 0x74, 0x14, 0x70, 0x96, 0xf7, 0x96, 0xc5, 0x3d, 0xd8,
0x20, 0x72, 0x1b, 0xba, 0x29, 0x93, 0x56, 0xf8, 0x84, 0x47, 0xc3, 0xbc, 0xb7, 0x22, 0x4c, 0x5f,
0x5b, 0x3d, 0x36, 0x94, 0x5f, 0xdf, 0xc5, 0x40, 0xd1, 0x1c, 0xe6, 0xa7, 0x83, 0x11, 0x8b, 0x82,
0x59, 0x6f, 0x55, 0x08, 0x5d, 0x01, 0xa0, 0x17, 0x61, 0x7d, 0x3f, 0xcc, 0xb9, 0x92, 0x34, 0xa3,
0xfd, 0xf6, 0x60, 0xc3, 0x05, 0xab, 0xb7, 0x78, 0x0b, 0x96, 0x94, 0xd8, 0xe4, 0xbd, 0xb6, 0x58,
0x7a, 0x43, 0x2d, 0xed, 0x48, 0xac, 0x6f, 0xb0, 0xe8, 0x1f, 0x36, 0xa0, 0x89, 0xef, 0xec, 0xfc,
0x37, 0x69, 0x3f, 0xf0, 0x86, 0xf3, 0xc0, 0x6d, 0x75, 0x3b, 0xe7, 0xa8, 0x5b, 0xe1, 0x59, 0xcf,
0x38, 0x53, 0xb7, 0x21, 0x25, 0xd6, 0x82, 0x14, 0xf3, 0x19, 0x1b, 0x9e, 0x0a, 0xb1, 0x35, 0xf3,
0x08, 0x41, 0xa1, 0x46, 0x33, 0x27, 0xbe, 0x96, 0x32, 0x6b, 0xc6, 0x7a, 0x4e, 0x7c, 0xb9, 0x58,
0xcc, 0x89, 0xef, 0x7a, 0xb0, 0x18, 0xc6, 0x47, 0xc9, 0x34, 0x1e, 0x09, 0xf9, 0x5c, 0xf2, 0xf5,
0x10, 0xf9, 0x9c, 0x0a, 0xef, 0x28, 0x9c, 0x30, 0x25, 0x98, 0x05, 0x80, 0x12, 0x74, 0x83, 0x72,
0xa1, 0x71, 0x0c, 0x93, 0xdf, 0x87, 0x35, 0x0b, 0xa6, 0x38, 0x7c, 0x1d, 0xe6, 0xf1, 0xf4, 0xda,
0x9f, 0xd6, 0x37, 0x2b, 0x54, 0x95, 0x9c, 0xa1, 0xab, 0xb0, 0xfc, 0x98, 0xf1, 0x8f, 0xe3, 0xe3,
0x44, 0x53, 0xfa, 0xe3, 0x39, 0x58, 0x31, 0x20, 0x45, 0x68, 0x1b, 0x56, 0xc2, 0x11, 0x8b, 0x79,
0xc8, 0x67, 0x03, 0xc7, 0xdb, 0x2a, 0x83, 0x51, 0xf9, 0x07, 0x51, 0x18, 0xe4, 0x4a, 0x7d, 0xc8,
0x01, 0xd9, 0x85, 0x0d, 0x94, 0x3c, 0x2d, 0x4c, 0xe6, 0xda, 0xa5, 0x93, 0x57, 0x3b, 0x87, 0x8f,
0x05, 0xe1, 0x52, 0x3d, 0x15, 0x9f, 0x48, 0x55, 0x57, 0x37, 0x85, 0x5c, 0x93, 0x94, 0xf0, 0xc8,
0xf3, 0x52, 0x3a, 0x0d, 0xa0, 0x12, 0x1f, 0x2d, 0x48, 0x07, 0xb3, 0x1c, 0x1f, 0x59, 0x31, 0xd6,
0x52, 0x25, 0xc6, 0xda, 0x86, 0x95, 0x7c, 0x16, 0x0f, 0xd9, 0x68, 0xc0, 0x13, 0x5c, 0x37, 0x8c,
0xc5, 0xed, 0x2c, 0xf9, 0x65, 0xb0, 0x88, 0x06, 0x59, 0xce, 0x63, 0xc6, 0x85, 0xd6, 0x58, 0xf2,
0xf5, 0x10, 0x15, 0xb0, 0x40, 0x91, 0x42, 0xdf, 0xf2, 0xd5, 0x08, 0xad, 0xd8, 0x34, 0x0b, 0xf3,
0x5e, 0x47, 0x40, 0xc5, 0x6f, 0xfa, 0x3d, 0x61, 0x1c, 0x4d, 0x10, 0xf8, 0x99, 0x78, 0xb9, 0xe4,
0x32, 0xb4, 0xe4, 0x9e, 0xf2, 0x93, 0x40, 0x87, 0xab, 0x02, 0x70, 0x78, 0x12, 0x60, 0xec, 0xe2,
0x1c, 0x53, 0xbe, 0x82, 0xb6, 0x80, 0xed, 0xc9, 0x53, 0xbe, 0x0d, 0xcb, 0x3a, 0xbc, 0xcc, 0x07,
0x11, 0x3b, 0xe6, 0xda, 0xd9, 0x8e, 0xa7, 0x13, 0x5c, 0x2e, 0xdf, 0x67, 0xc7, 0x9c, 0x3e, 0x81,
0x35, 0xf5, 0x02, 0x3f, 0x4d, 0x99, 0x5e, 0xfa, 0x1b, 0x65, 0xfd, 0x2f, 0x0d, 0xf4, 0xba, 0x92,
0x2c, 0x3b, 0x42, 0x28, 0x19, 0x05, 0xea, 0x03, 0x51, 0xd3, 0xf7, 0xa3, 0x24, 0x67, 0x8a, 0x20,
0x85, 0xce, 0x30, 0x4a, 0xf2, 0x72, 0x18, 0x61, 0xc3, 0x90, 0x97, 0xf9, 0x74, 0x38, 0xc4, 0x97,
0x2b, 0x4d, 0xbc, 0x1e, 0xd2, 0xbf, 0xf1, 0x60, 0x5d, 0x50, 0xd3, 0xba, 0xc2, 0xf8, 0x85, 0x6f,
0xbe, 0xcd, 0xce, 0xd0, 0x0e, 0x6b, 0x36, 0x60, 0xfe, 0x38, 0xc9, 0x86, 0x4c, 0xad, 0x24, 0x07,
0xbf, 0x08, 0x4f, 0xf7, 0x5f, 0x3d, 0x58, 0x13, 0x5b, 0x3d, 0xe4, 0x01, 0x9f, 0xe6, 0xea, 0xf8,
0xbf, 0x0a, 0x5d, 0x3c, 0x2a, 0xd3, 0xe2, 0xaf, 0x36, 0xba, 0x61, 0x5e, 0xaa, 0x80, 0x4a, 0xe4,
0xbd, 0x0b, 0xbe, 0x8b, 0x4c, 0x3e, 0x82, 0x8e, 0x9d, 0x23, 0x10, 0x7b, 0x6e, 0xef, 0x5e, 0xd2,
0xa7, 0xac, 0x48, 0xce, 0xde, 0x05, 0xdf, 0xf9, 0x80, 0xdc, 0x01, 0x10, 0x96, 0x59, 0x90, 0x55,
0x61, 0xe0, 0x25, 0x97, 0x49, 0xd6, 0x65, 0xed, 0x5d, 0xf0, 0x2d, 0xf4, 0x7b, 0x4b, 0xb0, 0x20,
0x4d, 0x09, 0x7d, 0x0c, 0x5d, 0x67, 0xa7, 0x8e, 0x07, 0xdf, 0x91, 0x1e, 0x7c, 0x25, 0xc0, 0x6b,
0xd4, 0x04, 0x78, 0xff, 0xd0, 0x00, 0x82, 0xd2, 0x56, 0xba, 0xce, 0x77, 0x60, 0x59, 0xb1, 0xdf,
0x75, 0xde, 0x4a, 0x50, 0x61, 0xf3, 0x92, 0x91, 0xe3, 0xc1, 0x74, 0x7c, 0x1b, 0x44, 0x6e, 0x02,
0xb1, 0x86, 0x3a, 0x6a, 0x97, 0xf6, 0xa0, 0x66, 0x06, 0x15, 0x97, 0x74, 0x3f, 0x74, 0xbc, 0xaa,
0x3c, 0xb6, 0xa6, 0xb8, 0xdf, 0xda, 0x39, 0x91, 0x4c, 0x9a, 0xe6, 0x27, 0x68, 0x93, 0xb5, 0x8f,
0xa3, 0xc7, 0x65, 0x41, 0x5a, 0x78, 0xad, 0x20, 0x2d, 0x96, 0x05, 0x49, 0x58, 0xb8, 0x2c, 0x3c,
0x0d, 0x38, 0xd3, 0x56, 0x43, 0x0d, 0xe9, 0x4f, 0x3c, 0x58, 0x45, 0xee, 0x39, 0x12, 0xf6, 0x21,
0x08, 0x01, 0x7f, 0x43, 0x01, 0x73, 0x70, 0x7f, 0x7e, 0xf9, 0xfa, 0x00, 0x5a, 0x82, 0x60, 0x92,
0xb2, 0x58, 0x89, 0x57, 0xcf, 0x15, 0xaf, 0x42, 0xb7, 0xec, 0x5d, 0xf0, 0x0b, 0x64, 0x4b, 0xb8,
0xfe, 0xd9, 0x83, 0xb6, 0xda, 0xe6, 0xff, 0xd8, 0xa5, 0xee, 0xc3, 0x12, 0xca, 0x99, 0xe5, 0xb1,
0x9a, 0x31, 0xea, 0xf4, 0x09, 0x46, 0x34, 0x68, 0xc4, 0x1c, 0x77, 0xba, 0x0c, 0x46, 0x8b, 0x24,
0xd4, 0x68, 0x3e, 0xe0, 0x61, 0x34, 0xd0, 0xb3, 0x2a, 0xd1, 0x56, 0x37, 0x85, 0xda, 0x24, 0xe7,
0xc1, 0x98, 0x29, 0x63, 0x23, 0x07, 0x18, 0x37, 0xa8, 0x03, 0x95, 0x5d, 0xa5, 0x1f, 0x03, 0x6c,
0x55, 0xa6, 0x8c, 0xbb, 0xa4, 0x3c, 0xc4, 0x28, 0x9c, 0x1c, 0x25, 0xc6, 0xd9, 0xf4, 0x6c, 0xe7,
0xd1, 0x99, 0x22, 0x63, 0xb8, 0xa8, 0xad, 0x2a, 0xf2, 0xb4, 0xb0, 0xa1, 0x0d, 0xe1, 0x0e, 0xdc,
0x76, 0x65, 0xa0, 0xbc, 0xa0, 0x86, 0xdb, 0xef, 0xb1, 0x9e, 0x1e, 0x39, 0x81, 0x9e, 0x31, 0xdf,
0x4a, 0x71, 0x5b, 0x26, 0x1e, 0xd7, 0x7a, 0xef, 0x35, 0x6b, 0x09, 0x2d, 0x33, 0xd2, 0xcb, 0x9c,
0x4b, 0x8d, 0xcc, 0xe0, 0xaa, 0x9e, 0x13, 0x9a, 0xb9, 0xba, 0x5e, 0xf3, 0x8d, 0xce, 0xf6, 0x08,
0x3f, 0x76, 0x17, 0x7d, 0x0d, 0xe1, 0xfe, 0x8f, 0x3d, 0x58, 0x76, 0xc9, 0xa1, 0xe8, 0xa8, 0xa8,
0x43, 0xab, 0x0e, 0xed, 0x16, 0x95, 0xc0, 0xd5, 0xb8, 0xa9, 0x51, 0x17, 0x37, 0xd9, 0xd1, 0xd1,
0xdc, 0xeb, 0xa2, 0xa3, 0xe6, 0x9b, 0x45, 0x47, 0xf3, 0x75, 0xd1, 0x51, 0xff, 0xbf, 0x3c, 0x20,
0xd5, 0xfb, 0x25, 0x8f, 0x65, 0xe0, 0x16, 0xb3, 0x48, 0xe9, 0x89, 0x5f, 0x7a, 0x33, 0x19, 0xd1,
0x3c, 0xd4, 0x5f, 0xa3, 0xb0, 0xda, 0x8a, 0xc0, 0x76, 0x46, 0xba, 0x7e, 0xdd, 0x54, 0x29, 0x5e,
0x6b, 0xbe, 0x3e, 0x5e, 0x9b, 0x7f, 0x7d, 0xbc, 0xb6, 0x50, 0x8e, 0xd7, 0xfa, 0xbf, 0x0b, 0x5d,
0xe7, 0xd6, 0x7f, 0x71, 0x27, 0x2e, 0x3b, 0x32, 0xf2, 0x82, 0x1d, 0x58, 0xff, 0x3f, 0x1b, 0x40,
0xaa, 0x92, 0xf7, 0x7f, 0xba, 0x07, 0x21, 0x47, 0x8e, 0x02, 0x99, 0x53, 0x72, 0xe4, 0xa8, 0x8e,
0xff, 0x4d, 0xa5, 0xf8, 0x1e, 0xac, 0x65, 0x6c, 0x98, 0x9c, 0xb2, 0xcc, 0x8a, 0x99, 0xe5, 0x55,
0x55, 0x27, 0xd0, 0x95, 0x73, 0xa3, 0xd4, 0x25, 0xa7, 0x36, 0x60, 0x59, 0x86, 0x52, 0xb0, 0x4a,
0xbf, 0x01, 0x1b, 0xb2, 0x64, 0x73, 0x4f, 0x92, 0xd2, 0xde, 0xc4, 0x75, 0xe8, 0x9c, 0xc9, 0x34,
0xdd, 0x20, 0x89, 0xa3, 0x99, 0x32, 0x22, 0x6d, 0x05, 0xfb, 0x34, 0x8e, 0x66, 0xf4, 0x47, 0x1e,
0x5c, 0x2c, 0x7d, 0x5b, 0x64, 0xe3, 0xa5, 0xaa, 0x75, 0xf5, 0xaf, 0x0b, 0xc4, 0x23, 0x2a, 0x19,
0xb7, 0x8e, 0x28, 0x4d, 0x52, 0x75, 0x02, 0x59, 0x38, 0x8d, 0xab, 0xf8, 0xf2, 0x62, 0xea, 0xa6,
0xe8, 0x16, 0x5c, 0x54, 0x97, 0xef, 0x9e, 0x8d, 0xee, 0xc2, 0x66, 0x79, 0xa2, 0xc8, 0x7c, 0xb9,
0x5b, 0xd6, 0x43, 0xfa, 0x11, 0x90, 0x6f, 0x4d, 0x59, 0x36, 0x13, 0x79, 0x7f, 0x93, 0x5a, 0xdd,
0x2a, 0x87, 0xd8, 0x0b, 0xe9, 0xf4, 0xe8, 0x9b, 0x6c, 0xa6, 0xcb, 0x25, 0x0d, 0x53, 0x2e, 0xa1,
0x77, 0x60, 0xdd, 0x21, 0x60, 0x58, 0xb5, 0x20, 0x6a, 0x07, 0x3a, 0xfc, 0x74, 0xeb, 0x0b, 0x6a,
0x8e, 0xfe, 0xa5, 0x07, 0x73, 0x7b, 0x49, 0x6a, 0xe7, 0x8c, 0x3c, 0x37, 0x67, 0xa4, 0x74, 0xe7,
0xc0, 0xa8, 0xc6, 0x86, 0x7a, 0xf9, 0x36, 0x10, 0x35, 0x5f, 0x30, 0xe1, 0x18, 0x80, 0x1d, 0x27,
0xd9, 0x59, 0x90, 0x8d, 0x14, 0xff, 0x4a, 0x50, 0xdc, 0x7e, 0xa1, 0x60, 0xf0, 0x27, 0x3a, 0x0d,
0x22, 0x71, 0x36, 0x53, 0x31, 0xa3, 0x1a, 0xd1, 0x1f, 0x78, 0x30, 0x2f, 0xf6, 0x8a, 0xaf, 0x41,
0xde, 0xaf, 0x28, 0x95, 0x89, 0xbc, 0x9c, 0x27, 0x5f, 0x43, 0x09, 0x5c, 0x2a, 0xa0, 0x35, 0x2a,
0x05, 0xb4, 0x2b, 0xd0, 0x92, 0xa3, 0xa2, 0xe2, 0x54, 0x00, 0xc8, 0x55, 0x68, 0x9e, 0x24, 0xa9,
0xb6, 0x61, 0xa0, 0x13, 0x31, 0x49, 0xea, 0x0b, 0x38, 0xbd, 0x01, 0x2b, 0x4f, 0x92, 0x11, 0xb3,
0xa2, 0xf5, 0x73, 0xaf, 0x89, 0xfe, 0x9e, 0x07, 0x4b, 0x1a, 0x99, 0x6c, 0x43, 0x13, 0x4d, 0x51,
0xc9, 0xf9, 0x33, 0xe9, 0x54, 0xc4, 0xf3, 0x05, 0x06, 0xaa, 0x10, 0x11, 0x1b, 0x16, 0xae, 0x82,
0x8e, 0x0c, 0x0b, 0x23, 0x8c, 0xee, 0xb8, 0xd8, 0x73, 0xc9, 0x58, 0x95, 0xa0, 0xf4, 0x6f, 0x3d,
0xe8, 0x3a, 0x6b, 0xa0, 0x83, 0x1e, 0x05, 0x39, 0x57, 0x29, 0x28, 0xc5, 0x44, 0x1b, 0x64, 0x67,
0x76, 0x1a, 0x6e, 0x66, 0xc7, 0x64, 0x16, 0xe6, 0xec, 0xcc, 0xc2, 0x2d, 0x68, 0x15, 0xc5, 0xc8,
0xa6, 0xa3, 0x1a, 0x70, 0x45, 0x9d, 0x28, 0x2e, 0x90, 0x90, 0xce, 0x30, 0x89, 0x92, 0x4c, 0xd5,
0xea, 0xe4, 0x80, 0xde, 0x81, 0xb6, 0x85, 0x8f, 0xdb, 0x88, 0x19, 0x3f, 0x4b, 0xb2, 0x67, 0x3a,
0xc1, 0xa4, 0x86, 0xa6, 0x40, 0xd2, 0x28, 0x0a, 0x24, 0xf4, 0xef, 0x3c, 0xe8, 0xa2, 0xa4, 0x84,
0xf1, 0xf8, 0x20, 0x89, 0xc2, 0xe1, 0x4c, 0x48, 0x8c, 0x16, 0x8a, 0xc1, 0x88, 0x45, 0x3c, 0x30,
0x12, 0xe3, 0x82, 0xd1, 0xe6, 0x4f, 0xc2, 0x58, 0xa8, 0x2c, 0x25, 0x2f, 0x66, 0x8c, 0x92, 0x8f,
0xb6, 0xeb, 0x28, 0xc8, 0xd9, 0x60, 0x82, 0xe1, 0x84, 0xd2, 0xd5, 0x0e, 0x10, 0xd5, 0x07, 0x02,
0xb2, 0x80, 0xb3, 0xc1, 0x24, 0x8c, 0xa2, 0x50, 0xe2, 0x4a, 0x09, 0xaf, 0x9b, 0xc2, 0x30, 0xab,
0xad, 0xd4, 0xc4, 0xc3, 0xd1, 0x58, 0xe6, 0x4a, 0x95, 0x23, 0x62, 0x9e, 0x9f, 0x05, 0xd1, 0xf3,
0x8e, 0xeb, 0x62, 0x41, 0xca, 0xd7, 0x3a, 0x57, 0xbd, 0xd6, 0x2b, 0xd0, 0x42, 0xf1, 0xba, 0x2d,
0x7c, 0x24, 0x59, 0xbb, 0x2e, 0x00, 0x7a, 0x76, 0x57, 0xcc, 0xce, 0x17, 0xb3, 0x02, 0xe0, 0x78,
0x45, 0x0b, 0x25, 0xaf, 0xe8, 0x03, 0xe8, 0x28, 0x32, 0x82, 0xef, 0x22, 0x5c, 0x2a, 0x04, 0xdc,
0xb9, 0x13, 0xdf, 0xc1, 0xd4, 0x5f, 0xee, 0xea, 0x2f, 0x97, 0x5e, 0xf7, 0xa5, 0xc6, 0xa4, 0x17,
0x61, 0x5d, 0x31, 0xef, 0x71, 0x16, 0xa4, 0x27, 0x5a, 0xf5, 0x8e, 0x4c, 0x81, 0x54, 0x80, 0xc9,
0x0d, 0x98, 0xc7, 0xcf, 0xb4, 0xf6, 0xab, 0x7f, 0x74, 0x12, 0x85, 0x6c, 0xc3, 0x3c, 0x1b, 0x8d,
0x99, 0xf6, 0xcc, 0x89, 0x1b, 0x23, 0xe1, 0x1d, 0xf9, 0x12, 0x01, 0x55, 0x00, 0x42, 0x4b, 0x2a,
0xc0, 0xd5, 0x9c, 0x0b, 0x38, 0xfc, 0x78, 0x44, 0x37, 0x80, 0x3c, 0x91, 0x52, 0x6b, 0xe7, 0xf7,
0xfe, 0x60, 0x0e, 0xda, 0x16, 0x18, 0x5f, 0xf3, 0x18, 0x37, 0x3c, 0x18, 0x85, 0xc1, 0x84, 0x71,
0x96, 0x29, 0x49, 0x2d, 0x41, 0x85, 0x82, 0x3d, 0x1d, 0x0f, 0x92, 0x29, 0x1f, 0x8c, 0xd8, 0x38,
0x63, 0xd2, 0xa0, 0x79, 0x7e, 0x09, 0x8a, 0x78, 0x93, 0xe0, 0xb9, 0x8d, 0x27, 0xe5, 0xa1, 0x04,
0xd5, 0xd9, 0x3a, 0xc9, 0xa3, 0x66, 0x91, 0xad, 0x93, 0x1c, 0x29, 0xeb, 0xa1, 0xf9, 0x1a, 0x3d,
0xf4, 0x3e, 0x6c, 0x4a, 0x8d, 0xa3, 0xde, 0xe6, 0xa0, 0x24, 0x26, 0xe7, 0xcc, 0x92, 0x1b, 0xb0,
0x8a, 0x7b, 0xd6, 0x02, 0x9e, 0x87, 0xdf, 0x93, 0x71, 0xb6, 0xe7, 0x57, 0xe0, 0x88, 0x8b, 0xcf,
0xd1, 0xc1, 0x95, 0xc5, 0x84, 0x0a, 0x5c, 0xe0, 0x06, 0xcf, 0x5d, 0xdc, 0x96, 0xc2, 0x2d, 0xc1,
0x69, 0x17, 0xda, 0x87, 0x3c, 0x49, 0xf5, 0xa5, 0x2c, 0x43, 0x47, 0x0e, 0x55, 0x01, 0xe9, 0x32,
0x5c, 0x12, 0x52, 0xf4, 0x34, 0x49, 0x93, 0x28, 0x19, 0xcf, 0x0e, 0xa7, 0x47, 0xf9, 0x30, 0x0b,
0x53, 0xf4, 0x98, 0xe9, 0x3f, 0x79, 0xb0, 0xee, 0xcc, 0xaa, 0x50, 0xff, 0x97, 0xa5, 0x48, 0x9b,
0x9c, 0xbf, 0x14, 0xbc, 0x35, 0x4b, 0x1d, 0x4a, 0x44, 0x99, 0x12, 0xf9, 0x4c, 0x95, 0x01, 0xee,
0xc2, 0x8a, 0xde, 0x99, 0xfe, 0x50, 0x4a, 0x61, 0xaf, 0x2a, 0x85, 0xea, 0xfb, 0x65, 0xf5, 0x81,
0x26, 0xf1, 0x6b, 0xd2, 0xef, 0x64, 0x23, 0x71, 0x46, 0x1d, 0xf3, 0xf5, 0xf5, 0xf7, 0xb6, 0xb3,
0xab, 0x77, 0x30, 0x34, 0xc0, 0x9c, 0xfe, 0x89, 0x07, 0x50, 0xec, 0x0e, 0x05, 0xa3, 0x50, 0xe9,
0x9e, 0xc8, 0x86, 0x5a, 0xea, 0xfb, 0x3a, 0x74, 0x4c, 0xce, 0xb9, 0xb0, 0x12, 0x6d, 0x0d, 0x43,
0x0f, 0xe5, 0x5d, 0x58, 0x19, 0x47, 0xc9, 0x91, 0xb0, 0xb9, 0xa2, 0x56, 0x99, 0xab, 0x32, 0xda,
0xb2, 0x04, 0x3f, 0x52, 0xd0, 0xc2, 0xa4, 0x34, 0x2d, 0x93, 0x42, 0xff, 0xb4, 0x61, 0x32, 0x9f,
0xc5, 0x99, 0xcf, 0x7d, 0x65, 0x64, 0xb7, 0xa2, 0x1c, 0xcf, 0x49, 0x34, 0x8a, 0xec, 0xc6, 0xc1,
0x6b, 0x03, 0xbd, 0x3b, 0xb0, 0x9c, 0x49, 0xed, 0xa3, 0x55, 0x53, 0xf3, 0x15, 0xaa, 0xa9, 0x9b,
0x39, 0x76, 0xe7, 0xff, 0xc1, 0x6a, 0x30, 0x3a, 0x65, 0x19, 0x0f, 0x85, 0xc7, 0x2f, 0x8c, 0xbe,
0x54, 0xa8, 0x2b, 0x16, 0x5c, 0xd8, 0xe2, 0x77, 0x61, 0x45, 0x95, 0x2e, 0x0d, 0xa6, 0xea, 0x48,
0x29, 0xc0, 0x88, 0x48, 0xff, 0x5a, 0x27, 0x59, 0xdd, 0x3b, 0x3c, 0x9f, 0x23, 0xf6, 0xe9, 0x1a,
0xa5, 0xd3, 0x7d, 0x55, 0x25, 0x3c, 0x47, 0x3a, 0xac, 0x50, 0xa9, 0x67, 0x09, 0x54, 0x09, 0x6a,
0x97, 0xa5, 0xcd, 0x37, 0x61, 0x29, 0xfd, 0xd1, 0x1c, 0x2c, 0x7e, 0x1c, 0x9f, 0x26, 0xe1, 0x50,
0xa4, 0x1f, 0x27, 0x6c, 0x92, 0xe8, 0x06, 0x02, 0xfc, 0x8d, 0x16, 0x5d, 0xd4, 0xc6, 0x52, 0xae,
0xf2, 0x82, 0x7a, 0x88, 0xd6, 0x2d, 0x2b, 0x9a, 0x66, 0xa4, 0xa4, 0x58, 0x10, 0xf4, 0x0f, 0x33,
0xbb, 0x0f, 0x48, 0x8d, 0x8a, 0x0e, 0x8c, 0x79, 0xab, 0x03, 0x43, 0x24, 0xab, 0x65, 0xd9, 0x4f,
0xb0, 0x73, 0xc9, 0xd7, 0x43, 0xe1, 0xc7, 0x66, 0x4c, 0x06, 0xbd, 0xc2, 0x4e, 0x2e, 0x2a, 0x3f,
0xd6, 0x06, 0xa2, 0x2d, 0x95, 0x1f, 0x48, 0x1c, 0xa9, 0x6b, 0x6c, 0x10, 0xfa, 0x16, 0xe5, 0x56,
0xa2, 0x96, 0xbc, 0xe2, 0x12, 0x18, 0x15, 0xd2, 0x88, 0x19, 0xbd, 0x21, 0xcf, 0x00, 0xb2, 0x29,
0xa8, 0x0c, 0xb7, 0xbc, 0x60, 0x59, 0xbe, 0x54, 0x23, 0xe1, 0x83, 0x04, 0x51, 0x74, 0x14, 0x0c,
0x9f, 0x89, 0x06, 0x2f, 0x51, 0xad, 0x6c, 0xf9, 0x2e, 0x10, 0x77, 0x3d, 0x8c, 0xf8, 0xe9, 0x40,
0x91, 0xe8, 0xca, 0x6a, 0xa3, 0x05, 0xa2, 0x9f, 0x03, 0xb9, 0x3b, 0x1a, 0xa9, 0x1b, 0x32, 0x31,
0x42, 0xc1, 0x5b, 0xcf, 0xe1, 0x6d, 0xcd, 0x19, 0x1b, 0xb5, 0x67, 0xa4, 0x0f, 0xa1, 0x7d, 0x60,
0xf5, 0x65, 0x89, 0xcb, 0xd4, 0x1d, 0x59, 0x4a, 0x00, 0x2c, 0x88, 0xb5, 0x60, 0xc3, 0x5e, 0x90,
0xfe, 0x0a, 0x90, 0xfd, 0x30, 0xe7, 0x66, 0x7f, 0x26, 0x54, 0x34, 0x19, 0x2f, 0x2b, 0x54, 0x54,
0x30, 0x11, 0x2a, 0xde, 0x95, 0x45, 0xcf, 0xf2, 0xc1, 0x6e, 0xc0, 0x52, 0x28, 0x41, 0x5a, 0x0f,
0x2f, 0x2b, 0x01, 0xd6, 0x98, 0x66, 0x1e, 0x1d, 0x0a, 0x05, 0x74, 0xd4, 0xfc, 0x0f, 0x3c, 0x58,
0x54, 0x47, 0x43, 0x73, 0xe8, 0x74, 0xa4, 0xc9, 0x83, 0x39, 0xb0, 0xfa, 0x8e, 0xa0, 0xaa, 0xd4,
0xcd, 0xd5, 0x49, 0x1d, 0x81, 0x66, 0x1a, 0xf0, 0x13, 0xe1, 0x41, 0xb7, 0x7c, 0xf1, 0x5b, 0x47,
0x4a, 0xf3, 0x26, 0x52, 0xd2, 0x05, 0x5e, 0xb5, 0x29, 0x93, 0xb5, 0xbc, 0x27, 0x0b, 0xbc, 0x05,
0xb8, 0xe0, 0x81, 0xda, 0x60, 0x99, 0x07, 0x0a, 0xd5, 0x37, 0xf3, 0xb4, 0x0f, 0xbd, 0x07, 0x2c,
0x62, 0x9c, 0xdd, 0x8d, 0xa2, 0x32, 0xfd, 0xcb, 0x70, 0xa9, 0x66, 0x4e, 0x59, 0xca, 0x47, 0xb0,
0xf6, 0x80, 0x1d, 0x4d, 0xc7, 0xfb, 0xec, 0xb4, 0x28, 0x18, 0x10, 0x68, 0xe6, 0x27, 0xc9, 0x99,
0xba, 0x2f, 0xf1, 0x9b, 0xbc, 0x05, 0x10, 0x21, 0xce, 0x20, 0x4f, 0xd9, 0x50, 0xb7, 0xb3, 0x08,
0xc8, 0x61, 0xca, 0x86, 0xf4, 0x7d, 0x20, 0x36, 0x1d, 0x75, 0x04, 0x7c, 0x8d, 0xd3, 0xa3, 0x41,
0x3e, 0xcb, 0x39, 0x9b, 0xe8, 0x3e, 0x1d, 0x1b, 0x44, 0xdf, 0x85, 0xce, 0x41, 0x30, 0xf3, 0xd9,
0x97, 0xaa, 0xd1, 0x0f, 0x03, 0xb2, 0x60, 0x86, 0xe2, 0x69, 0x02, 0x32, 0x31, 0x4d, 0xff, 0xb1,
0x01, 0x0b, 0x12, 0x13, 0xa9, 0x8e, 0x58, 0xce, 0xc3, 0x58, 0xa6, 0xd5, 0x15, 0x55, 0x0b, 0x54,
0xb9, 0xef, 0x46, 0xcd, 0x7d, 0x2b, 0x17, 0x49, 0x97, 0xfe, 0xd5, 0xc5, 0x3a, 0x30, 0x11, 0x6f,
0x86, 0x13, 0x26, 0xfb, 0x3d, 0x9b, 0x2a, 0xde, 0xd4, 0x80, 0x52, 0xe4, 0x5b, 0xbc, 0x79, 0xb9,
0x3f, 0x2d, 0x88, 0xca, 0x2c, 0xd8, 0xa0, 0x5a, 0xcd, 0xb2, 0x28, 0x3b, 0xfb, 0x2a, 0x9a, 0xa5,
0xa2, 0x41, 0x96, 0xde, 0x40, 0x83, 0x48, 0xbf, 0xc9, 0xd1, 0x20, 0x04, 0x56, 0x1f, 0x31, 0xe6,
0xb3, 0x34, 0xc9, 0x4c, 0xb7, 0xe4, 0x0f, 0x3d, 0x58, 0x55, 0x16, 0xc1, 0xcc, 0x91, 0xeb, 0x8e,
0xf9, 0xf0, 0xea, 0x32, 0xad, 0x6f, 0x43, 0x57, 0x04, 0x50, 0x18, 0x1d, 0x89, 0x68, 0x49, 0xe5,
0x14, 0x1c, 0x20, 0xee, 0x49, 0xe7, 0x0e, 0x27, 0x61, 0xa4, 0x18, 0x6c, 0x83, 0xd0, 0xd4, 0xe9,
0x00, 0x4b, 0xb0, 0xd7, 0xf3, 0xcd, 0x98, 0x1e, 0xc0, 0x9a, 0xb5, 0x5f, 0x25, 0x50, 0x77, 0x40,
0xd7, 0x1b, 0x65, 0x8a, 0x40, 0xbe, 0x8b, 0x2d, 0xd7, 0xb8, 0x15, 0x9f, 0x39, 0xc8, 0xf4, 0xef,
0x3d, 0xc1, 0x02, 0xe5, 0x43, 0x99, 0xfe, 0xa4, 0x05, 0xe9, 0xd6, 0x48, 0x69, 0xdf, 0xbb, 0xe0,
0xab, 0x31, 0xf9, 0xfa, 0x1b, 0x7a, 0x26, 0xa6, 0xae, 0x77, 0x0e, 0x6f, 0xe6, 0xea, 0x78, 0xf3,
0x8a, 0x93, 0xdf, 0x5b, 0x84, 0xf9, 0x7c, 0x98, 0xa4, 0x8c, 0xae, 0x0b, 0x16, 0xe8, 0xfd, 0x4a,
0x16, 0xec, 0xfe, 0x9b, 0x07, 0xcb, 0x32, 0xb9, 0x26, 0xfb, 0xaa, 0x59, 0x46, 0x30, 0x76, 0xb2,
0xda, 0xb5, 0x89, 0x71, 0x1d, 0xab, 0x6d, 0xdf, 0xfd, 0xcb, 0xb5, 0x73, 0xda, 0x6f, 0xfe, 0xfe,
0x4f, 0xfe, 0xe3, 0xcf, 0x1a, 0x17, 0xe9, 0xea, 0xce, 0xe9, 0xed, 0x1d, 0xa1, 0xe2, 0xd8, 0x99,
0xc0, 0xf8, 0xd0, 0xbb, 0x81, 0xab, 0xd8, 0x9d, 0xdc, 0x66, 0x95, 0x9a, 0x8e, 0x70, 0xb3, 0x4a,
0x6d, 0xeb, 0xb7, 0xb3, 0xca, 0x54, 0x60, 0x98, 0x55, 0x76, 0x7f, 0xda, 0x87, 0x96, 0x09, 0xf2,
0xc8, 0x77, 0xa1, 0xeb, 0x24, 0x12, 0x89, 0x26, 0x5c, 0x97, 0x9a, 0xec, 0x5f, 0xa9, 0x9f, 0x54,
0xcb, 0x5e, 0x15, 0xcb, 0xf6, 0xc8, 0x26, 0x2e, 0xab, 0xb2, 0x77, 0x3b, 0x22, 0xc3, 0x2a, 0x7b,
0x0e, 0x9e, 0xc1, 0xb2, 0x9b, 0xfc, 0x23, 0x57, 0xdc, 0xdb, 0x2e, 0xad, 0xf6, 0xd6, 0x39, 0xb3,
0x6a, 0xb9, 0x2b, 0x62, 0xb9, 0x4d, 0xb2, 0x61, 0x2f, 0x67, 0x82, 0x2f, 0x26, 0xba, 0x44, 0xec,
0x16, 0x6f, 0xa2, 0xe9, 0xd5, 0xb7, 0x7e, 0xf7, 0x2f, 0x55, 0xdb, 0xb9, 0x55, 0xff, 0x37, 0xed,
0x89, 0xa5, 0x08, 0x11, 0x0c, 0xb5, 0x3b, 0xbc, 0xc9, 0x77, 0xa0, 0x65, 0x1a, 0x44, 0xc9, 0x96,
0xd5, 0x95, 0x6b, 0x77, 0xad, 0xf6, 0x7b, 0xd5, 0x89, 0xba, 0xab, 0xb2, 0x29, 0xa3, 0x40, 0xec,
0xc3, 0x45, 0x65, 0x71, 0x8f, 0xd8, 0xcf, 0x72, 0x92, 0x9a, 0xc6, 0xf4, 0x5b, 0x1e, 0xb9, 0x03,
0x4b, 0xba, 0xef, 0x96, 0x6c, 0xd6, 0xf7, 0x0f, 0xf7, 0xb7, 0x2a, 0x70, 0xa5, 0x17, 0xee, 0x02,
0x14, 0x2d, 0xa2, 0xa4, 0x77, 0x5e, 0x27, 0xab, 0x61, 0x62, 0x4d, 0x3f, 0xe9, 0x58, 0x74, 0xc8,
0xba, 0x1d, 0xa8, 0xe4, 0x2b, 0x05, 0x7e, 0x6d, 0x6f, 0xea, 0x2b, 0x08, 0xd2, 0x4d, 0xc1, 0xbb,
0x55, 0xb2, 0x8c, 0xbc, 0x8b, 0xd9, 0x99, 0xee, 0x97, 0x7a, 0x00, 0x6d, 0xab, 0xed, 0x94, 0x68,
0x0a, 0xd5, 0x96, 0xd5, 0x7e, 0xbf, 0x6e, 0x4a, 0x6d, 0xf7, 0x37, 0xa0, 0xeb, 0xf4, 0x8f, 0x9a,
0x97, 0x51, 0xd7, 0x9d, 0x6a, 0x5e, 0x46, 0x7d, 0xcb, 0xe9, 0xb7, 0xa1, 0x6d, 0x75, 0x7b, 0x12,
0xab, 0x42, 0x5d, 0xea, 0xe6, 0x34, 0x3b, 0xaa, 0x69, 0x0e, 0xa5, 0x1b, 0xe2, 0xbc, 0xcb, 0xb4,
0x85, 0xe7, 0x15, 0x4d, 0x43, 0x28, 0x24, 0xdf, 0x85, 0x65, 0xb7, 0xcb, 0xd3, 0xbc, 0xaa, 0xda,
0x7e, 0x51, 0xf3, 0xaa, 0xce, 0x69, 0x0d, 0x55, 0x02, 0x79, 0x63, 0xdd, 0x2c, 0xb2, 0xf3, 0x42,
0xa5, 0x38, 0x5f, 0x92, 0x6f, 0xa1, 0xea, 0x50, 0x5d, 0x5c, 0xa4, 0xe8, 0x7a, 0x75, 0x7b, 0xbd,
0x8c, 0xb4, 0x57, 0x1a, 0xbe, 0xe8, 0x9a, 0x20, 0xde, 0x26, 0xc5, 0x09, 0xc8, 0x27, 0xb0, 0xa8,
0xba, 0xb9, 0xc8, 0xc5, 0x42, 0xaa, 0xad, 0x84, 0x50, 0x7f, 0xb3, 0x0c, 0x56, 0xc4, 0xd6, 0x05,
0xb1, 0x2e, 0x69, 0x23, 0xb1, 0x31, 0xe3, 0x21, 0xd2, 0x88, 0x61, 0xa5, 0x54, 0x95, 0x32, 0x8f,
0xa5, 0xbe, 0xa6, 0xdd, 0xbf, 0xfa, 0xea, 0x62, 0x96, 0xab, 0x66, 0xb4, 0x7a, 0xd9, 0xd1, 0x2d,
0x08, 0xbf, 0x0d, 0x1d, 0xbb, 0x79, 0xd0, 0xe8, 0xec, 0x9a, 0x46, 0x43, 0xa3, 0xb3, 0xeb, 0xba,
0x0d, 0xf5, 0xe5, 0x92, 0x8e, 0xbd, 0x0c, 0xf9, 0x36, 0xac, 0x58, 0xf5, 0xcf, 0xc3, 0x59, 0x3c,
0x34, 0xc2, 0x53, 0xed, 0x43, 0xe9, 0xd7, 0x19, 0x4f, 0xba, 0x25, 0x08, 0xaf, 0x51, 0x87, 0x30,
0x0a, 0xce, 0x7d, 0x68, 0xdb, 0xb5, 0xd5, 0x57, 0xd0, 0xdd, 0xb2, 0xa6, 0xec, 0xe6, 0x8d, 0x5b,
0x1e, 0xf9, 0x0b, 0x0f, 0x3a, 0x76, 0x87, 0x13, 0x71, 0xb2, 0x2a, 0x25, 0x3a, 0x3d, 0x7b, 0xce,
0x26, 0x44, 0x9f, 0x88, 0x4d, 0xee, 0xdd, 0x78, 0xe4, 0x30, 0xf9, 0x85, 0xe3, 0x14, 0xdd, 0xb4,
0xff, 0x93, 0xf1, 0xb2, 0x3c, 0x69, 0xf7, 0xe9, 0xbc, 0xbc, 0xe5, 0x91, 0x0f, 0xe5, 0x3f, 0x6f,
0x74, 0x80, 0x42, 0x2c, 0xc5, 0x56, 0x66, 0x97, 0xfd, 0x77, 0x96, 0x6d, 0xef, 0x96, 0x47, 0x7e,
0x47, 0xfe, 0x0d, 0x43, 0x7d, 0x2b, 0xb8, 0xfe, 0xa6, 0xdf, 0xd3, 0xb7, 0xc5, 0x49, 0xae, 0xd2,
0x4b, 0xce, 0x49, 0xca, 0x9a, 0xfd, 0x00, 0xa0, 0x88, 0x36, 0x49, 0x29, 0xf4, 0x32, 0x3a, 0xaf,
0x1a, 0x90, 0xba, 0xb7, 0xa9, 0x23, 0x34, 0xa9, 0x06, 0x3a, 0x56, 0x9c, 0x97, 0x9b, 0xeb, 0xac,
0x46, 0x8d, 0xfd, 0x7e, 0xdd, 0x94, 0xa2, 0xff, 0x55, 0x41, 0xff, 0x2d, 0x72, 0xd9, 0xa6, 0xbf,
0xf3, 0xc2, 0x8e, 0x32, 0x5f, 0x92, 0xcf, 0xa1, 0xbb, 0x9f, 0x24, 0xcf, 0xa6, 0xa9, 0x49, 0x68,
0xb8, 0x71, 0x13, 0x46, 0xba, 0xfd, 0xd2, 0xa1, 0xe8, 0x75, 0x41, 0xf9, 0x32, 0xb9, 0xe4, 0x52,
0x2e, 0x62, 0xdf, 0x97, 0x24, 0x80, 0x35, 0x63, 0xef, 0xcc, 0x41, 0xfa, 0x2e, 0x1d, 0x3b, 0x04,
0xad, 0xac, 0xe1, 0x78, 0x20, 0x66, 0x8d, 0x5c, 0xd3, 0xbc, 0xe5, 0x91, 0x03, 0xe8, 0x3c, 0x60,
0xc3, 0x64, 0xc4, 0x54, 0xa8, 0xb3, 0x5e, 0xec, 0xdc, 0xc4, 0x48, 0xfd, 0xae, 0x03, 0x74, 0x35,
0x40, 0x1a, 0xcc, 0x32, 0xf6, 0xe5, 0xce, 0x0b, 0x15, 0x44, 0xbd, 0xd4, 0x1a, 0x40, 0x07, 0x7e,
0x8e, 0x06, 0x28, 0x45, 0x8a, 0x8e, 0x06, 0xa8, 0x44, 0x8a, 0x8e, 0x06, 0xd0, 0x81, 0x27, 0x89,
0x30, 0x7e, 0x2c, 0x05, 0x97, 0xc6, 0x6a, 0x9e, 0x17, 0x92, 0xf6, 0xaf, 0x9d, 0x8f, 0xe0, 0xae,
0x76, 0xc3, 0x5d, 0xed, 0x10, 0xba, 0x0f, 0x98, 0x64, 0x96, 0xac, 0x12, 0xf4, 0x5d, 0x95, 0x62,
0x57, 0x14, 0xca, 0xea, 0x46, 0xcc, 0xb9, 0x2a, 0x5e, 0xa4, 0xe8, 0xc9, 0x77, 0xa0, 0xfd, 0x98,
0x71, 0x5d, 0x16, 0x30, 0xbe, 0x47, 0xa9, 0x4e, 0xd0, 0xaf, 0xa9, 0x2a, 0xd0, 0x6b, 0x82, 0x5a,
0x9f, 0xf4, 0x0c, 0xb5, 0x1d, 0x36, 0x1a, 0x33, 0xf9, 0xf8, 0x07, 0xe1, 0xe8, 0x25, 0xf9, 0x4d,
0x41, 0xdc, 0x54, 0x12, 0x37, 0xad, 0x6c, 0xb2, 0x4d, 0x7c, 0xa5, 0x04, 0xaf, 0xa3, 0x1c, 0x27,
0x23, 0x66, 0x19, 0xbb, 0x18, 0xda, 0x56, 0xd9, 0xd8, 0x3c, 0xa8, 0x6a, 0x2d, 0xda, 0x3c, 0xa8,
0x9a, 0x2a, 0x33, 0xdd, 0x16, 0xeb, 0x50, 0x72, 0xad, 0x58, 0x47, 0x56, 0x96, 0x8b, 0x95, 0x76,
0x5e, 0x04, 0x13, 0xfe, 0x92, 0x7c, 0x21, 0x5a, 0x9d, 0xed, 0xd2, 0x47, 0xe1, 0xfb, 0x94, 0xab,
0x24, 0x86, 0x59, 0xd6, 0x94, 0xeb, 0x0f, 0xc9, 0xa5, 0x84, 0x4d, 0xfc, 0x3a, 0xc0, 0x21, 0x4f,
0xd2, 0x07, 0x01, 0x9b, 0x24, 0x71, 0xa1, 0xc9, 0x8a, 0xf4, 0x7e, 0xa1, 0xc9, 0xac, 0x1c, 0x3f,
0xf9, 0xc2, 0xf2, 0x3e, 0x9d, 0xca, 0x91, 0x16, 0xae, 0x73, 0x2b, 0x00, 0x86, 0x21, 0x35, 0x55,
0x80, 0x5b, 0x1e, 0xfa, 0x92, 0x45, 0x2a, 0xc3, 0xf8, 0x92, 0x95, 0x2c, 0x89, 0x51, 0x83, 0x35,
0x79, 0x8f, 0x03, 0x68, 0x15, 0xf1, 0xb4, 0x36, 0x4f, 0xe5, 0xe8, 0xdb, 0xd8, 0x9b, 0x4a, 0x98,
0x4b, 0x57, 0x05, 0xab, 0x80, 0x2c, 0x21, 0xab, 0x44, 0xe5, 0xfb, 0x29, 0x80, 0xdc, 0xe0, 0x23,
0x1c, 0x59, 0x24, 0x9d, 0x68, 0xd6, 0x26, 0xe9, 0x86, 0x8d, 0xda, 0x1d, 0xa1, 0x86, 0xe4, 0x87,
0xde, 0x8d, 0xa3, 0x05, 0xf1, 0x0f, 0xe1, 0xaf, 0xfd, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x6e,
0x8c, 0x0d, 0xd9, 0x53, 0x3c, 0x00, 0x00,
// 4877 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x3b, 0x4d, 0x8f, 0x1c, 0x49,
0x56, 0xce, 0xea, 0xea, 0x8f, 0x7a, 0x55, 0xd5, 0x1f, 0xd1, 0xed, 0xee, 0x72, 0xd9, 0xeb, 0xb5,
0x63, 0x47, 0x33, 0x8d, 0x19, 0xdc, 0x76, 0x2f, 0x3b, 0xcc, 0x8e, 0x81, 0x91, 0xbf, 0x7b, 0xd8,
0x1e, 0x4f, 0x6f, 0xb6, 0x67, 0x06, 0x76, 0x85, 0x8a, 0xec, 0xaa, 0xe8, 0xea, 0x5c, 0x67, 0x65,
0xe6, 0x64, 0x46, 0x75, 0xbb, 0xd6, 0x58, 0x82, 0x05, 0x21, 0x21, 0x81, 0xf6, 0x00, 0x02, 0xed,
0x61, 0xb9, 0x70, 0x81, 0x03, 0xbf, 0x00, 0x89, 0x1f, 0xb0, 0x12, 0x02, 0x69, 0x4f, 0x08, 0x2e,
0x08, 0x4e, 0x70, 0xe6, 0xc0, 0x0d, 0xbd, 0xf8, 0xca, 0x88, 0xcc, 0x6c, 0xdb, 0xcb, 0x2e, 0xdc,
0x2a, 0x5e, 0xbc, 0x7c, 0x11, 0xf1, 0xe2, 0xc5, 0xfb, 0x2e, 0x68, 0x65, 0xe9, 0xf0, 0x66, 0x9a,
0x25, 0x3c, 0x21, 0xf3, 0x51, 0x9c, 0xa5, 0xc3, 0xfe, 0x95, 0x71, 0x92, 0x8c, 0x23, 0xb6, 0x13,
0xa4, 0xe1, 0x4e, 0x10, 0xc7, 0x09, 0x0f, 0x78, 0x98, 0xc4, 0xb9, 0x44, 0xa2, 0xb7, 0x61, 0xfd,
0x7e, 0xc6, 0x02, 0xce, 0x3e, 0x0f, 0xa2, 0x88, 0x71, 0x9f, 0x7d, 0x31, 0x65, 0x39, 0x27, 0x7d,
0x58, 0x4a, 0x83, 0x3c, 0x3f, 0x4b, 0xb2, 0x51, 0xcf, 0xbb, 0xe6, 0x6d, 0x77, 0x7c, 0x33, 0xa6,
0x9b, 0xb0, 0xe1, 0x7e, 0x92, 0xa7, 0x49, 0x9c, 0x33, 0x24, 0xf5, 0x69, 0x1c, 0x25, 0xc3, 0x67,
0x3f, 0x11, 0x29, 0xf7, 0x13, 0x45, 0xea, 0x07, 0x0d, 0x68, 0x3f, 0xcd, 0x82, 0x38, 0x0f, 0x86,
0xb8, 0x59, 0xd2, 0x83, 0x45, 0xfe, 0x7c, 0x70, 0x12, 0xe4, 0x27, 0x82, 0x44, 0xcb, 0xd7, 0x43,
0xb2, 0x09, 0x0b, 0xc1, 0x24, 0x99, 0xc6, 0xbc, 0xd7, 0xb8, 0xe6, 0x6d, 0xcf, 0xf9, 0x6a, 0x44,
0xde, 0x85, 0xb5, 0x78, 0x3a, 0x19, 0x0c, 0x93, 0xf8, 0x38, 0xcc, 0x26, 0xf2, 0xc8, 0xbd, 0xb9,
0x6b, 0xde, 0xf6, 0xbc, 0x5f, 0x9d, 0x20, 0x57, 0x01, 0x8e, 0x70, 0x1b, 0x72, 0x89, 0xa6, 0x58,
0xc2, 0x82, 0x10, 0x0a, 0x1d, 0x35, 0x62, 0xe1, 0xf8, 0x84, 0xf7, 0xe6, 0x05, 0x21, 0x07, 0x86,
0x34, 0x78, 0x38, 0x61, 0x83, 0x9c, 0x07, 0x93, 0xb4, 0xb7, 0x20, 0x76, 0x63, 0x41, 0xc4, 0x7c,
0xc2, 0x83, 0x68, 0x70, 0xcc, 0x58, 0xde, 0x5b, 0x54, 0xf3, 0x06, 0x42, 0xde, 0x86, 0xe5, 0x11,
0xcb, 0xf9, 0x20, 0x18, 0x8d, 0x32, 0x96, 0xe7, 0x2c, 0xef, 0x2d, 0x5d, 0x9b, 0xdb, 0x6e, 0xf9,
0x25, 0x28, 0xed, 0xc1, 0xe6, 0x63, 0xc6, 0x2d, 0xee, 0xe4, 0x8a, 0xd3, 0x74, 0x1f, 0x88, 0x05,
0x7e, 0xc0, 0x78, 0x10, 0x46, 0x39, 0x79, 0x0f, 0x3a, 0xdc, 0x42, 0xee, 0x79, 0xd7, 0xe6, 0xb6,
0xdb, 0xbb, 0xe4, 0xa6, 0x90, 0x8e, 0x9b, 0xd6, 0x07, 0xbe, 0x83, 0x47, 0xff, 0xd1, 0x83, 0xf6,
0x21, 0x8b, 0x47, 0xfa, 0x1e, 0x09, 0x34, 0x71, 0x27, 0xea, 0x0e, 0xc5, 0x6f, 0xf2, 0x65, 0x68,
0x8b, 0xdd, 0xe5, 0x3c, 0x0b, 0xe3, 0xb1, 0xb8, 0x82, 0x96, 0x0f, 0x08, 0x3a, 0x14, 0x10, 0xb2,
0x0a, 0x73, 0xc1, 0x84, 0x0b, 0xc6, 0xcf, 0xf9, 0xf8, 0x93, 0x5c, 0x87, 0x4e, 0x1a, 0xcc, 0x26,
0x2c, 0xe6, 0x05, 0xb3, 0x3b, 0x7e, 0x5b, 0xc1, 0xf6, 0x90, 0xdb, 0x37, 0x61, 0xdd, 0x46, 0xd1,
0xd4, 0xe7, 0x05, 0xf5, 0x35, 0x0b, 0x53, 0x2d, 0xf2, 0x0e, 0xac, 0x68, 0xfc, 0x4c, 0x6e, 0x56,
0xb0, 0xbf, 0xe5, 0x2f, 0x2b, 0xb0, 0x66, 0xd0, 0x9f, 0x7a, 0xd0, 0x91, 0x47, 0x92, 0x72, 0x46,
0xde, 0x82, 0xae, 0xfe, 0x92, 0x65, 0x59, 0x92, 0x29, 0xe9, 0x72, 0x81, 0xe4, 0x06, 0xac, 0x6a,
0x40, 0x9a, 0xb1, 0x70, 0x12, 0x8c, 0x99, 0x38, 0x6a, 0xc7, 0xaf, 0xc0, 0xc9, 0x6e, 0x41, 0x31,
0x4b, 0xa6, 0x9c, 0x89, 0xa3, 0xb7, 0x77, 0x3b, 0x8a, 0xdd, 0x3e, 0xc2, 0x7c, 0x17, 0x85, 0x7e,
0xcf, 0x83, 0xce, 0xfd, 0x93, 0x20, 0x8e, 0x59, 0x74, 0x90, 0x84, 0x31, 0x47, 0x71, 0x3b, 0x9e,
0xc6, 0xa3, 0x30, 0x1e, 0x0f, 0xf8, 0xf3, 0x50, 0x3f, 0x1b, 0x07, 0x86, 0x9b, 0xb2, 0xc7, 0xc8,
0x24, 0xc5, 0xff, 0x0a, 0x1c, 0xe9, 0x25, 0x53, 0x9e, 0x4e, 0xf9, 0x20, 0x8c, 0x47, 0xec, 0xb9,
0xd8, 0x53, 0xd7, 0x77, 0x60, 0xf4, 0x57, 0x61, 0x75, 0x1f, 0xe5, 0x38, 0x0e, 0xe3, 0xf1, 0x5d,
0x29, 0x6c, 0xf8, 0xb8, 0xd2, 0xe9, 0xd1, 0x33, 0x36, 0x53, 0x7c, 0x51, 0x23, 0x14, 0x85, 0x93,
0x24, 0xe7, 0x6a, 0x3d, 0xf1, 0x9b, 0xfe, 0x9b, 0x07, 0x2b, 0xc8, 0xdb, 0x8f, 0x83, 0x78, 0xa6,
0x45, 0x66, 0x1f, 0x3a, 0x48, 0xea, 0x69, 0x72, 0x57, 0x3e, 0x51, 0x29, 0x7a, 0xdb, 0x8a, 0x17,
0x25, 0xec, 0x9b, 0x36, 0xea, 0xc3, 0x98, 0x67, 0x33, 0xdf, 0xf9, 0x1a, 0x85, 0x8d, 0x07, 0xd9,
0x98, 0x71, 0xf1, 0x78, 0xd5, 0x63, 0x06, 0x09, 0xba, 0x9f, 0xc4, 0xc7, 0xe4, 0x1a, 0x74, 0xf2,
0x80, 0x0f, 0x52, 0x96, 0x0d, 0x8e, 0x66, 0x9c, 0x09, 0x81, 0x99, 0xf3, 0x21, 0x0f, 0xf8, 0x01,
0xcb, 0xee, 0xcd, 0x38, 0xeb, 0x7f, 0x08, 0x6b, 0x95, 0x55, 0x50, 0x46, 0x8b, 0x23, 0xe2, 0x4f,
0xb2, 0x01, 0xf3, 0xa7, 0x41, 0x34, 0x65, 0x4a, 0xa7, 0xc8, 0xc1, 0x07, 0x8d, 0xf7, 0x3d, 0xfa,
0x36, 0xac, 0x16, 0xdb, 0x56, 0x42, 0x44, 0xa0, 0x69, 0x6e, 0xa9, 0xe5, 0x8b, 0xdf, 0xf4, 0x77,
0x3d, 0x89, 0x78, 0x3f, 0x09, 0xcd, 0xfb, 0x44, 0x44, 0x7c, 0xc6, 0x1a, 0x11, 0x7f, 0x9f, 0xab,
0xbf, 0x7e, 0xfa, 0xc3, 0xd2, 0x77, 0x60, 0xcd, 0xda, 0xc2, 0x2b, 0x36, 0xfb, 0x17, 0x1e, 0xac,
0x3d, 0x61, 0x67, 0xea, 0xd6, 0xf5, 0x6e, 0xdf, 0x87, 0x26, 0x9f, 0xa5, 0x4c, 0x60, 0x2e, 0xef,
0xbe, 0xa5, 0x2e, 0xad, 0x82, 0x77, 0x53, 0x0d, 0x9f, 0xce, 0x52, 0xe6, 0x8b, 0x2f, 0xe8, 0x27,
0xd0, 0xb6, 0x80, 0x64, 0x0b, 0xd6, 0x3f, 0xff, 0xe8, 0xe9, 0x93, 0x87, 0x87, 0x87, 0x83, 0x83,
0x4f, 0xef, 0x7d, 0xe3, 0xe1, 0x6f, 0x0c, 0xf6, 0xee, 0x1e, 0xee, 0xad, 0x5e, 0x20, 0x9b, 0x40,
0x9e, 0x3c, 0x3c, 0x7c, 0xfa, 0xf0, 0x81, 0x03, 0xf7, 0xc8, 0x0a, 0xb4, 0x6d, 0x40, 0x83, 0xf6,
0xa1, 0xf7, 0x84, 0x9d, 0x7d, 0x1e, 0xf2, 0x98, 0xe5, 0xb9, 0xbb, 0x3c, 0xbd, 0x09, 0xc4, 0xde,
0x93, 0x3a, 0x66, 0x0f, 0x16, 0x95, 0xc6, 0xd4, 0x06, 0x43, 0x0d, 0xe9, 0xdb, 0x40, 0x0e, 0xc3,
0x71, 0xfc, 0x31, 0xcb, 0xf3, 0x60, 0xcc, 0xf4, 0x61, 0x57, 0x61, 0x6e, 0x92, 0x8f, 0xd5, 0x43,
0xc3, 0x9f, 0xf4, 0xab, 0xb0, 0xee, 0xe0, 0x29, 0xc2, 0x57, 0xa0, 0x95, 0x87, 0xe3, 0x38, 0xe0,
0xd3, 0x8c, 0x29, 0xd2, 0x05, 0x80, 0x3e, 0x82, 0x8d, 0xcf, 0x58, 0x16, 0x1e, 0xcf, 0x5e, 0x47,
0xde, 0xa5, 0xd3, 0x28, 0xd3, 0x79, 0x08, 0x17, 0x4b, 0x74, 0xd4, 0xf2, 0x52, 0x32, 0xd5, 0xfd,
0x2d, 0xf9, 0x72, 0x60, 0xbd, 0xd3, 0x86, 0xfd, 0x4e, 0xe9, 0xa7, 0x40, 0xee, 0x27, 0x71, 0xcc,
0x86, 0xfc, 0x80, 0xb1, 0x4c, 0x6f, 0xe6, 0xe7, 0x2d, 0x31, 0x6c, 0xef, 0x6e, 0xa9, 0x8b, 0x2d,
0x3f, 0x7e, 0x25, 0x9f, 0x04, 0x9a, 0x29, 0xcb, 0x26, 0x82, 0xf0, 0x92, 0x2f, 0x7e, 0xd3, 0x1d,
0x58, 0x77, 0xc8, 0x16, 0x3c, 0x4f, 0x19, 0xcb, 0x06, 0x6a, 0x77, 0xf3, 0xbe, 0x1e, 0xd2, 0xdb,
0x70, 0xf1, 0x41, 0x98, 0x0f, 0xab, 0x5b, 0xc1, 0x4f, 0xa6, 0x47, 0x83, 0xe2, 0xf9, 0xe9, 0x21,
0x5a, 0xb9, 0xf2, 0x27, 0xca, 0x37, 0xf8, 0x03, 0x0f, 0x9a, 0x7b, 0x4f, 0xf7, 0xef, 0xa3, 0x63,
0x11, 0xc6, 0xc3, 0x64, 0x82, 0xb6, 0x41, 0xb2, 0xc3, 0x8c, 0xcf, 0x7d, 0x56, 0x57, 0xa0, 0x25,
0x4c, 0x0a, 0x1a, 0x6e, 0xf1, 0xa8, 0x3a, 0x7e, 0x01, 0x40, 0xa7, 0x81, 0x3d, 0x4f, 0xc3, 0x4c,
0x78, 0x05, 0xda, 0xd6, 0x37, 0x85, 0xb2, 0xac, 0x4e, 0xd0, 0xff, 0x68, 0x42, 0xf7, 0xee, 0x90,
0x87, 0xa7, 0x4c, 0x29, 0x6f, 0xb1, 0xaa, 0x00, 0xa8, 0xfd, 0xa8, 0x11, 0x9a, 0x99, 0x8c, 0x4d,
0x12, 0xce, 0x06, 0xce, 0x35, 0xb9, 0x40, 0xc4, 0x1a, 0x4a, 0x42, 0x83, 0x14, 0xcd, 0x80, 0xd8,
0x5f, 0xcb, 0x77, 0x81, 0xc8, 0x32, 0x04, 0x20, 0x97, 0x71, 0x67, 0x4d, 0x5f, 0x0f, 0x91, 0x1f,
0xc3, 0x20, 0x0d, 0x86, 0x21, 0x9f, 0x29, 0x6d, 0x60, 0xc6, 0x48, 0x3b, 0x4a, 0x86, 0x41, 0x34,
0x38, 0x0a, 0xa2, 0x20, 0x1e, 0x32, 0xe5, 0x9f, 0xb8, 0x40, 0x74, 0x41, 0xd4, 0x96, 0x34, 0x9a,
0x74, 0x53, 0x4a, 0x50, 0x74, 0x65, 0x86, 0xc9, 0x64, 0x12, 0x72, 0xf4, 0x5c, 0x7a, 0x4b, 0x52,
0xf3, 0x14, 0x10, 0x71, 0x12, 0x39, 0x3a, 0x93, 0x3c, 0x6c, 0xc9, 0xd5, 0x1c, 0x20, 0x52, 0x39,
0x66, 0x4c, 0x68, 0xb0, 0x67, 0x67, 0x3d, 0x90, 0x54, 0x0a, 0x08, 0xde, 0xc6, 0x34, 0xce, 0x19,
0xe7, 0x11, 0x1b, 0x99, 0x0d, 0xb5, 0x05, 0x5a, 0x75, 0x82, 0xdc, 0x82, 0x75, 0xe9, 0x4c, 0xe5,
0x01, 0x4f, 0xf2, 0x93, 0x30, 0x1f, 0xe4, 0x2c, 0xe6, 0xbd, 0x8e, 0xc0, 0xaf, 0x9b, 0x22, 0xef,
0xc3, 0x56, 0x09, 0x9c, 0xb1, 0x21, 0x0b, 0x4f, 0xd9, 0xa8, 0xd7, 0x15, 0x5f, 0x9d, 0x37, 0x4d,
0xae, 0x41, 0x1b, 0x7d, 0xc8, 0x69, 0x3a, 0x0a, 0x38, 0xcb, 0x7b, 0xcb, 0xe2, 0x1e, 0x6c, 0x10,
0xb9, 0x0d, 0xdd, 0x94, 0x49, 0x2b, 0x7c, 0xc2, 0xa3, 0x61, 0xde, 0x5b, 0x11, 0xa6, 0xaf, 0xad,
0x1e, 0x1b, 0xca, 0xaf, 0xef, 0x62, 0xa0, 0x68, 0x0e, 0xf3, 0xd3, 0xc1, 0x88, 0x45, 0xc1, 0xac,
0xb7, 0x2a, 0x84, 0xae, 0x00, 0xd0, 0x8b, 0xb0, 0xbe, 0x1f, 0xe6, 0x5c, 0x49, 0x9a, 0xd1, 0x7e,
0x7b, 0xb0, 0xe1, 0x82, 0xd5, 0x5b, 0xbc, 0x05, 0x4b, 0x4a, 0x6c, 0xf2, 0x5e, 0x5b, 0x2c, 0xbd,
0xa1, 0x96, 0x76, 0x24, 0xd6, 0x37, 0x58, 0xf4, 0xf7, 0x1b, 0xd0, 0xc4, 0x77, 0x76, 0xfe, 0x9b,
0xb4, 0x1f, 0x78, 0xc3, 0x79, 0xe0, 0xb6, 0xba, 0x9d, 0x73, 0xd4, 0xad, 0xf0, 0xac, 0x67, 0x9c,
0xa9, 0xdb, 0x90, 0x12, 0x6b, 0x41, 0x8a, 0xf9, 0x8c, 0x0d, 0x4f, 0x85, 0xd8, 0x9a, 0x79, 0x84,
0xa0, 0x50, 0xa3, 0x99, 0x13, 0x5f, 0x4b, 0x99, 0x35, 0x63, 0x3d, 0x27, 0xbe, 0x5c, 0x2c, 0xe6,
0xc4, 0x77, 0x3d, 0x58, 0x0c, 0xe3, 0xa3, 0x64, 0x1a, 0x8f, 0x84, 0x7c, 0x2e, 0xf9, 0x7a, 0x88,
0x7c, 0x4e, 0x85, 0x77, 0x14, 0x4e, 0x98, 0x12, 0xcc, 0x02, 0x40, 0x09, 0xba, 0x41, 0xb9, 0xd0,
0x38, 0x86, 0xc9, 0xef, 0xc1, 0x9a, 0x05, 0x53, 0x1c, 0xbe, 0x0e, 0xf3, 0x78, 0x7a, 0xed, 0x4f,
0xeb, 0x9b, 0x15, 0xaa, 0x4a, 0xce, 0xd0, 0x55, 0x58, 0x7e, 0xcc, 0xf8, 0x47, 0xf1, 0x71, 0xa2,
0x29, 0xfd, 0xe1, 0x1c, 0xac, 0x18, 0x90, 0x22, 0xb4, 0x0d, 0x2b, 0xe1, 0x88, 0xc5, 0x3c, 0xe4,
0xb3, 0x81, 0xe3, 0x6d, 0x95, 0xc1, 0xa8, 0xfc, 0x83, 0x28, 0x0c, 0x72, 0xa5, 0x3e, 0xe4, 0x80,
0xec, 0xc2, 0x06, 0x4a, 0x9e, 0x16, 0x26, 0x73, 0xed, 0xd2, 0xc9, 0xab, 0x9d, 0xc3, 0xc7, 0x82,
0x70, 0xa9, 0x9e, 0x8a, 0x4f, 0xa4, 0xaa, 0xab, 0x9b, 0x42, 0xae, 0x49, 0x4a, 0x78, 0xe4, 0x79,
0x29, 0x9d, 0x06, 0x50, 0x89, 0x8f, 0x16, 0xa4, 0x83, 0x59, 0x8e, 0x8f, 0xac, 0x18, 0x6b, 0xa9,
0x12, 0x63, 0x6d, 0xc3, 0x4a, 0x3e, 0x8b, 0x87, 0x6c, 0x34, 0xe0, 0x09, 0xae, 0x1b, 0xc6, 0xe2,
0x76, 0x96, 0xfc, 0x32, 0x58, 0x44, 0x83, 0x2c, 0xe7, 0x31, 0xe3, 0x42, 0x6b, 0x2c, 0xf9, 0x7a,
0x88, 0x0a, 0x58, 0xa0, 0x48, 0xa1, 0x6f, 0xf9, 0x6a, 0x84, 0x56, 0x6c, 0x9a, 0x85, 0x79, 0xaf,
0x23, 0xa0, 0xe2, 0x37, 0xfd, 0xae, 0x30, 0x8e, 0x26, 0x08, 0xfc, 0x54, 0xbc, 0x5c, 0x72, 0x19,
0x5a, 0x72, 0x4f, 0xf9, 0x49, 0xa0, 0xc3, 0x55, 0x01, 0x38, 0x3c, 0x09, 0x30, 0x76, 0x71, 0x8e,
0x29, 0x5f, 0x41, 0x5b, 0xc0, 0xf6, 0xe4, 0x29, 0xdf, 0x82, 0x65, 0x1d, 0x5e, 0xe6, 0x83, 0x88,
0x1d, 0x73, 0xed, 0x6c, 0xc7, 0xd3, 0x09, 0x2e, 0x97, 0xef, 0xb3, 0x63, 0x4e, 0x9f, 0xc0, 0x9a,
0x7a, 0x81, 0x9f, 0xa4, 0x4c, 0x2f, 0xfd, 0xf5, 0xb2, 0xfe, 0x97, 0x06, 0x7a, 0x5d, 0x49, 0x96,
0x1d, 0x21, 0x94, 0x8c, 0x02, 0xf5, 0x81, 0xa8, 0xe9, 0xfb, 0x51, 0x92, 0x33, 0x45, 0x90, 0x42,
0x67, 0x18, 0x25, 0x79, 0x39, 0x8c, 0xb0, 0x61, 0xc8, 0xcb, 0x7c, 0x3a, 0x1c, 0xe2, 0xcb, 0x95,
0x26, 0x5e, 0x0f, 0xe9, 0x5f, 0x79, 0xb0, 0x2e, 0xa8, 0x69, 0x5d, 0x61, 0xfc, 0xc2, 0x37, 0xdf,
0x66, 0x67, 0x68, 0x87, 0x35, 0x1b, 0x30, 0x7f, 0x9c, 0x64, 0x43, 0xa6, 0x56, 0x92, 0x83, 0x9f,
0x85, 0xa7, 0xfb, 0x4f, 0x1e, 0xac, 0x89, 0xad, 0x1e, 0xf2, 0x80, 0x4f, 0x73, 0x75, 0xfc, 0x5f,
0x86, 0x2e, 0x1e, 0x95, 0x69, 0xf1, 0x57, 0x1b, 0xdd, 0x30, 0x2f, 0x55, 0x40, 0x25, 0xf2, 0xde,
0x05, 0xdf, 0x45, 0x26, 0x1f, 0x42, 0xc7, 0xce, 0x11, 0x88, 0x3d, 0xb7, 0x77, 0x2f, 0xe9, 0x53,
0x56, 0x24, 0x67, 0xef, 0x82, 0xef, 0x7c, 0x40, 0xee, 0x00, 0x08, 0xcb, 0x2c, 0xc8, 0xaa, 0x30,
0xf0, 0x92, 0xcb, 0x24, 0xeb, 0xb2, 0xf6, 0x2e, 0xf8, 0x16, 0xfa, 0xbd, 0x25, 0x58, 0x90, 0xa6,
0x84, 0x3e, 0x86, 0xae, 0xb3, 0x53, 0xc7, 0x83, 0xef, 0x48, 0x0f, 0xbe, 0x12, 0xe0, 0x35, 0x6a,
0x02, 0xbc, 0x7f, 0x6d, 0x00, 0x41, 0x69, 0x2b, 0x5d, 0xe7, 0xdb, 0xb0, 0xac, 0xd8, 0xef, 0x3a,
0x6f, 0x25, 0xa8, 0xb0, 0x79, 0xc9, 0xc8, 0xf1, 0x60, 0x3a, 0xbe, 0x0d, 0x22, 0x37, 0x81, 0x58,
0x43, 0x1d, 0xb5, 0x4b, 0x7b, 0x50, 0x33, 0x83, 0x8a, 0x4b, 0xba, 0x1f, 0x3a, 0x5e, 0x55, 0x1e,
0x5b, 0x53, 0xdc, 0x6f, 0xed, 0x9c, 0x48, 0x26, 0x4d, 0xf3, 0x13, 0xb4, 0xc9, 0xda, 0xc7, 0xd1,
0xe3, 0xb2, 0x20, 0x2d, 0xbc, 0x56, 0x90, 0x16, 0xcb, 0x82, 0x24, 0x2c, 0x5c, 0x16, 0x9e, 0x06,
0x9c, 0x69, 0xab, 0xa1, 0x86, 0xe8, 0xd2, 0x4c, 0xc2, 0x58, 0x98, 0xea, 0xc1, 0x04, 0x57, 0x57,
0x2e, 0x8d, 0x03, 0xa4, 0x3f, 0xf6, 0x60, 0x15, 0x79, 0xec, 0xc8, 0xe1, 0x07, 0x20, 0x9e, 0xc1,
0x1b, 0x8a, 0xa1, 0x83, 0xfb, 0xd3, 0x4b, 0xe1, 0xfb, 0xd0, 0x12, 0x04, 0x93, 0x94, 0xc5, 0x4a,
0x08, 0x7b, 0xae, 0x10, 0x16, 0x1a, 0x68, 0xef, 0x82, 0x5f, 0x20, 0x5b, 0x22, 0xf8, 0x0f, 0x1e,
0xb4, 0xd5, 0x36, 0xff, 0xd7, 0x8e, 0x77, 0x1f, 0x96, 0x50, 0x1a, 0x2d, 0xbf, 0xd6, 0x8c, 0x51,
0xf3, 0x4f, 0x30, 0xee, 0x41, 0x53, 0xe7, 0x38, 0xdd, 0x65, 0x30, 0xda, 0x2d, 0xa1, 0x6c, 0xf3,
0x01, 0x0f, 0xa3, 0x81, 0x9e, 0x55, 0xe9, 0xb8, 0xba, 0x29, 0xd4, 0x39, 0x39, 0x0f, 0xc6, 0x4c,
0x99, 0x24, 0x39, 0xc0, 0xe8, 0x42, 0x1d, 0xa8, 0xec, 0x50, 0xfd, 0x08, 0x60, 0xab, 0x32, 0x65,
0x9c, 0x2a, 0xe5, 0x47, 0x46, 0xe1, 0xe4, 0x28, 0x31, 0x2e, 0xa9, 0x67, 0xbb, 0x98, 0xce, 0x14,
0x19, 0xc3, 0x45, 0x6d, 0x7b, 0x91, 0xa7, 0x85, 0xa5, 0x6d, 0x08, 0xa7, 0xe1, 0xb6, 0x2b, 0x03,
0xe5, 0x05, 0x35, 0xdc, 0x7e, 0xb5, 0xf5, 0xf4, 0xc8, 0x09, 0xf4, 0x8c, 0x91, 0x57, 0xea, 0xdd,
0x72, 0x04, 0x70, 0xad, 0x77, 0x5f, 0xb3, 0x96, 0xd0, 0x45, 0x23, 0xbd, 0xcc, 0xb9, 0xd4, 0xc8,
0x0c, 0xae, 0xea, 0x39, 0xa1, 0xbf, 0xab, 0xeb, 0x35, 0xdf, 0xe8, 0x6c, 0x8f, 0xf0, 0x63, 0x77,
0xd1, 0xd7, 0x10, 0xee, 0xff, 0xc8, 0x83, 0x65, 0x97, 0x1c, 0x8a, 0x8e, 0x8a, 0x4d, 0xb4, 0x82,
0xd1, 0xce, 0x53, 0x09, 0x5c, 0x8d, 0xae, 0x1a, 0x75, 0xd1, 0x95, 0x1d, 0x43, 0xcd, 0xbd, 0x2e,
0x86, 0x6a, 0xbe, 0x59, 0x0c, 0x35, 0x5f, 0x17, 0x43, 0xf5, 0xff, 0xcb, 0x03, 0x52, 0xbd, 0x5f,
0xf2, 0x58, 0x86, 0x77, 0x31, 0x8b, 0x94, 0x9e, 0xf8, 0x85, 0x37, 0x93, 0x11, 0xcd, 0x43, 0xfd,
0x35, 0x0a, 0xab, 0xad, 0x08, 0x6c, 0x97, 0xa5, 0xeb, 0xd7, 0x4d, 0x95, 0xa2, 0xba, 0xe6, 0xeb,
0xa3, 0xba, 0xf9, 0xd7, 0x47, 0x75, 0x0b, 0xe5, 0xa8, 0xae, 0xff, 0xdb, 0xd0, 0x75, 0x6e, 0xfd,
0x67, 0x77, 0xe2, 0xb2, 0xbb, 0x23, 0x2f, 0xd8, 0x81, 0xf5, 0xff, 0xb3, 0x01, 0xa4, 0x2a, 0x79,
0xff, 0xaf, 0x7b, 0x10, 0x72, 0xe4, 0x28, 0x90, 0x39, 0x25, 0x47, 0x8e, 0xea, 0xf8, 0xbf, 0x54,
0x8a, 0xef, 0xc2, 0x5a, 0xc6, 0x86, 0xc9, 0x29, 0xcb, 0xac, 0xc8, 0x5a, 0x5e, 0x55, 0x75, 0x02,
0x1d, 0x3e, 0x37, 0x96, 0x5d, 0x72, 0x2a, 0x08, 0x96, 0x65, 0x28, 0x85, 0xb4, 0xf4, 0xeb, 0xb0,
0x21, 0x0b, 0x3b, 0xf7, 0x24, 0x29, 0xed, 0x73, 0x5c, 0x87, 0xce, 0x99, 0x4c, 0xe6, 0x0d, 0x92,
0x38, 0x9a, 0x29, 0x23, 0xd2, 0x56, 0xb0, 0x4f, 0xe2, 0x68, 0x46, 0x7f, 0xe8, 0xc1, 0xc5, 0xd2,
0xb7, 0x45, 0xce, 0x5e, 0xaa, 0x5a, 0x57, 0xff, 0xba, 0x40, 0x3c, 0xa2, 0x92, 0x71, 0xeb, 0x88,
0xd2, 0x24, 0x55, 0x27, 0x90, 0x85, 0xd3, 0xb8, 0x8a, 0x2f, 0x2f, 0xa6, 0x6e, 0x8a, 0x6e, 0xc1,
0x45, 0x75, 0xf9, 0xee, 0xd9, 0xe8, 0x2e, 0x6c, 0x96, 0x27, 0x8a, 0xfc, 0x98, 0xbb, 0x65, 0x3d,
0xa4, 0x1f, 0x02, 0xf9, 0xe6, 0x94, 0x65, 0x33, 0x51, 0x1d, 0x30, 0x09, 0xd8, 0xad, 0x72, 0x20,
0xbe, 0x90, 0x4e, 0x8f, 0xbe, 0xc1, 0x66, 0xba, 0xa8, 0xd2, 0x30, 0x45, 0x15, 0x7a, 0x07, 0xd6,
0x1d, 0x02, 0x86, 0x55, 0x0b, 0xa2, 0xc2, 0xa0, 0x83, 0x54, 0xb7, 0x0a, 0xa1, 0xe6, 0xe8, 0x9f,
0x7b, 0x30, 0xb7, 0x97, 0xa4, 0x76, 0x66, 0xc9, 0x73, 0x33, 0x4b, 0x4a, 0x77, 0x0e, 0x8c, 0x6a,
0x6c, 0xa8, 0x97, 0x6f, 0x03, 0x51, 0xf3, 0x05, 0x13, 0x8e, 0x61, 0xda, 0x71, 0x92, 0x9d, 0x05,
0xd9, 0x48, 0xf1, 0xaf, 0x04, 0xc5, 0xed, 0x17, 0x0a, 0x06, 0x7f, 0xa2, 0xd3, 0x20, 0xd2, 0x6b,
0x33, 0x15, 0x59, 0xaa, 0x11, 0xfd, 0xbe, 0x07, 0xf3, 0x62, 0xaf, 0xf8, 0x1a, 0xe4, 0xfd, 0x8a,
0x82, 0x9a, 0xc8, 0xde, 0x79, 0xf2, 0x35, 0x94, 0xc0, 0xa5, 0x32, 0x5b, 0xa3, 0x52, 0x66, 0xbb,
0x02, 0x2d, 0x39, 0x2a, 0xea, 0x52, 0x05, 0x80, 0x5c, 0x85, 0xe6, 0x49, 0x92, 0x6a, 0x1b, 0x06,
0x3a, 0x5d, 0x93, 0xa4, 0xbe, 0x80, 0xd3, 0x1b, 0xb0, 0xf2, 0x24, 0x19, 0x31, 0x2b, 0xa6, 0x3f,
0xf7, 0x9a, 0xe8, 0xef, 0x78, 0xb0, 0xa4, 0x91, 0xc9, 0x36, 0x34, 0xd1, 0x14, 0x95, 0x9c, 0x3f,
0x93, 0x74, 0x45, 0x3c, 0x5f, 0x60, 0xa0, 0x0a, 0x11, 0x11, 0x64, 0xe1, 0x2a, 0xe8, 0xf8, 0xb1,
0x30, 0xc2, 0xe8, 0xb4, 0x8b, 0x3d, 0x97, 0x8c, 0x55, 0x09, 0x4a, 0xff, 0xda, 0x83, 0xae, 0xb3,
0x06, 0xba, 0xf1, 0x51, 0x90, 0x73, 0x95, 0xa8, 0x52, 0x4c, 0xb4, 0x41, 0x76, 0xfe, 0xa7, 0xe1,
0xe6, 0x7f, 0x4c, 0xfe, 0x61, 0xce, 0xce, 0x3f, 0xdc, 0x82, 0x56, 0x51, 0xb2, 0x6c, 0x3a, 0xaa,
0x01, 0x57, 0xd4, 0xe9, 0xe4, 0x02, 0x09, 0xe9, 0x0c, 0x93, 0x28, 0xc9, 0x54, 0x45, 0x4f, 0x0e,
0xe8, 0x1d, 0x68, 0x5b, 0xf8, 0xb8, 0x8d, 0x98, 0xf1, 0xb3, 0x24, 0x7b, 0xa6, 0xd3, 0x50, 0x6a,
0x68, 0xca, 0x28, 0x8d, 0xa2, 0x8c, 0x42, 0xff, 0xc6, 0x83, 0x2e, 0x4a, 0x4a, 0x18, 0x8f, 0x0f,
0x92, 0x28, 0x1c, 0xce, 0x84, 0xc4, 0x68, 0xa1, 0x18, 0x8c, 0x58, 0xc4, 0x03, 0x23, 0x31, 0x2e,
0x18, 0x6d, 0xbe, 0xf6, 0xe2, 0x95, 0xbc, 0x98, 0x31, 0x4a, 0x3e, 0xda, 0xae, 0xa3, 0x20, 0x67,
0xd2, 0xed, 0x57, 0xba, 0xda, 0x01, 0xa2, 0xfa, 0x40, 0x40, 0x16, 0x70, 0x36, 0x98, 0x84, 0x51,
0x14, 0x4a, 0x5c, 0x29, 0xe1, 0x75, 0x53, 0xf4, 0x6f, 0x1b, 0xd0, 0x56, 0x6a, 0xe2, 0xe1, 0x68,
0x2c, 0x33, 0xaa, 0xca, 0x11, 0x31, 0xcf, 0xcf, 0x82, 0xe8, 0x79, 0xc7, 0x75, 0xb1, 0x20, 0xe5,
0x6b, 0x9d, 0xab, 0x5e, 0xeb, 0x15, 0x68, 0xa1, 0x78, 0xdd, 0x16, 0x3e, 0x92, 0xac, 0x70, 0x17,
0x00, 0x3d, 0xbb, 0x2b, 0x66, 0xe7, 0x8b, 0x59, 0x01, 0x70, 0xbc, 0xa2, 0x85, 0x92, 0x57, 0xf4,
0x3e, 0x74, 0x14, 0x19, 0xc1, 0x77, 0x11, 0x54, 0x15, 0x02, 0xee, 0xdc, 0x89, 0xef, 0x60, 0xea,
0x2f, 0x77, 0xf5, 0x97, 0x4b, 0xaf, 0xfb, 0x52, 0x63, 0xd2, 0x8b, 0xb0, 0xae, 0x98, 0xf7, 0x38,
0x0b, 0xd2, 0x13, 0xad, 0x7a, 0x47, 0xa6, 0x8c, 0x2a, 0xc0, 0xe4, 0x06, 0xcc, 0xe3, 0x67, 0x5a,
0xfb, 0xd5, 0x3f, 0x3a, 0x89, 0x42, 0xb6, 0x61, 0x9e, 0x8d, 0xc6, 0x4c, 0x7b, 0xe6, 0xc4, 0x8d,
0x91, 0xf0, 0x8e, 0x7c, 0x89, 0x80, 0x2a, 0x00, 0xa1, 0x25, 0x15, 0xe0, 0x6a, 0xce, 0x05, 0x1c,
0x7e, 0x34, 0xa2, 0x1b, 0x40, 0x9e, 0x48, 0xa9, 0xb5, 0xb3, 0x80, 0xbf, 0x37, 0x07, 0x6d, 0x0b,
0x8c, 0xaf, 0x79, 0x8c, 0x1b, 0x1e, 0x8c, 0xc2, 0x60, 0xc2, 0x38, 0xcb, 0x94, 0xa4, 0x96, 0xa0,
0x42, 0xc1, 0x9e, 0x8e, 0x07, 0xc9, 0x94, 0x0f, 0x46, 0x6c, 0x9c, 0x31, 0x69, 0xd0, 0x3c, 0xbf,
0x04, 0x45, 0xbc, 0x49, 0xf0, 0xdc, 0xc6, 0x93, 0xf2, 0x50, 0x82, 0xea, 0x9c, 0x9e, 0xe4, 0x51,
0xb3, 0xc8, 0xe9, 0x49, 0x8e, 0x94, 0xf5, 0xd0, 0x7c, 0x8d, 0x1e, 0x7a, 0x0f, 0x36, 0xa5, 0xc6,
0x51, 0x6f, 0x73, 0x50, 0x12, 0x93, 0x73, 0x66, 0xc9, 0x0d, 0x58, 0xc5, 0x3d, 0x6b, 0x01, 0xcf,
0xc3, 0xef, 0xca, 0x68, 0xdc, 0xf3, 0x2b, 0x70, 0xc4, 0xc5, 0xe7, 0xe8, 0xe0, 0xca, 0x92, 0x43,
0x05, 0x2e, 0x70, 0x83, 0xe7, 0x2e, 0x6e, 0x4b, 0xe1, 0x96, 0xe0, 0xb4, 0x0b, 0xed, 0x43, 0x9e,
0xa4, 0xfa, 0x52, 0x96, 0xa1, 0x23, 0x87, 0xaa, 0xcc, 0x74, 0x19, 0x2e, 0x09, 0x29, 0x7a, 0x9a,
0xa4, 0x49, 0x94, 0x8c, 0x67, 0x87, 0xd3, 0xa3, 0x7c, 0x98, 0x85, 0x29, 0x7a, 0xcc, 0xf4, 0xef,
0x3d, 0x58, 0x77, 0x66, 0x55, 0xa8, 0xff, 0x8b, 0x52, 0xa4, 0x4d, 0x65, 0x40, 0x0a, 0xde, 0x9a,
0xa5, 0x0e, 0x25, 0xa2, 0x4c, 0x9c, 0x7c, 0xaa, 0x8a, 0x05, 0x77, 0x61, 0x45, 0xef, 0x4c, 0x7f,
0x28, 0xa5, 0xb0, 0x57, 0x95, 0x42, 0xf5, 0xfd, 0xb2, 0xfa, 0x40, 0x93, 0xf8, 0x15, 0xe9, 0x77,
0xb2, 0x91, 0x38, 0xa3, 0x8e, 0xf9, 0xfa, 0xfa, 0x7b, 0xdb, 0xd9, 0xd5, 0x3b, 0x18, 0x1a, 0x60,
0x4e, 0xff, 0xc8, 0x03, 0x28, 0x76, 0x87, 0x82, 0x51, 0xa8, 0x74, 0x4f, 0xe4, 0x4c, 0x2d, 0xf5,
0x7d, 0x1d, 0x3a, 0x26, 0x33, 0x5d, 0x58, 0x89, 0xb6, 0x86, 0xa1, 0x87, 0xf2, 0x0e, 0xac, 0x8c,
0xa3, 0xe4, 0x48, 0xd8, 0x5c, 0x51, 0xd1, 0xcc, 0x55, 0xb1, 0x6d, 0x59, 0x82, 0x1f, 0x29, 0x68,
0x61, 0x52, 0x9a, 0x96, 0x49, 0xa1, 0x7f, 0xdc, 0x30, 0xf9, 0xd1, 0xe2, 0xcc, 0xe7, 0xbe, 0x32,
0xb2, 0x5b, 0x51, 0x8e, 0xe7, 0xa4, 0x23, 0x45, 0x76, 0xe3, 0xe0, 0xb5, 0x81, 0xde, 0x1d, 0x58,
0xce, 0xa4, 0xf6, 0xd1, 0xaa, 0xa9, 0xf9, 0x0a, 0xd5, 0xd4, 0xcd, 0x1c, 0xbb, 0xf3, 0x73, 0xb0,
0x1a, 0x8c, 0x4e, 0x59, 0xc6, 0x43, 0xe1, 0xf1, 0x0b, 0xa3, 0x2f, 0x15, 0xea, 0x8a, 0x05, 0x17,
0xb6, 0xf8, 0x1d, 0x58, 0x51, 0x05, 0x4e, 0x83, 0xa9, 0xfa, 0x56, 0x0a, 0x30, 0x22, 0xd2, 0xbf,
0xd4, 0xa9, 0x58, 0xf7, 0x0e, 0xcf, 0xe7, 0x88, 0x7d, 0xba, 0x46, 0xe9, 0x74, 0x5f, 0x51, 0x69,
0xd1, 0x91, 0x0e, 0x2b, 0x54, 0x82, 0x5a, 0x02, 0x55, 0x1a, 0xdb, 0x65, 0x69, 0xf3, 0x4d, 0x58,
0x4a, 0x7f, 0x38, 0x07, 0x8b, 0x1f, 0xc5, 0xa7, 0x49, 0x38, 0x14, 0x49, 0xca, 0x09, 0x9b, 0x24,
0xba, 0xcd, 0x00, 0x7f, 0xa3, 0x45, 0x17, 0x15, 0xb4, 0x94, 0xab, 0xec, 0xa1, 0x1e, 0xa2, 0x75,
0xcb, 0x8a, 0xd6, 0x1a, 0x29, 0x29, 0x16, 0x04, 0xfd, 0xc3, 0xcc, 0xee, 0x16, 0x52, 0xa3, 0xa2,
0x4f, 0x63, 0xde, 0xea, 0xd3, 0x10, 0x29, 0x6d, 0x59, 0x1c, 0x14, 0xec, 0x5c, 0xf2, 0xf5, 0x50,
0xf8, 0xb1, 0x19, 0x93, 0x41, 0xaf, 0xb0, 0x93, 0x8b, 0xca, 0x8f, 0xb5, 0x81, 0x68, 0x4b, 0xe5,
0x07, 0x12, 0x47, 0xea, 0x1a, 0x1b, 0x84, 0xbe, 0x45, 0xb9, 0xe1, 0xa8, 0x25, 0xaf, 0xb8, 0x04,
0x46, 0x85, 0x34, 0x62, 0x46, 0x6f, 0xc8, 0x33, 0x80, 0x6c, 0x1d, 0x2a, 0xc3, 0x2d, 0x2f, 0x58,
0x16, 0x39, 0xd5, 0x48, 0xf8, 0x20, 0x41, 0x14, 0x1d, 0x05, 0xc3, 0x67, 0xa2, 0x0d, 0x4c, 0xd4,
0x34, 0x5b, 0xbe, 0x0b, 0xc4, 0x5d, 0x0f, 0x23, 0x7e, 0x3a, 0x50, 0x24, 0xba, 0xb2, 0x26, 0x69,
0x81, 0xe8, 0x67, 0x40, 0xee, 0x8e, 0x46, 0xea, 0x86, 0x4c, 0x8c, 0x50, 0xf0, 0xd6, 0x73, 0x78,
0x5b, 0x73, 0xc6, 0x46, 0xed, 0x19, 0xe9, 0x43, 0x68, 0x1f, 0x58, 0xdd, 0x5b, 0xe2, 0x32, 0x75,
0xdf, 0x96, 0x12, 0x00, 0x0b, 0x62, 0x2d, 0xd8, 0xb0, 0x17, 0xa4, 0xbf, 0x04, 0x64, 0x3f, 0xcc,
0xb9, 0xd9, 0x9f, 0x09, 0x15, 0x4d, 0xc6, 0xcb, 0x0a, 0x15, 0x15, 0x4c, 0x84, 0x8a, 0x77, 0x65,
0x69, 0xb4, 0x7c, 0xb0, 0x1b, 0xb0, 0x14, 0x4a, 0x90, 0xd6, 0xc3, 0xcb, 0x4a, 0x80, 0x35, 0xa6,
0x99, 0x47, 0x87, 0x42, 0x01, 0x1d, 0x35, 0xff, 0x7d, 0x0f, 0x16, 0xd5, 0xd1, 0xd0, 0x1c, 0x3a,
0x7d, 0x6b, 0xf2, 0x60, 0x0e, 0xac, 0xbe, 0x6f, 0xa8, 0x2a, 0x75, 0x73, 0x75, 0x52, 0x47, 0xa0,
0x99, 0x06, 0xfc, 0x44, 0x78, 0xd0, 0x2d, 0x5f, 0xfc, 0xd6, 0x91, 0xd2, 0xbc, 0x89, 0x94, 0x74,
0x19, 0x58, 0x6d, 0xca, 0x64, 0x2d, 0xef, 0xc9, 0x32, 0x70, 0x01, 0x2e, 0x78, 0xa0, 0x36, 0x58,
0xe6, 0x81, 0x42, 0xf5, 0xcd, 0x3c, 0xed, 0x43, 0xef, 0x01, 0x8b, 0x18, 0x67, 0x77, 0xa3, 0xa8,
0x4c, 0xff, 0x32, 0x5c, 0xaa, 0x99, 0x53, 0x96, 0xf2, 0x11, 0xac, 0x3d, 0x60, 0x47, 0xd3, 0xf1,
0x3e, 0x3b, 0x2d, 0xca, 0x0a, 0x04, 0x9a, 0xf9, 0x49, 0x72, 0xa6, 0xee, 0x4b, 0xfc, 0x26, 0x5f,
0x02, 0x88, 0x10, 0x67, 0x90, 0xa7, 0x6c, 0xa8, 0x9b, 0x5e, 0x04, 0xe4, 0x30, 0x65, 0x43, 0xfa,
0x1e, 0x10, 0x9b, 0x8e, 0x3a, 0x02, 0xbe, 0xc6, 0xe9, 0xd1, 0x20, 0x9f, 0xe5, 0x9c, 0x4d, 0x74,
0x37, 0x8f, 0x0d, 0xa2, 0xef, 0x40, 0xe7, 0x20, 0x98, 0xf9, 0xec, 0x0b, 0xd5, 0x0e, 0x88, 0x01,
0x59, 0x30, 0x43, 0xf1, 0x34, 0x01, 0x99, 0x98, 0xa6, 0x7f, 0xd7, 0x80, 0x05, 0x89, 0x89, 0x54,
0x47, 0x2c, 0xe7, 0x61, 0x2c, 0xd3, 0xea, 0x8a, 0xaa, 0x05, 0xaa, 0xdc, 0x77, 0xa3, 0xe6, 0xbe,
0x95, 0x8b, 0xa4, 0x1b, 0x04, 0xd4, 0xc5, 0x3a, 0x30, 0x11, 0x6f, 0x86, 0x13, 0x26, 0xbb, 0x42,
0x9b, 0x2a, 0xde, 0xd4, 0x80, 0x52, 0xe4, 0x5b, 0xbc, 0x79, 0xb9, 0x3f, 0x2d, 0x88, 0xca, 0x2c,
0xd8, 0xa0, 0x5a, 0xcd, 0xb2, 0x28, 0xfb, 0xff, 0x2a, 0x9a, 0xa5, 0xa2, 0x41, 0x96, 0xde, 0x40,
0x83, 0x48, 0xbf, 0xc9, 0xd1, 0x20, 0x04, 0x56, 0x1f, 0x31, 0xe6, 0xb3, 0x34, 0xc9, 0x4c, 0x4f,
0xe5, 0x0f, 0x3c, 0x58, 0x55, 0x16, 0xc1, 0xcc, 0x91, 0xeb, 0x8e, 0xf9, 0xf0, 0xea, 0x32, 0xad,
0x6f, 0x41, 0x57, 0x04, 0x50, 0x18, 0x1d, 0x89, 0x68, 0x49, 0xe5, 0x14, 0x1c, 0x20, 0xee, 0x49,
0xe7, 0x0e, 0x27, 0x61, 0xa4, 0x18, 0x6c, 0x83, 0xd0, 0xd4, 0xe9, 0x00, 0x4b, 0xb0, 0xd7, 0xf3,
0xcd, 0x98, 0x1e, 0xc0, 0x9a, 0xb5, 0x5f, 0x25, 0x50, 0x77, 0x40, 0x57, 0x25, 0x65, 0x8a, 0x40,
0xbe, 0x8b, 0x2d, 0xd7, 0xb8, 0x15, 0x9f, 0x39, 0xc8, 0xf4, 0x9f, 0x3d, 0x58, 0x97, 0x86, 0x5e,
0xb9, 0x51, 0xa6, 0x91, 0x69, 0x41, 0x7a, 0x36, 0x52, 0xe0, 0xf7, 0x2e, 0xf8, 0x6a, 0x4c, 0xbe,
0xf6, 0x86, 0xce, 0x89, 0x29, 0x00, 0x9e, 0xc3, 0x9e, 0xb9, 0x3a, 0xf6, 0xbc, 0xe2, 0xf0, 0x75,
0x01, 0xf0, 0x7c, 0x6d, 0x00, 0x7c, 0x6f, 0x11, 0xe6, 0xf3, 0x61, 0x92, 0x32, 0xba, 0x09, 0x1b,
0xee, 0xe1, 0x24, 0xcb, 0x76, 0xff, 0xc5, 0x83, 0x65, 0x99, 0x8c, 0x93, 0xdd, 0xda, 0x2c, 0x23,
0x18, 0x6b, 0x59, 0x4d, 0xe0, 0xc4, 0xb8, 0x9a, 0xd5, 0x66, 0xf2, 0xfe, 0xe5, 0xda, 0x39, 0xed,
0x67, 0x7f, 0xef, 0xc7, 0xff, 0xfe, 0x27, 0x8d, 0x8b, 0x74, 0x75, 0xe7, 0xf4, 0xf6, 0x8e, 0x50,
0x89, 0xec, 0x4c, 0x60, 0x7c, 0xe0, 0xdd, 0xc0, 0x55, 0xec, 0xfe, 0x70, 0xb3, 0x4a, 0x4d, 0x9f,
0xb9, 0x59, 0xa5, 0xb6, 0xa1, 0xdc, 0x59, 0x65, 0x2a, 0x30, 0xcc, 0x2a, 0xbb, 0xff, 0xdd, 0x87,
0x96, 0x09, 0x0a, 0xc9, 0x77, 0xa0, 0xeb, 0x24, 0x1e, 0x89, 0x26, 0x5c, 0x97, 0xca, 0xec, 0x5f,
0xa9, 0x9f, 0x54, 0xcb, 0x5e, 0x15, 0xcb, 0xf6, 0xc8, 0x26, 0x2e, 0xab, 0xb2, 0x7d, 0x3b, 0x22,
0x23, 0x2b, 0x3b, 0x19, 0x9e, 0xc1, 0xb2, 0x9b, 0x2c, 0x24, 0x57, 0x5c, 0xd1, 0x28, 0xad, 0xf6,
0xa5, 0x73, 0x66, 0xd5, 0x72, 0x57, 0xc4, 0x72, 0x9b, 0x64, 0xc3, 0x5e, 0xce, 0x04, 0x6b, 0x4c,
0xf4, 0x9e, 0xd8, 0x8d, 0xe3, 0x44, 0xd3, 0xab, 0x6f, 0x28, 0xef, 0x5f, 0xaa, 0x36, 0x89, 0xab,
0xae, 0x72, 0xda, 0x13, 0x4b, 0x11, 0x22, 0x18, 0x6a, 0xf7, 0x8d, 0x93, 0x6f, 0x43, 0xcb, 0xb4,
0x9d, 0x92, 0x2d, 0xab, 0xd7, 0xd7, 0xee, 0x85, 0xed, 0xf7, 0xaa, 0x13, 0x75, 0x57, 0x65, 0x53,
0x46, 0x81, 0xd8, 0x87, 0x8b, 0xca, 0x42, 0x1f, 0xb1, 0x9f, 0xe4, 0x24, 0x35, 0xed, 0xee, 0xb7,
0x3c, 0x72, 0x07, 0x96, 0x74, 0x37, 0x2f, 0xd9, 0xac, 0xef, 0x4a, 0xee, 0x6f, 0x55, 0xe0, 0x4a,
0x8f, 0xdc, 0x05, 0x28, 0x1a, 0x4f, 0x49, 0xef, 0xbc, 0xfe, 0x58, 0xc3, 0xc4, 0x9a, 0x2e, 0xd5,
0xb1, 0xe8, 0xbb, 0x75, 0xfb, 0x5a, 0xc9, 0x97, 0x0b, 0xfc, 0xda, 0x8e, 0xd7, 0x57, 0x10, 0xa4,
0x9b, 0x82, 0x77, 0xab, 0x64, 0x19, 0x79, 0x17, 0xb3, 0x33, 0xdd, 0x85, 0xf5, 0x00, 0xda, 0x56,
0x33, 0x2b, 0xd1, 0x14, 0xaa, 0x8d, 0xb0, 0xfd, 0x7e, 0xdd, 0x94, 0xda, 0xee, 0xaf, 0x41, 0xd7,
0xe9, 0x4a, 0x35, 0x2f, 0xa3, 0xae, 0xe7, 0xd5, 0xbc, 0x8c, 0xfa, 0x46, 0xd6, 0x6f, 0x41, 0xdb,
0xea, 0x21, 0x25, 0x56, 0x45, 0xbb, 0xd4, 0x23, 0x6a, 0x76, 0x54, 0xd3, 0x72, 0x4a, 0x37, 0xc4,
0x79, 0x97, 0x69, 0x0b, 0xcf, 0x2b, 0x5a, 0x91, 0x50, 0x48, 0xbe, 0x03, 0xcb, 0x6e, 0xef, 0xa8,
0x79, 0x55, 0xb5, 0x5d, 0xa8, 0xe6, 0x55, 0x9d, 0xd3, 0x70, 0xaa, 0x04, 0xf2, 0xc6, 0xba, 0x59,
0x64, 0xe7, 0x85, 0x4a, 0x89, 0xbe, 0x24, 0xdf, 0x44, 0xd5, 0xa1, 0x7a, 0xc3, 0x48, 0xd1, 0x4b,
0xeb, 0x76, 0x90, 0x19, 0x69, 0xaf, 0xb4, 0x91, 0xd1, 0x35, 0x41, 0xbc, 0x4d, 0x8a, 0x13, 0x90,
0x8f, 0x61, 0x51, 0xf5, 0x88, 0x91, 0x8b, 0x85, 0x54, 0x5b, 0x09, 0xa4, 0xfe, 0x66, 0x19, 0xac,
0x88, 0xad, 0x0b, 0x62, 0x5d, 0xd2, 0x46, 0x62, 0x63, 0xc6, 0x43, 0xa4, 0x11, 0xc3, 0x4a, 0xa9,
0x8a, 0x65, 0x1e, 0x4b, 0x7d, 0x0d, 0xbc, 0x7f, 0xf5, 0xd5, 0xc5, 0x2f, 0x57, 0xcd, 0x68, 0xf5,
0xb2, 0xa3, 0x5b, 0x16, 0x7e, 0x13, 0x3a, 0x76, 0x4b, 0xa2, 0xd1, 0xd9, 0x35, 0xed, 0x8b, 0x46,
0x67, 0xd7, 0xf5, 0x30, 0xea, 0xcb, 0x25, 0x1d, 0x7b, 0x19, 0xf2, 0x2d, 0x58, 0xb1, 0xea, 0xa5,
0x87, 0xb3, 0x78, 0x68, 0x84, 0xa7, 0xda, 0xdd, 0xd2, 0xaf, 0xb3, 0xb4, 0x74, 0x4b, 0x10, 0x5e,
0xa3, 0x0e, 0x61, 0x14, 0x9c, 0xfb, 0xd0, 0xb6, 0x6b, 0xb1, 0xaf, 0xa0, 0xbb, 0x65, 0x4d, 0xd9,
0xcd, 0x1e, 0xb7, 0x3c, 0xf2, 0x67, 0x1e, 0x74, 0xec, 0xbe, 0x29, 0xe2, 0x64, 0x61, 0x4a, 0x74,
0x7a, 0xf6, 0x9c, 0x4d, 0x88, 0x3e, 0x11, 0x9b, 0xdc, 0xbb, 0xf1, 0xc8, 0x61, 0xf2, 0x0b, 0xc7,
0x89, 0xba, 0x69, 0xff, 0xd3, 0xe3, 0x65, 0x79, 0xd2, 0xee, 0xfe, 0x79, 0x79, 0xcb, 0x23, 0x1f,
0xc8, 0xff, 0xf3, 0xe8, 0x80, 0x86, 0x58, 0x8a, 0xad, 0xcc, 0x2e, 0xfb, 0x4f, 0x32, 0xdb, 0xde,
0x2d, 0x8f, 0xfc, 0x96, 0xfc, 0x73, 0x87, 0xfa, 0x56, 0x70, 0xfd, 0x4d, 0xbf, 0xa7, 0x6f, 0x89,
0x93, 0x5c, 0xa5, 0x97, 0x9c, 0x93, 0x94, 0x35, 0xfb, 0x01, 0x40, 0x11, 0x9d, 0x92, 0x52, 0xa8,
0x66, 0x74, 0x5e, 0x35, 0x80, 0x75, 0x6f, 0x53, 0x47, 0x74, 0x52, 0x0d, 0x74, 0xac, 0xb8, 0x30,
0x37, 0xd7, 0x59, 0x8d, 0x32, 0xfb, 0xfd, 0xba, 0x29, 0x45, 0xff, 0x2b, 0x82, 0xfe, 0x97, 0xc8,
0x65, 0x9b, 0xfe, 0xce, 0x0b, 0x3b, 0x2a, 0x7d, 0x49, 0x3e, 0x83, 0xee, 0x7e, 0x92, 0x3c, 0x9b,
0xa6, 0x26, 0x01, 0xe2, 0xc6, 0x59, 0x18, 0x19, 0xf7, 0x4b, 0x87, 0xa2, 0xd7, 0x05, 0xe5, 0xcb,
0xe4, 0x92, 0x4b, 0xb9, 0x88, 0x95, 0x5f, 0x92, 0x00, 0xd6, 0x8c, 0xbd, 0x33, 0x07, 0xe9, 0xbb,
0x74, 0xec, 0x90, 0xb5, 0xb2, 0x86, 0xe3, 0x81, 0x98, 0x35, 0x72, 0x4d, 0xf3, 0x96, 0x47, 0x0e,
0xa0, 0xf3, 0x80, 0x0d, 0x93, 0x11, 0x53, 0xa1, 0xd1, 0x7a, 0xb1, 0x73, 0x13, 0x53, 0xf5, 0xbb,
0x0e, 0xd0, 0xd5, 0x00, 0x69, 0x30, 0xcb, 0xd8, 0x17, 0x3b, 0x2f, 0x54, 0xd0, 0xf5, 0x52, 0x6b,
0x00, 0x1d, 0x28, 0x3a, 0x1a, 0xa0, 0x14, 0x59, 0x3a, 0x1a, 0xa0, 0x12, 0x59, 0x3a, 0x1a, 0x40,
0x07, 0xaa, 0x24, 0xc2, 0x78, 0xb3, 0x14, 0x8c, 0x1a, 0xab, 0x79, 0x5e, 0x08, 0xdb, 0xbf, 0x76,
0x3e, 0x82, 0xbb, 0xda, 0x0d, 0x77, 0xb5, 0x43, 0xe8, 0x3e, 0x60, 0x92, 0x59, 0xb2, 0xaa, 0xd0,
0x77, 0x55, 0x8a, 0x5d, 0x81, 0x28, 0xab, 0x1b, 0x31, 0xe7, 0xaa, 0x78, 0x91, 0xd2, 0x27, 0xdf,
0x86, 0xf6, 0x63, 0xc6, 0x75, 0x19, 0xc1, 0xf8, 0x1e, 0xa5, 0xba, 0x42, 0xbf, 0xa6, 0x0a, 0x41,
0xaf, 0x09, 0x6a, 0x7d, 0xd2, 0x33, 0xd4, 0x76, 0xd8, 0x68, 0xcc, 0xe4, 0xe3, 0x1f, 0x84, 0xa3,
0x97, 0xe4, 0xd7, 0x05, 0x71, 0x53, 0x79, 0xdc, 0xb4, 0xb2, 0xcf, 0x36, 0xf1, 0x95, 0x12, 0xbc,
0x8e, 0x72, 0x9c, 0x8c, 0x98, 0x65, 0xec, 0x62, 0x68, 0x5b, 0x65, 0x66, 0xf3, 0xa0, 0xaa, 0xb5,
0x6b, 0xf3, 0xa0, 0x6a, 0xaa, 0xd2, 0x74, 0x5b, 0xac, 0x43, 0xc9, 0xb5, 0x62, 0x1d, 0x59, 0x89,
0x2e, 0x56, 0xda, 0x79, 0x11, 0x4c, 0xf8, 0x4b, 0xf2, 0xb9, 0x68, 0xa0, 0xb6, 0x4b, 0x25, 0x85,
0xef, 0x53, 0xae, 0xaa, 0x18, 0x66, 0x59, 0x53, 0xae, 0x3f, 0x24, 0x97, 0x12, 0x36, 0xf1, 0x6b,
0x00, 0x87, 0x3c, 0x49, 0x1f, 0x04, 0x6c, 0x92, 0xc4, 0x85, 0x26, 0x2b, 0xca, 0x01, 0x85, 0x26,
0xb3, 0x6a, 0x02, 0xe4, 0x73, 0xcb, 0xfb, 0x74, 0x2a, 0x4d, 0x5a, 0xb8, 0xce, 0xad, 0x18, 0x18,
0x86, 0xd4, 0x54, 0x0d, 0x6e, 0x79, 0xe8, 0x4b, 0x16, 0xa9, 0x0f, 0xe3, 0x4b, 0x56, 0xb2, 0x2a,
0x46, 0x0d, 0xd6, 0xe4, 0x49, 0x0e, 0xa0, 0x55, 0xc4, 0xdf, 0xda, 0x3c, 0x95, 0xa3, 0x75, 0x63,
0x6f, 0x2a, 0x61, 0x31, 0x5d, 0x15, 0xac, 0x02, 0xb2, 0x84, 0xac, 0x12, 0x95, 0xf2, 0x21, 0xac,
0xcb, 0x0d, 0x1a, 0xe3, 0x29, 0x12, 0xdc, 0xfa, 0x24, 0x35, 0x61, 0xb0, 0x79, 0xcd, 0x75, 0x51,
0xa4, 0xf6, 0x4e, 0xa8, 0x59, 0xe1, 0x03, 0xef, 0xc6, 0xd1, 0x82, 0xf8, 0x1b, 0xf2, 0x57, 0xff,
0x27, 0x00, 0x00, 0xff, 0xff, 0x33, 0xf0, 0xc8, 0xda, 0xb8, 0x3c, 0x00, 0x00,
}

@ -523,15 +523,15 @@ func request_Lightning_FeeReport_0(ctx context.Context, marshaler runtime.Marsha
}
func request_Lightning_UpdateFees_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq FeeUpdateRequest
func request_Lightning_UpdateChannelPolicy_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq PolicyUpdateRequest
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.UpdateFees(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.UpdateChannelPolicy(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
@ -1452,7 +1452,7 @@ func RegisterLightningHandler(ctx context.Context, mux *runtime.ServeMux, conn *
})
mux.Handle("POST", pattern_Lightning_UpdateFees_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("POST", pattern_Lightning_UpdateChannelPolicy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
if cn, ok := w.(http.CloseNotifier); ok {
@ -1470,14 +1470,14 @@ func RegisterLightningHandler(ctx context.Context, mux *runtime.ServeMux, conn *
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Lightning_UpdateFees_0(rctx, inboundMarshaler, client, req, pathParams)
resp, md, err := request_Lightning_UpdateChannelPolicy_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Lightning_UpdateFees_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_Lightning_UpdateChannelPolicy_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@ -1539,7 +1539,7 @@ var (
pattern_Lightning_FeeReport_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "fees"}, ""))
pattern_Lightning_UpdateFees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "fees"}, ""))
pattern_Lightning_UpdateChannelPolicy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "fees"}, ""))
)
var (
@ -1597,5 +1597,5 @@ var (
forward_Lightning_FeeReport_0 = runtime.ForwardResponseMessage
forward_Lightning_UpdateFees_0 = runtime.ForwardResponseMessage
forward_Lightning_UpdateChannelPolicy_0 = runtime.ForwardResponseMessage
)

@ -441,11 +441,11 @@ service Lightning {
};
}
/** lncli: `updatefees`
UpdateFees allows the caller to update the fee schedule for all channels
globally, or a particular channel.
/** lncli: `updatechanpolicy`
UpdateChannelPolicy allows the caller to update the fee schedule and
channel policies for all channels globally, or a particular channel.
*/
rpc UpdateFees(FeeUpdateRequest) returns (FeeUpdateResponse) {
rpc UpdateChannelPolicy(PolicyUpdateRequest) returns (PolicyUpdateResponse) {
option (google.api.http) = {
post: "/v1/fees"
body: "*"
@ -877,6 +877,9 @@ message OpenChannelRequest {
/// Whether this channel should be private, not announced to the greater network.
bool private = 8 [json_name = "private"];
/// The minimum value in millisatoshi we will require for incoming HTLCs on the channel.
int64 min_htlc_msat = 9 [json_name = "min_htlc_msat"];
}
message OpenStatusUpdate {
oneof update {
@ -1401,12 +1404,12 @@ message FeeReportResponse {
repeated ChannelFeeReport channel_fees = 1 [json_name = "channel_fees"];
}
message FeeUpdateRequest {
message PolicyUpdateRequest {
oneof scope {
/// If set, then this fee update applies to all currently active channels.
/// If set, then this update applies to all currently active channels.
bool global = 1 [json_name = "global"] ;
/// If set, this fee update will target a specific channel.
/// If set, this update will target a specific channel.
ChannelPoint chan_point = 2 [json_name = "chan_point"];
}
@ -1415,6 +1418,9 @@ message FeeUpdateRequest {
/// The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6.
double fee_rate = 4 [json_name = "fee_rate"];
/// The required timelock delta for HTLCs forwarded over the channel.
uint32 time_lock_delta = 5 [json_name = "time_lock_delta"];
}
message FeeUpdateResponse {
message PolicyUpdateResponse {
}

@ -222,13 +222,13 @@
]
},
"post": {
"summary": "* lncli: `updatefees`\nUpdateFees allows the caller to update the fee schedule for all channels\nglobally, or a particular channel.",
"operationId": "UpdateFees",
"summary": "* lncli: `updatechanpolicy`\nUpdateChannelPolicy allows the caller to update the fee schedule and\nchannel policies for all channels globally, or a particular channel.",
"operationId": "UpdateChannelPolicy",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/lnrpcFeeUpdateResponse"
"$ref": "#/definitions/lnrpcPolicyUpdateResponse"
}
}
},
@ -238,7 +238,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/lnrpcFeeUpdateRequest"
"$ref": "#/definitions/lnrpcPolicyUpdateRequest"
}
}
],
@ -1166,33 +1166,6 @@
}
}
},
"lnrpcFeeUpdateRequest": {
"type": "object",
"properties": {
"global": {
"type": "boolean",
"format": "boolean",
"description": "/ If set, then this fee update applies to all currently active channels."
},
"chan_point": {
"$ref": "#/definitions/lnrpcChannelPoint",
"description": "/ If set, this fee update will target a specific channel."
},
"base_fee_msat": {
"type": "string",
"format": "int64",
"description": "/ The base fee charged regardless of the number of milli-satoshis sent."
},
"fee_rate": {
"type": "number",
"format": "double",
"description": "/ The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6."
}
}
},
"lnrpcFeeUpdateResponse": {
"type": "object"
},
"lnrpcGetInfoResponse": {
"type": "object",
"properties": {
@ -1616,6 +1589,11 @@
"type": "boolean",
"format": "boolean",
"description": "/ Whether this channel should be private, not announced to the greater network."
},
"min_htlc_msat": {
"type": "string",
"format": "int64",
"description": "/ The minimum value in millisatoshi we will require for incoming HTLCs on the channel."
}
}
},
@ -1826,6 +1804,38 @@
}
}
},
"lnrpcPolicyUpdateRequest": {
"type": "object",
"properties": {
"global": {
"type": "boolean",
"format": "boolean",
"description": "/ If set, then this update applies to all currently active channels."
},
"chan_point": {
"$ref": "#/definitions/lnrpcChannelPoint",
"description": "/ If set, this update will target a specific channel."
},
"base_fee_msat": {
"type": "string",
"format": "int64",
"description": "/ The base fee charged regardless of the number of milli-satoshis sent."
},
"fee_rate": {
"type": "number",
"format": "double",
"description": "/ The effective fee rate in milli-satoshis. The precision of this value goes up to 6 decimal places, so 1e-6."
},
"time_lock_delta": {
"type": "integer",
"format": "int64",
"description": "/ The required timelock delta for HTLCs forwarded over the channel."
}
}
},
"lnrpcPolicyUpdateResponse": {
"type": "object"
},
"lnrpcQueryRoutesResponse": {
"type": "object",
"properties": {

@ -122,7 +122,8 @@ func (cfg nodeConfig) genArgs() []string {
args = append(args, "--nobootstrap")
args = append(args, "--noencryptwallet")
args = append(args, "--debuglevel=debug")
args = append(args, "--defaultchanconfs=1")
args = append(args, "--bitcoin.defaultchanconfs=1")
args = append(args, "--bitcoin.defaultremotedelay=4")
args = append(args, fmt.Sprintf("--bitcoin.rpchost=%v", cfg.RPCConfig.Host))
args = append(args, fmt.Sprintf("--bitcoin.rpcuser=%v", cfg.RPCConfig.User))
args = append(args, fmt.Sprintf("--bitcoin.rpcpass=%v", cfg.RPCConfig.Pass))

@ -89,8 +89,12 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey,
if err != nil {
return err
}
// TODO(halseth): make configurable?
minHtlc := lnwire.NewMSatFromSatoshis(1)
updateStream, errChan := c.server.OpenChannel(-1, target, amt, 0,
feePerWeight, false)
minHtlc, feePerWeight, false)
select {
case err := <-errChan:

@ -94,6 +94,18 @@ type FeeSchema struct {
FeeRate uint32
}
// ChannelPolicy holds the parameters that determine the policy we enforce
// when fowarding payments on a channel. These parameters are communicated
// to the rest of the network in ChannelUpdate messages.
type ChannelPolicy struct {
// FeeSchema holds the fee configuration for a channel.
FeeSchema
// TimeLockDelta is the required HTLC timelock delta to be used
// when forwarding payments.
TimeLockDelta uint32
}
// Config defines the configuration for the ChannelRouter. ALL elements within
// the configuration MUST be non-nil for the ChannelRouter to carry out its
// duties.

@ -551,6 +551,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
remoteInitialBalance := btcutil.Amount(in.PushSat)
minHtlc := lnwire.MilliSatoshi(in.MinHtlcMsat)
// Ensure that the initial balance of the remote party (if pushing
// satoshis) does not exceed the amount the local party has requested
@ -627,7 +628,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
updateChan, errChan := r.server.OpenChannel(
in.TargetPeerId, nodePubKey, localFundingAmt,
lnwire.NewMSatFromSatoshis(remoteInitialBalance),
feePerByte, in.Private,
minHtlc, feePerByte, in.Private,
)
var outpoint wire.OutPoint
@ -722,6 +723,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
remoteInitialBalance := btcutil.Amount(in.PushSat)
minHtlc := lnwire.MilliSatoshi(in.MinHtlcMsat)
// Ensure that the initial balance of the remote party (if pushing
// satoshis) does not exceed the amount the local party has requested
@ -746,7 +748,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
updateChan, errChan := r.server.OpenChannel(
in.TargetPeerId, nodepubKey, localFundingAmt,
lnwire.NewMSatFromSatoshis(remoteInitialBalance),
feePerByte, in.Private,
minHtlc, feePerByte, in.Private,
)
select {
@ -2083,7 +2085,7 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
zpay32.CLTVExpiry(invoice.CltvExpiry))
default:
// TODO(roasbeef): assumes set delta between versions
defaultDelta := defaultBitcoinForwardingPolicy.TimeLockDelta
defaultDelta := cfg.Bitcoin.TimeLockDelta
options = append(options, zpay32.CLTVExpiry(uint64(defaultDelta)))
}
@ -3192,13 +3194,13 @@ func (r *rpcServer) FeeReport(ctx context.Context,
// 0.000001, or 0.0001%.
const minFeeRate = 1e-6
// UpdateFees allows the caller to update the fee schedule for all channels
// globally, or a particular channel.
func (r *rpcServer) UpdateFees(ctx context.Context,
req *lnrpc.FeeUpdateRequest) (*lnrpc.FeeUpdateResponse, error) {
// UpdateChannelPolicy allows the caller to update the channel forwarding policy
// for all channels globally, or a particular channel.
func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
req *lnrpc.PolicyUpdateRequest) (*lnrpc.PolicyUpdateResponse, error) {
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "udpatefees",
if err := macaroons.ValidateMacaroon(ctx, "updatechannelpolicy",
r.authSvc); err != nil {
return nil, err
}
@ -3208,11 +3210,11 @@ func (r *rpcServer) UpdateFees(ctx context.Context,
switch scope := req.Scope.(type) {
// If the request is targeting all active channels, then we don't need
// target any channels by their channel point.
case *lnrpc.FeeUpdateRequest_Global:
case *lnrpc.PolicyUpdateRequest_Global:
// Otherwise, we're targeting an individual channel by its channel
// point.
case *lnrpc.FeeUpdateRequest_ChanPoint:
case *lnrpc.PolicyUpdateRequest_ChanPoint:
txid, err := chainhash.NewHash(scope.ChanPoint.FundingTxid)
if err != nil {
return nil, err
@ -3226,12 +3228,19 @@ func (r *rpcServer) UpdateFees(ctx context.Context,
}
// As a sanity check, we'll ensure that the passed fee rate is below
// 1e-6, or the lowest allowed fee rate.
// 1e-6, or the lowest allowed fee rate, and that the passed timelock
// is large enough.
if req.FeeRate < minFeeRate {
return nil, fmt.Errorf("fee rate of %v is too small, min fee "+
"rate is %v", req.FeeRate, minFeeRate)
}
if req.TimeLockDelta < minTimeLockDelta {
return nil, fmt.Errorf("time lock delta of %v is too small, "+
"minimum supported is %v", req.TimeLockDelta,
minTimeLockDelta)
}
// We'll also need to convert the floating point fee rate we accept
// over RPC to the fixed point rate that we use within the protocol. We
// do this by multiplying the passed fee rate by the fee base. This
@ -3244,16 +3253,21 @@ func (r *rpcServer) UpdateFees(ctx context.Context,
FeeRate: feeRateFixed,
}
rpcsLog.Tracef("[updatefees] updating fee schedule base_fee=%v, "+
"rate_float=%v, rate_fixed=%v, targets=%v",
req.BaseFeeMsat, req.FeeRate, feeRateFixed,
chanPolicy := routing.ChannelPolicy{
FeeSchema: feeSchema,
TimeLockDelta: req.TimeLockDelta,
}
rpcsLog.Tracef("[updatechanpolicy] updating channel policy base_fee=%v, "+
"rate_float=%v, rate_fixed=%v, time_lock_delta: %v, targets=%v",
req.BaseFeeMsat, req.FeeRate, feeRateFixed, req.TimeLockDelta,
spew.Sdump(targetChans))
// With the scope resolved, we'll now send this to the
// AuthenticatedGossiper so it can propagate the new fee schema for out
// AuthenticatedGossiper so it can propagate the new policy for our
// target channel(s).
err := r.server.authGossiper.PropagateFeeUpdate(
feeSchema, targetChans...,
err := r.server.authGossiper.PropagateChanPolicyUpdate(
chanPolicy, targetChans...,
)
if err != nil {
return nil, err
@ -3265,8 +3279,9 @@ func (r *rpcServer) UpdateFees(ctx context.Context,
// We create a partially policy as the logic won't overwrite a valid
// sub-policy with a "nil" one.
p := htlcswitch.ForwardingPolicy{
BaseFee: baseFeeMsat,
FeeRate: lnwire.MilliSatoshi(feeRateFixed),
BaseFee: baseFeeMsat,
FeeRate: lnwire.MilliSatoshi(feeRateFixed),
TimeLockDelta: req.TimeLockDelta,
}
err = r.server.htlcSwitch.UpdateForwardingPolicies(p, targetChans...)
if err != nil {
@ -3276,5 +3291,5 @@ func (r *rpcServer) UpdateFees(ctx context.Context,
rpcsLog.Warnf("Unable to update link fees: %v", err)
}
return &lnrpc.FeeUpdateResponse{}, nil
return &lnrpc.PolicyUpdateResponse{}, nil
}

@ -1495,6 +1495,8 @@ type openChanReq struct {
private bool
minHtlc lnwire.MilliSatoshi
// TODO(roasbeef): add ability to specify channel constraints as well
updates chan *lnrpc.OpenStatusUpdate
@ -1612,6 +1614,7 @@ func (s *server) DisconnectPeer(pubKey *btcec.PublicKey) error {
// NOTE: This function is safe for concurrent access.
func (s *server) OpenChannel(peerID int32, nodeKey *btcec.PublicKey,
localAmt btcutil.Amount, pushAmt lnwire.MilliSatoshi,
minHtlc lnwire.MilliSatoshi,
fundingFeePerByte btcutil.Amount,
private bool) (chan *lnrpc.OpenStatusUpdate, chan error) {
@ -1674,6 +1677,7 @@ func (s *server) OpenChannel(peerID int32, nodeKey *btcec.PublicKey,
fundingFeePerWeight: fundingFeePerWeight,
pushAmt: pushAmt,
private: private,
minHtlc: minHtlc,
updates: updateChan,
err: errChan,
}