Merge pull request #1693 from wpaulino/autopilot-zero-conf-inputs

multi: allow use of unconfirmed outputs for funding transactions
This commit is contained in:
Olaoluwa Osuntokun 2018-08-17 17:06:09 -07:00 committed by GitHub
commit 4c51f9b5ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1058 additions and 635 deletions

@ -186,13 +186,18 @@ type balanceUpdate struct {
balanceDelta btcutil.Amount
}
// chanOpenUpdate is a type of external state update the indicates a new
// chanOpenUpdate is a type of external state update that indicates a new
// channel has been opened, either by the Agent itself (within the main
// controller loop), or by an external user to the system.
type chanOpenUpdate struct {
newChan Channel
}
// chanPendingOpenUpdate is a type of external state update that indicates a new
// channel has been opened, either by the agent itself or an external subsystem,
// but is still pending.
type chanPendingOpenUpdate struct{}
// chanOpenFailureUpdate is a type of external state update that indicates
// a previous channel open failed, and that it might be possible to try again.
type chanOpenFailureUpdate struct{}
@ -206,9 +211,13 @@ type chanCloseUpdate struct {
// OnBalanceChange is a callback that should be executed each time the balance of
// the backing wallet changes.
func (a *Agent) OnBalanceChange(delta btcutil.Amount) {
a.wg.Add(1)
go func() {
a.stateUpdates <- &balanceUpdate{
balanceDelta: delta,
defer a.wg.Done()
select {
case a.stateUpdates <- &balanceUpdate{balanceDelta: delta}:
case <-a.quit:
}
}()
}
@ -216,9 +225,25 @@ func (a *Agent) OnBalanceChange(delta btcutil.Amount) {
// OnChannelOpen is a callback that should be executed each time a new channel
// is manually opened by the user or any system outside the autopilot agent.
func (a *Agent) OnChannelOpen(c Channel) {
a.wg.Add(1)
go func() {
a.stateUpdates <- &chanOpenUpdate{
newChan: c,
defer a.wg.Done()
select {
case a.stateUpdates <- &chanOpenUpdate{newChan: c}:
case <-a.quit:
}
}()
}
// OnChannelPendingOpen is a callback that should be executed each time a new
// channel is opened, either by the agent or an external subsystems, but is
// still pending.
func (a *Agent) OnChannelPendingOpen() {
go func() {
select {
case a.stateUpdates <- &chanPendingOpenUpdate{}:
case <-a.quit:
}
}()
}
@ -227,8 +252,14 @@ func (a *Agent) OnChannelOpen(c Channel) {
// autopilot has attempted to open a channel, but failed. In this case we can
// retry channel creation with a different node.
func (a *Agent) OnChannelOpenFailure() {
a.wg.Add(1)
go func() {
a.stateUpdates <- &chanOpenFailureUpdate{}
defer a.wg.Done()
select {
case a.stateUpdates <- &chanOpenFailureUpdate{}:
case <-a.quit:
}
}()
}
@ -236,9 +267,13 @@ func (a *Agent) OnChannelOpenFailure() {
// channel has been closed for any reason. This includes regular
// closes, force closes, and channel breaches.
func (a *Agent) OnChannelClose(closedChans ...lnwire.ShortChannelID) {
a.wg.Add(1)
go func() {
a.stateUpdates <- &chanCloseUpdate{
closedChans: closedChans,
defer a.wg.Done()
select {
case a.stateUpdates <- &chanCloseUpdate{closedChans: closedChans}:
case <-a.quit:
}
}()
}
@ -364,6 +399,12 @@ func (a *Agent) controller(startingBalance btcutil.Amount) {
updateBalance()
// A new channel has been opened by the agent or an
// external subsystem, but is still pending
// confirmation.
case *chanPendingOpenUpdate:
updateBalance()
// A channel has been closed, this may free up an
// available slot, triggering a new channel update.
case *chanCloseUpdate:
@ -580,6 +621,12 @@ func (a *Agent) controller(startingBalance btcutil.Amount) {
err)
}
}
// Since the channel open was successful
// and is currently pending, we'll
// trigger the autopilot agent to query
// for more peers.
a.OnChannelPendingOpen()
}(chanCandidate)
}
pendingMtx.Unlock()

@ -2,13 +2,12 @@ package autopilot
import (
"bytes"
"errors"
"net"
"sync"
"testing"
"time"
"errors"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
@ -31,21 +30,32 @@ type mockHeuristic struct {
directiveResps chan []AttachmentDirective
directiveArgs chan directiveArg
quit chan struct{}
}
func (m *mockHeuristic) NeedMoreChans(chans []Channel,
balance btcutil.Amount) (btcutil.Amount, uint32, bool) {
if m.moreChanArgs != nil {
m.moreChanArgs <- moreChanArg{
moreChan := moreChanArg{
chans: chans,
balance: balance,
}
select {
case m.moreChanArgs <- moreChan:
case <-m.quit:
return 0, 0, false
}
}
resp := <-m.moreChansResps
return resp.amt, resp.numMore, resp.needMore
select {
case resp := <-m.moreChansResps:
return resp.amt, resp.numMore, resp.needMore
case <-m.quit:
return 0, 0, false
}
}
type directiveArg struct {
@ -60,16 +70,26 @@ func (m *mockHeuristic) Select(self *btcec.PublicKey, graph ChannelGraph,
skipChans map[NodeID]struct{}) ([]AttachmentDirective, error) {
if m.directiveArgs != nil {
m.directiveArgs <- directiveArg{
directive := directiveArg{
self: self,
graph: graph,
amt: amtToUse,
skip: skipChans,
}
select {
case m.directiveArgs <- directive:
case <-m.quit:
return nil, errors.New("exiting")
}
}
resp := <-m.directiveResps
return resp, nil
select {
case resp := <-m.directiveResps:
return resp, nil
case <-m.quit:
return nil, errors.New("exiting")
}
}
var _ AttachmentHeuristic = (*mockHeuristic)(nil)
@ -155,6 +175,10 @@ func TestAgentChannelOpenSignal(t *testing.T) {
t.Fatalf("unable to create agent: %v", err)
}
// To ensure the heuristic doesn't block on quitting the agent, we'll
// use the agent's quit chan to signal when it should also stop.
heuristic.quit = agent.quit
// With the autopilot agent and all its dependencies we'll star the
// primary controller goroutine.
if err := agent.Start(); err != nil {
@ -296,6 +320,10 @@ func TestAgentChannelFailureSignal(t *testing.T) {
t.Fatalf("unable to create agent: %v", err)
}
// To ensure the heuristic doesn't block on quitting the agent, we'll
// use the agent's quit chan to signal when it should also stop.
heuristic.quit = agent.quit
// With the autopilot agent and all its dependencies we'll start the
// primary controller goroutine.
if err := agent.Start(); err != nil {
@ -402,6 +430,10 @@ func TestAgentChannelCloseSignal(t *testing.T) {
t.Fatalf("unable to create agent: %v", err)
}
// To ensure the heuristic doesn't block on quitting the agent, we'll
// use the agent's quit chan to signal when it should also stop.
heuristic.quit = agent.quit
// With the autopilot agent and all its dependencies we'll star the
// primary controller goroutine.
if err := agent.Start(); err != nil {
@ -521,6 +553,10 @@ func TestAgentBalanceUpdate(t *testing.T) {
t.Fatalf("unable to create agent: %v", err)
}
// To ensure the heuristic doesn't block on quitting the agent, we'll
// use the agent's quit chan to signal when it should also stop.
heuristic.quit = agent.quit
// With the autopilot agent and all its dependencies we'll star the
// primary controller goroutine.
if err := agent.Start(); err != nil {
@ -643,6 +679,10 @@ func TestAgentImmediateAttach(t *testing.T) {
t.Fatalf("unable to create agent: %v", err)
}
// To ensure the heuristic doesn't block on quitting the agent, we'll
// use the agent's quit chan to signal when it should also stop.
heuristic.quit = agent.quit
// With the autopilot agent and all its dependencies we'll star the
// primary controller goroutine.
if err := agent.Start(); err != nil {
@ -781,6 +821,10 @@ func TestAgentPrivateChannels(t *testing.T) {
t.Fatalf("unable to create agent: %v", err)
}
// To ensure the heuristic doesn't block on quitting the agent, we'll
// use the agent's quit chan to signal when it should also stop.
heuristic.quit = agent.quit
// With the autopilot agent and all its dependencies we'll star the
// primary controller goroutine.
if err := agent.Start(); err != nil {
@ -914,6 +958,10 @@ func TestAgentPendingChannelState(t *testing.T) {
t.Fatalf("unable to create agent: %v", err)
}
// To ensure the heuristic doesn't block on quitting the agent, we'll
// use the agent's quit chan to signal when it should also stop.
heuristic.quit = agent.quit
// With the autopilot agent and all its dependencies we'll start the
// primary controller goroutine.
if err := agent.Start(); err != nil {
@ -966,7 +1014,6 @@ func TestAgentPendingChannelState(t *testing.T) {
}
select {
case heuristic.directiveResps <- []AttachmentDirective{nodeDirective}:
return
case <-time.After(time.Second * 10):
t.Fatalf("heuristic wasn't queried in time")
}
@ -994,8 +1041,6 @@ func TestAgentPendingChannelState(t *testing.T) {
// heuristic.
agent.OnBalanceChange(0.4 * btcutil.SatoshiPerBitcoin)
wg = sync.WaitGroup{}
// The heuristic should be queried, and the argument for the set of
// channels passed in should include the pending channels that
// should've been created above.
@ -1044,3 +1089,97 @@ func TestAgentPendingChannelState(t *testing.T) {
t.Fatalf("select wasn't queried in time")
}
}
// TestAgentPendingOpenChannel ensures that the agent queries its heuristic once
// it detects a channel is pending open. This allows the agent to use its own
// change outputs that have yet to confirm for funding transactions.
func TestAgentPendingOpenChannel(t *testing.T) {
t.Parallel()
// First, we'll create all the dependencies that we'll need in order to
// create the autopilot agent.
self, err := randKey()
if err != nil {
t.Fatalf("unable to generate key: %v", err)
}
heuristic := &mockHeuristic{
moreChansResps: make(chan moreChansResp),
directiveResps: make(chan []AttachmentDirective),
}
chanController := &mockChanController{
openChanSignals: make(chan openChanIntent),
}
memGraph, _, _ := newMemChanGraph()
// The wallet will start with 6 BTC available.
const walletBalance = btcutil.SatoshiPerBitcoin * 6
// With the dependencies we created, we can now create the initial
// agent itself.
cfg := Config{
Self: self,
Heuristic: heuristic,
ChanController: chanController,
WalletBalance: func() (btcutil.Amount, error) {
return walletBalance, nil
},
Graph: memGraph,
MaxPendingOpens: 10,
}
agent, err := New(cfg, nil)
if err != nil {
t.Fatalf("unable to create agent: %v", err)
}
// To ensure the heuristic doesn't block on quitting the agent, we'll
// use the agent's quit chan to signal when it should also stop.
heuristic.quit = agent.quit
// With the autopilot agent and all its dependencies we'll start the
// primary controller goroutine.
if err := agent.Start(); err != nil {
t.Fatalf("unable to start agent: %v", err)
}
defer agent.Stop()
// We'll send an initial "no" response to advance the agent past its
// initial check.
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
select {
case heuristic.moreChansResps <- moreChansResp{false, 0, 0}:
case <-time.After(time.Second * 10):
t.Fatalf("heuristic wasn't queried in time")
}
}()
// Next, we'll signal that a new channel has been opened, but it is
// still pending.
agent.OnChannelPendingOpen()
// The agent should now query the heuristic in order to determine its
// next action as its local state has now been modified.
wg.Add(1)
go func() {
defer wg.Done()
select {
case heuristic.moreChansResps <- moreChansResp{false, 0, 0}:
case <-time.After(time.Second * 10):
t.Fatalf("heuristic wasn't queried in time")
}
}()
// We'll wait here for either the agent to query the heuristic to be
// queried, or for the timeout above to tick.
wg.Wait()
// There shouldn't be a call to the Select method as we've returned
// "false" for NeedMoreChans above.
select {
case heuristic.directiveResps <- []AttachmentDirective{}:
t.Fatalf("Select was called but shouldn't have been")
default:
}
}

@ -469,6 +469,12 @@ var openChannelCommand = cli.Command{
"not set, we will scale the value according to the " +
"channel size",
},
cli.Uint64Flag{
Name: "min_confs",
Usage: "(optional) the minimum number of confirmations " +
"each one of your outputs used for the funding " +
"transaction must satisfy",
},
},
Action: actionDecorator(openChannel),
}
@ -493,6 +499,7 @@ func openChannel(ctx *cli.Context) error {
SatPerByte: ctx.Int64("sat_per_byte"),
MinHtlcMsat: ctx.Int64("min_htlc_msat"),
RemoteCsvDelay: uint32(ctx.Uint64("remote_csv_delay")),
MinConfs: int32(ctx.Uint64("min_confs")),
}
switch {

@ -146,6 +146,7 @@ type autoPilotConfig struct {
MinChannelSize int64 `long:"minchansize" description:"The smallest channel that the autopilot agent should create"`
MaxChannelSize int64 `long:"maxchansize" description:"The largest channel that the autopilot agent should create"`
Private bool `long:"private" description:"Whether the channels created by the autopilot agent should be private or not. Private channels won't be announced to the network."`
MinConfs int32 `long:"minconfs" description:"The minimum number of confirmations each of your inputs in funding transactions created by the autopilot agent must have."`
}
type torConfig struct {
@ -424,6 +425,12 @@ func loadConfig() (*config, error) {
fmt.Fprintln(os.Stderr, err)
return nil, err
}
if cfg.Autopilot.MinConfs < 0 {
str := "%s: autopilot.minconfs must be non-negative"
err := fmt.Errorf(str, funcName)
fmt.Fprintln(os.Stderr, err)
return nil, err
}
// Ensure that the specified values for the min and max channel size
// don't are within the bounds of the normal chan size constraints.

@ -1042,12 +1042,20 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
// responding side of a single funder workflow, we don't commit any
// funds to the channel ourselves.
chainHash := chainhash.Hash(msg.ChainHash)
reservation, err := f.cfg.Wallet.InitChannelReservation(
amt, 0, msg.PushAmount,
lnwallet.SatPerKWeight(msg.FeePerKiloWeight), 0,
fmsg.peer.IdentityKey(), fmsg.peer.Address(), &chainHash,
msg.ChannelFlags,
)
req := &lnwallet.InitFundingReserveMsg{
ChainHash: &chainHash,
NodeID: fmsg.peer.IdentityKey(),
NodeAddr: fmsg.peer.Address(),
FundingAmount: 0,
Capacity: amt,
CommitFeePerKw: lnwallet.SatPerKWeight(msg.FeePerKiloWeight),
FundingFeePerKw: 0,
PushMSat: msg.PushAmount,
Flags: msg.ChannelFlags,
MinConfs: 1,
}
reservation, err := f.cfg.Wallet.InitChannelReservation(req)
if err != nil {
fndgLog.Errorf("Unable to initialize reservation: %v", err)
f.failFundingFlow(fmsg.peer, msg.PendingChannelID, err)
@ -2598,11 +2606,20 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
// Initialize a funding reservation with the local wallet. If the
// wallet doesn't have enough funds to commit to this channel, then the
// request will fail, and be aborted.
reservation, err := f.cfg.Wallet.InitChannelReservation(
capacity, localAmt, msg.pushAmt, commitFeePerKw,
msg.fundingFeePerKw, peerKey, msg.peer.Address(),
&msg.chainHash, channelFlags,
)
req := &lnwallet.InitFundingReserveMsg{
ChainHash: &msg.chainHash,
NodeID: peerKey,
NodeAddr: msg.peer.Address(),
FundingAmount: localAmt,
Capacity: capacity,
CommitFeePerKw: commitFeePerKw,
FundingFeePerKw: msg.fundingFeePerKw,
PushMSat: msg.pushAmt,
Flags: channelFlags,
MinConfs: msg.minConfs,
}
reservation, err := f.cfg.Wallet.InitChannelReservation(req)
if err != nil {
msg.err <- err
return

@ -153,7 +153,7 @@ func openChannelAndAssert(ctx context.Context, t *harnessTest,
private bool) *lnrpc.ChannelPoint {
chanOpenUpdate, err := net.OpenChannel(
ctx, alice, bob, fundingAmt, pushAmt, private,
ctx, alice, bob, fundingAmt, pushAmt, private, true,
)
if err != nil {
t.Fatalf("unable to open channel: %v", err)
@ -677,6 +677,82 @@ func testBasicChannelFunding(net *lntest.NetworkHarness, t *harnessTest) {
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPoint, false)
}
// testUnconfirmedChannelFunding tests that unconfirmed outputs that pay to us
// can be used to fund channels.
func testUnconfirmedChannelFunding(net *lntest.NetworkHarness, t *harnessTest) {
const (
timeout = time.Duration(15 * time.Second)
chanAmt = maxBtcFundingAmount
pushAmt = btcutil.Amount(100000)
)
ctxb := context.Background()
// We'll start off by creating a node for Carol.
carol, err := net.NewNode("Carol", nil)
if err != nil {
t.Fatalf("unable to create carol's node: %v", err)
}
defer shutdownAndAssert(net, t, carol)
// We'll send her some funds that should not confirm.
ctxt, _ := context.WithTimeout(ctxb, timeout)
err = net.SendCoinsUnconfirmed(ctxt, 2*chanAmt, carol)
if err != nil {
t.Fatalf("unable to send coins to carol: %v", err)
}
// Now, we'll connect her to Alice so that they can open a channel
// together. The funding flow should select Carol's unconfirmed output
// as she doesn't have any other funds since it's a new node.
ctxt, _ = context.WithTimeout(ctxb, timeout)
if err := net.ConnectNodes(ctxt, carol, net.Alice); err != nil {
t.Fatalf("unable to connect dave to alice: %v", err)
}
ctxt, _ = context.WithTimeout(ctxb, timeout)
chanOpenUpdate, err := net.OpenChannel(
ctxt, carol, net.Alice, chanAmt, pushAmt, false, false,
)
if err != nil {
t.Fatalf("unable to open channel between carol and alice: %v",
err)
}
// Confirm the channel and wait for it to be recognized by both parties.
mineBlocks(t, net, 6)
ctxt, _ = context.WithTimeout(ctxb, timeout)
chanPoint, err := net.WaitForChannelOpen(ctxt, chanOpenUpdate)
if err != nil {
t.Fatalf("error while waiting for channel open: %v", err)
}
// With the channel open, we'll check the balances on each side of the
// channel as a sanity check to ensure things worked out as intended.
balReq := &lnrpc.ChannelBalanceRequest{}
ctxt, _ = context.WithTimeout(ctxb, timeout)
carolBal, err := carol.ChannelBalance(ctxt, balReq)
if err != nil {
t.Fatalf("unable to get carol's balance: %v", err)
}
ctxt, _ = context.WithTimeout(ctxb, timeout)
aliceBal, err := net.Alice.ChannelBalance(ctxt, balReq)
if err != nil {
t.Fatalf("unable to get alice's balance: %v", err)
}
if carolBal.Balance != int64(chanAmt-pushAmt-calcStaticFee(0)) {
t.Fatalf("carol's balance is incorrect: expected %v got %v",
chanAmt-pushAmt-calcStaticFee(0), carolBal)
}
if aliceBal.Balance != int64(pushAmt) {
t.Fatalf("alice's balance is incorrect: expected %v got %v",
pushAmt, aliceBal.Balance)
}
// Now that we're done with the test, the channel can be closed.
ctxt, _ = context.WithTimeout(ctxb, timeout)
closeChannelAndAssert(ctxt, t, net, carol, chanPoint, false)
}
// txStr returns the string representation of the channel's funding transaction.
func txStr(chanPoint *lnrpc.ChannelPoint) string {
txidHash, err := getChanPointFundingTxid(chanPoint)
@ -3699,8 +3775,9 @@ func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) {
if err := net.ConnectNodes(ctxb, carol, net.Alice); err != nil {
t.Fatalf("unable to connect dave to alice: %v", err)
}
chanOpenUpdate, err := net.OpenChannel(ctxb, carol, net.Alice, chanAmt,
0, true)
chanOpenUpdate, err := net.OpenChannel(
ctxb, carol, net.Alice, chanAmt, 0, true, true,
)
if err != nil {
t.Fatalf("unable to open channel: %v", err)
}
@ -4581,8 +4658,9 @@ func testMaxPendingChannels(net *lntest.NetworkHarness, t *harnessTest) {
openStreams := make([]lnrpc.Lightning_OpenChannelClient, maxPendingChannels)
for i := 0; i < maxPendingChannels; i++ {
ctx, _ = context.WithTimeout(context.Background(), timeout)
stream, err := net.OpenChannel(ctx, net.Alice, carol, amount,
0, false)
stream, err := net.OpenChannel(
ctx, net.Alice, carol, amount, 0, false, true,
)
if err != nil {
t.Fatalf("unable to open channel: %v", err)
}
@ -4592,7 +4670,9 @@ func testMaxPendingChannels(net *lntest.NetworkHarness, t *harnessTest) {
// Carol exhausted available amount of pending channels, next open
// channel request should cause ErrorGeneric to be sent back to Alice.
ctx, _ = context.WithTimeout(context.Background(), timeout)
_, err = net.OpenChannel(ctx, net.Alice, carol, amount, 0, false)
_, err = net.OpenChannel(
ctx, net.Alice, carol, amount, 0, false, true,
)
if err == nil {
t.Fatalf("error wasn't received")
} else if grpc.Code(err) != lnwire.ErrMaxPendingChannels.ToGrpcCode() {
@ -11060,6 +11140,10 @@ var testsCases = []*testCase{
name: "basic funding flow",
test: testBasicChannelFunding,
},
{
name: "unconfirmed channel funding",
test: testUnconfirmedChannelFunding,
},
{
name: "update channel policy",
test: testUpdateChannelPolicy,

@ -2214,6 +2214,8 @@ type OpenChannelRequest struct {
MinHtlcMsat int64 `protobuf:"varint,9,opt,name=min_htlc_msat" json:"min_htlc_msat,omitempty"`
// / The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size.
RemoteCsvDelay uint32 `protobuf:"varint,10,opt,name=remote_csv_delay" json:"remote_csv_delay,omitempty"`
// / The minimum number of confirmations each one of your outputs used for the funding transaction must satisfy.
MinConfs int32 `protobuf:"varint,11,opt,name=min_confs" json:"min_confs,omitempty"`
}
func (m *OpenChannelRequest) Reset() { *m = OpenChannelRequest{} }
@ -2284,6 +2286,13 @@ func (m *OpenChannelRequest) GetRemoteCsvDelay() uint32 {
return 0
}
func (m *OpenChannelRequest) GetMinConfs() int32 {
if m != nil {
return m.MinConfs
}
return 0
}
type OpenStatusUpdate struct {
// Types that are valid to be assigned to Update:
// *OpenStatusUpdate_ChanPending
@ -7093,395 +7102,395 @@ var _Lightning_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("rpc.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 6227 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5c, 0xcd, 0x6f, 0x1c, 0xc9,
0x75, 0x57, 0x0f, 0x87, 0x1f, 0xf3, 0x66, 0x48, 0x0e, 0x8b, 0x14, 0x35, 0x9a, 0xdd, 0xd5, 0x6a,
0xdb, 0xc2, 0x4a, 0x66, 0x36, 0x92, 0x96, 0xb6, 0x37, 0xeb, 0xdd, 0xc4, 0x8e, 0x44, 0x52, 0xa2,
0x6c, 0xae, 0x44, 0x37, 0x25, 0x2b, 0xb1, 0x13, 0x8c, 0x9b, 0x33, 0xc5, 0x61, 0x5b, 0x33, 0xdd,
0xed, 0xee, 0x1e, 0x52, 0xe3, 0x8d, 0x00, 0xe7, 0x03, 0x39, 0xc5, 0x08, 0x82, 0xe4, 0xe2, 0x00,
0x41, 0x00, 0x07, 0x08, 0x9c, 0x3f, 0x20, 0xb9, 0x38, 0x01, 0x72, 0xc8, 0xc5, 0x01, 0x82, 0x1c,
0x7c, 0x32, 0x72, 0x4c, 0x72, 0x48, 0x82, 0x5c, 0x02, 0xe4, 0x1a, 0x04, 0xef, 0xd5, 0x47, 0x57,
0x75, 0x37, 0x45, 0xf9, 0x23, 0xb9, 0x4d, 0xfd, 0xea, 0x75, 0x7d, 0xbe, 0xaf, 0x7a, 0xf5, 0x6a,
0xa0, 0x91, 0xc4, 0xfd, 0x9b, 0x71, 0x12, 0x65, 0x11, 0x9b, 0x1d, 0x85, 0x49, 0xdc, 0xef, 0xbe,
0x3e, 0x8c, 0xa2, 0xe1, 0x88, 0xdf, 0xf2, 0xe3, 0xe0, 0x96, 0x1f, 0x86, 0x51, 0xe6, 0x67, 0x41,
0x14, 0xa6, 0x82, 0xc8, 0xfd, 0x1a, 0x2c, 0xdd, 0xe7, 0xe1, 0x01, 0xe7, 0x03, 0x8f, 0x7f, 0x63,
0xc2, 0xd3, 0x8c, 0xfd, 0x1c, 0xac, 0xf8, 0xfc, 0x9b, 0x9c, 0x0f, 0x7a, 0xb1, 0x9f, 0xa6, 0xf1,
0x71, 0xe2, 0xa7, 0xbc, 0xe3, 0x5c, 0x75, 0x6e, 0xb4, 0xbc, 0xb6, 0xa8, 0xd8, 0xd7, 0x38, 0x7b,
0x0b, 0x5a, 0x29, 0x92, 0xf2, 0x30, 0x4b, 0xa2, 0x78, 0xda, 0xa9, 0x11, 0x5d, 0x13, 0xb1, 0x1d,
0x01, 0xb9, 0x23, 0x58, 0xd6, 0x3d, 0xa4, 0x71, 0x14, 0xa6, 0x9c, 0xdd, 0x86, 0xb5, 0x7e, 0x10,
0x1f, 0xf3, 0xa4, 0x47, 0x1f, 0x8f, 0x43, 0x3e, 0x8e, 0xc2, 0xa0, 0xdf, 0x71, 0xae, 0xce, 0xdc,
0x68, 0x78, 0x4c, 0xd4, 0xe1, 0x17, 0x1f, 0xc9, 0x1a, 0x76, 0x1d, 0x96, 0x79, 0x28, 0x70, 0x3e,
0xa0, 0xaf, 0x64, 0x57, 0x4b, 0x39, 0x8c, 0x1f, 0xb8, 0x7f, 0xe7, 0xc0, 0xca, 0x83, 0x30, 0xc8,
0x9e, 0xfa, 0xa3, 0x11, 0xcf, 0xd4, 0x9c, 0xae, 0xc3, 0xf2, 0x29, 0x01, 0x34, 0xa7, 0xd3, 0x28,
0x19, 0xc8, 0x19, 0x2d, 0x09, 0x78, 0x5f, 0xa2, 0x67, 0x8e, 0xac, 0x76, 0xe6, 0xc8, 0x2a, 0x97,
0x6b, 0xe6, 0x8c, 0xe5, 0xba, 0x0e, 0xcb, 0x09, 0xef, 0x47, 0x27, 0x3c, 0x99, 0xf6, 0x4e, 0x83,
0x70, 0x10, 0x9d, 0x76, 0xea, 0x57, 0x9d, 0x1b, 0xb3, 0xde, 0x92, 0x82, 0x9f, 0x12, 0xea, 0xae,
0x01, 0x33, 0x67, 0x21, 0xd6, 0xcd, 0x1d, 0xc2, 0xea, 0x93, 0x70, 0x14, 0xf5, 0x9f, 0xfd, 0x84,
0xb3, 0xab, 0xe8, 0xbe, 0x56, 0xd9, 0xfd, 0x3a, 0xac, 0xd9, 0x1d, 0xc9, 0x01, 0x70, 0xb8, 0xb8,
0x75, 0xec, 0x87, 0x43, 0xae, 0x9a, 0x54, 0x43, 0xf8, 0x24, 0xb4, 0xfb, 0x93, 0x24, 0xe1, 0x61,
0x69, 0x0c, 0xcb, 0x12, 0xd7, 0x83, 0x78, 0x0b, 0x5a, 0x21, 0x3f, 0xcd, 0xc9, 0x24, 0xcb, 0x84,
0xfc, 0x54, 0x91, 0xb8, 0x1d, 0x58, 0x2f, 0x76, 0x23, 0x07, 0xf0, 0x9d, 0x1a, 0x34, 0x1f, 0x27,
0x7e, 0x98, 0xfa, 0x7d, 0xe4, 0x62, 0xd6, 0x81, 0xf9, 0xec, 0x79, 0xef, 0xd8, 0x4f, 0x8f, 0xa9,
0xbb, 0x86, 0xa7, 0x8a, 0x6c, 0x1d, 0xe6, 0xfc, 0x71, 0x34, 0x09, 0x33, 0xea, 0x60, 0xc6, 0x93,
0x25, 0xf6, 0x0e, 0xac, 0x84, 0x93, 0x71, 0xaf, 0x1f, 0x85, 0x47, 0x41, 0x32, 0x16, 0xb2, 0x40,
0xfb, 0x35, 0xeb, 0x95, 0x2b, 0xd8, 0x15, 0x80, 0x43, 0x5c, 0x07, 0xd1, 0x45, 0x9d, 0xba, 0x30,
0x10, 0xe6, 0x42, 0x4b, 0x96, 0x78, 0x30, 0x3c, 0xce, 0x3a, 0xb3, 0xd4, 0x90, 0x85, 0x61, 0x1b,
0x59, 0x30, 0xe6, 0xbd, 0x34, 0xf3, 0xc7, 0x71, 0x67, 0x8e, 0x46, 0x63, 0x20, 0x54, 0x1f, 0x65,
0xfe, 0xa8, 0x77, 0xc4, 0x79, 0xda, 0x99, 0x97, 0xf5, 0x1a, 0x61, 0x6f, 0xc3, 0xd2, 0x80, 0xa7,
0x59, 0xcf, 0x1f, 0x0c, 0x12, 0x9e, 0xa6, 0x3c, 0xed, 0x2c, 0x10, 0x37, 0x16, 0x50, 0x5c, 0xb5,
0xfb, 0x3c, 0x33, 0x56, 0x27, 0x95, 0xbb, 0xe3, 0xee, 0x01, 0x33, 0xe0, 0x6d, 0x9e, 0xf9, 0xc1,
0x28, 0x65, 0xef, 0x41, 0x2b, 0x33, 0x88, 0x49, 0xfa, 0x9a, 0x9b, 0xec, 0x26, 0xa9, 0x8d, 0x9b,
0xc6, 0x07, 0x9e, 0x45, 0xe7, 0xde, 0x87, 0x85, 0x7b, 0x9c, 0xef, 0x05, 0xe3, 0x20, 0x63, 0xeb,
0x30, 0x7b, 0x14, 0x3c, 0xe7, 0x62, 0xb3, 0x67, 0x76, 0x2f, 0x78, 0xa2, 0xc8, 0xba, 0x30, 0x1f,
0xf3, 0xa4, 0xcf, 0xd5, 0xf2, 0xef, 0x5e, 0xf0, 0x14, 0x70, 0x77, 0x1e, 0x66, 0x47, 0xf8, 0xb1,
0xfb, 0xbd, 0x1a, 0x34, 0x0f, 0x78, 0xa8, 0x99, 0x88, 0x41, 0x1d, 0xa7, 0x24, 0x19, 0x87, 0x7e,
0xb3, 0x37, 0xa1, 0x49, 0xd3, 0x4c, 0xb3, 0x24, 0x08, 0x87, 0xd4, 0x58, 0xc3, 0x03, 0x84, 0x0e,
0x08, 0x61, 0x6d, 0x98, 0xf1, 0xc7, 0x19, 0xed, 0xe0, 0x8c, 0x87, 0x3f, 0x91, 0xc1, 0x62, 0x7f,
0x3a, 0x46, 0x5e, 0xd4, 0xbb, 0xd6, 0xf2, 0x9a, 0x12, 0xdb, 0xc5, 0x6d, 0xbb, 0x09, 0xab, 0x26,
0x89, 0x6a, 0x7d, 0x96, 0x5a, 0x5f, 0x31, 0x28, 0x65, 0x27, 0xd7, 0x61, 0x59, 0xd1, 0x27, 0x62,
0xb0, 0xb4, 0x8f, 0x0d, 0x6f, 0x49, 0xc2, 0x6a, 0x0a, 0x37, 0xa0, 0x7d, 0x14, 0x84, 0xfe, 0xa8,
0xd7, 0x1f, 0x65, 0x27, 0xbd, 0x01, 0x1f, 0x65, 0x3e, 0xed, 0xe8, 0xac, 0xb7, 0x44, 0xf8, 0xd6,
0x28, 0x3b, 0xd9, 0x46, 0x94, 0xbd, 0x03, 0x8d, 0x23, 0xce, 0x7b, 0xb4, 0x12, 0x9d, 0x85, 0xab,
0xce, 0x8d, 0xe6, 0xe6, 0xb2, 0x5c, 0x7a, 0xb5, 0xba, 0xde, 0xc2, 0x91, 0xfc, 0xe5, 0xfe, 0x91,
0x03, 0x2d, 0xb1, 0x54, 0x52, 0x85, 0x5e, 0x83, 0x45, 0x35, 0x22, 0x9e, 0x24, 0x51, 0x22, 0xd9,
0xdf, 0x06, 0xd9, 0x06, 0xb4, 0x15, 0x10, 0x27, 0x3c, 0x18, 0xfb, 0x43, 0x2e, 0xe5, 0xad, 0x84,
0xb3, 0xcd, 0xbc, 0xc5, 0x24, 0x9a, 0x64, 0x42, 0x89, 0x35, 0x37, 0x5b, 0x72, 0x50, 0x1e, 0x62,
0x9e, 0x4d, 0xe2, 0x7e, 0xdb, 0x01, 0x86, 0xc3, 0x7a, 0x1c, 0x89, 0x6a, 0xb9, 0x0a, 0xc5, 0x1d,
0x70, 0x5e, 0x79, 0x07, 0x6a, 0x67, 0xed, 0xc0, 0x35, 0x98, 0xa3, 0x2e, 0x51, 0x56, 0x67, 0x4a,
0xc3, 0x92, 0x75, 0xee, 0x77, 0x1d, 0x68, 0xa1, 0xe6, 0x08, 0xf9, 0x68, 0x3f, 0x0a, 0xc2, 0x8c,
0xdd, 0x06, 0x76, 0x34, 0x09, 0x07, 0x41, 0x38, 0xec, 0x65, 0xcf, 0x83, 0x41, 0xef, 0x70, 0x8a,
0x4d, 0xd0, 0x78, 0x76, 0x2f, 0x78, 0x15, 0x75, 0xec, 0x1d, 0x68, 0x5b, 0x68, 0x9a, 0x25, 0x62,
0x54, 0xbb, 0x17, 0xbc, 0x52, 0x0d, 0xca, 0x7f, 0x34, 0xc9, 0xe2, 0x49, 0xd6, 0x0b, 0xc2, 0x01,
0x7f, 0x4e, 0x6b, 0xb6, 0xe8, 0x59, 0xd8, 0xdd, 0x25, 0x68, 0x99, 0xdf, 0xb9, 0x9f, 0x83, 0xf6,
0x1e, 0x2a, 0x86, 0x30, 0x08, 0x87, 0x77, 0x84, 0xf4, 0xa2, 0xb6, 0x8a, 0x27, 0x87, 0xcf, 0xf8,
0x54, 0xee, 0xa3, 0x2c, 0xa1, 0x48, 0x1c, 0x47, 0x69, 0x26, 0xd7, 0x85, 0x7e, 0xbb, 0xff, 0xec,
0xc0, 0x32, 0x2e, 0xfa, 0x47, 0x7e, 0x38, 0x55, 0x2b, 0xbe, 0x07, 0x2d, 0x6c, 0xea, 0x71, 0x74,
0x47, 0xe8, 0x3c, 0x21, 0xcb, 0x37, 0xe4, 0x22, 0x15, 0xa8, 0x6f, 0x9a, 0xa4, 0x68, 0xa6, 0xa7,
0x9e, 0xf5, 0x35, 0x0a, 0x5d, 0xe6, 0x27, 0x43, 0x9e, 0x91, 0x36, 0x94, 0xda, 0x11, 0x04, 0xb4,
0x15, 0x85, 0x47, 0xec, 0x2a, 0xb4, 0x52, 0x3f, 0xeb, 0xc5, 0x3c, 0xa1, 0x55, 0x23, 0xc1, 0x99,
0xf1, 0x20, 0xf5, 0xb3, 0x7d, 0x9e, 0xdc, 0x9d, 0x66, 0xbc, 0xfb, 0x79, 0x58, 0x29, 0xf5, 0x82,
0xb2, 0x9a, 0x4f, 0x11, 0x7f, 0xb2, 0x35, 0x98, 0x3d, 0xf1, 0x47, 0x13, 0x2e, 0x95, 0xb4, 0x28,
0x7c, 0x50, 0x7b, 0xdf, 0x71, 0xdf, 0x86, 0x76, 0x3e, 0x6c, 0xc9, 0xf4, 0x0c, 0xea, 0xb8, 0x82,
0xb2, 0x01, 0xfa, 0xed, 0xfe, 0xa6, 0x23, 0x08, 0xb7, 0xa2, 0x40, 0x2b, 0x3c, 0x24, 0x44, 0xbd,
0xa8, 0x08, 0xf1, 0xf7, 0x99, 0x06, 0xe1, 0xa7, 0x9f, 0xac, 0x7b, 0x1d, 0x56, 0x8c, 0x21, 0xbc,
0x64, 0xb0, 0xdf, 0x76, 0x60, 0xe5, 0x21, 0x3f, 0x95, 0xbb, 0xae, 0x46, 0xfb, 0x3e, 0xd4, 0xb3,
0x69, 0x2c, 0x9c, 0xac, 0xa5, 0xcd, 0x6b, 0x72, 0xd3, 0x4a, 0x74, 0x37, 0x65, 0xf1, 0xf1, 0x34,
0xe6, 0x1e, 0x7d, 0xe1, 0x7e, 0x0e, 0x9a, 0x06, 0xc8, 0x2e, 0xc1, 0xea, 0xd3, 0x07, 0x8f, 0x1f,
0xee, 0x1c, 0x1c, 0xf4, 0xf6, 0x9f, 0xdc, 0xfd, 0xe2, 0xce, 0xaf, 0xf6, 0x76, 0xef, 0x1c, 0xec,
0xb6, 0x2f, 0xb0, 0x75, 0x60, 0x0f, 0x77, 0x0e, 0x1e, 0xef, 0x6c, 0x5b, 0xb8, 0xe3, 0x76, 0xa1,
0xf3, 0x90, 0x9f, 0x3e, 0x0d, 0xb2, 0x90, 0xa7, 0xa9, 0xdd, 0x9b, 0x7b, 0x13, 0x98, 0x39, 0x04,
0x39, 0xab, 0x0e, 0xcc, 0x4b, 0x8b, 0xa3, 0x0c, 0xae, 0x2c, 0xba, 0x6f, 0x03, 0x3b, 0x08, 0x86,
0xe1, 0x47, 0x3c, 0x4d, 0xfd, 0xa1, 0x56, 0x05, 0x6d, 0x98, 0x19, 0xa7, 0x43, 0xa9, 0x01, 0xf0,
0xa7, 0xfb, 0x29, 0x58, 0xb5, 0xe8, 0x64, 0xc3, 0xaf, 0x43, 0x23, 0x0d, 0x86, 0xa1, 0x9f, 0x4d,
0x12, 0x2e, 0x9b, 0xce, 0x01, 0xf7, 0x1e, 0xac, 0x7d, 0x99, 0x27, 0xc1, 0xd1, 0xf4, 0xbc, 0xe6,
0xed, 0x76, 0x6a, 0xc5, 0x76, 0x76, 0xe0, 0x62, 0xa1, 0x1d, 0xd9, 0xbd, 0x60, 0x44, 0xb9, 0x5d,
0x0b, 0x9e, 0x28, 0x18, 0x62, 0x59, 0x33, 0xc5, 0xd2, 0x7d, 0x02, 0x6c, 0x2b, 0x0a, 0x43, 0xde,
0xcf, 0xf6, 0x39, 0x4f, 0x72, 0xcf, 0x39, 0xe7, 0xba, 0xe6, 0xe6, 0x25, 0xb9, 0x8f, 0x45, 0x59,
0x97, 0xec, 0xc8, 0xa0, 0x1e, 0xf3, 0x64, 0x4c, 0x0d, 0x2f, 0x78, 0xf4, 0xdb, 0xbd, 0x08, 0xab,
0x56, 0xb3, 0xd2, 0xe9, 0x79, 0x17, 0x2e, 0x6e, 0x07, 0x69, 0xbf, 0xdc, 0x61, 0x07, 0xe6, 0xe3,
0xc9, 0x61, 0x2f, 0x97, 0x29, 0x55, 0x44, 0x5f, 0xa0, 0xf8, 0x89, 0x6c, 0xec, 0x77, 0x1d, 0xa8,
0xef, 0x3e, 0xde, 0xdb, 0x62, 0x5d, 0x58, 0x08, 0xc2, 0x7e, 0x34, 0x46, 0xb5, 0x2b, 0x26, 0xad,
0xcb, 0x67, 0xca, 0xca, 0xeb, 0xd0, 0x20, 0x6d, 0x8d, 0xee, 0x8d, 0x74, 0x72, 0x73, 0x00, 0x5d,
0x2b, 0xfe, 0x3c, 0x0e, 0x12, 0xf2, 0x9d, 0x94, 0x47, 0x54, 0x27, 0x8d, 0x58, 0xae, 0x70, 0xff,
0xa7, 0x0e, 0xf3, 0x52, 0x57, 0x53, 0x7f, 0xfd, 0x2c, 0x38, 0xe1, 0x72, 0x24, 0xb2, 0x84, 0x56,
0x2e, 0xe1, 0xe3, 0x28, 0xe3, 0x3d, 0x6b, 0x1b, 0x6c, 0x10, 0xa9, 0xfa, 0xa2, 0xa1, 0x5e, 0x8c,
0x5a, 0x9f, 0x46, 0xd6, 0xf0, 0x6c, 0x10, 0x17, 0x0b, 0x81, 0x5e, 0x30, 0xa0, 0x31, 0xd5, 0x3d,
0x55, 0xc4, 0x95, 0xe8, 0xfb, 0xb1, 0xdf, 0x0f, 0xb2, 0xa9, 0x14, 0x6e, 0x5d, 0xc6, 0xb6, 0x47,
0x51, 0xdf, 0x1f, 0xf5, 0x0e, 0xfd, 0x91, 0x1f, 0xf6, 0xb9, 0xf4, 0xdf, 0x6c, 0x10, 0x5d, 0x34,
0x39, 0x24, 0x45, 0x26, 0xdc, 0xb8, 0x02, 0x8a, 0xae, 0x5e, 0x3f, 0x1a, 0x8f, 0x83, 0x0c, 0x3d,
0x3b, 0xb2, 0xfa, 0x33, 0x9e, 0x81, 0xd0, 0x4c, 0x44, 0xe9, 0x54, 0xac, 0x5e, 0x43, 0xf4, 0x66,
0x81, 0xd8, 0x0a, 0xba, 0x0e, 0xa8, 0x90, 0x9e, 0x9d, 0x76, 0x40, 0xb4, 0x92, 0x23, 0xb8, 0x0f,
0x93, 0x30, 0xe5, 0x59, 0x36, 0xe2, 0x03, 0x3d, 0xa0, 0x26, 0x91, 0x95, 0x2b, 0xd8, 0x6d, 0x58,
0x15, 0xce, 0x66, 0xea, 0x67, 0x51, 0x7a, 0x1c, 0xa4, 0xbd, 0x14, 0xdd, 0xb6, 0x16, 0xd1, 0x57,
0x55, 0xb1, 0xf7, 0xe1, 0x52, 0x01, 0x4e, 0x78, 0x9f, 0x07, 0x27, 0x7c, 0xd0, 0x59, 0xa4, 0xaf,
0xce, 0xaa, 0x66, 0x57, 0xa1, 0x89, 0x3e, 0xf6, 0x24, 0x1e, 0xf8, 0x68, 0x87, 0x97, 0x68, 0x1f,
0x4c, 0x88, 0xbd, 0x0b, 0x8b, 0x31, 0x17, 0xc6, 0xf2, 0x38, 0x1b, 0xf5, 0xd3, 0xce, 0x32, 0x59,
0xb2, 0xa6, 0x14, 0x26, 0xe4, 0x5c, 0xcf, 0xa6, 0x40, 0xa6, 0xec, 0xa7, 0xe4, 0x6c, 0xf9, 0xd3,
0x4e, 0x9b, 0xd8, 0x2d, 0x07, 0x48, 0x46, 0x92, 0xe0, 0xc4, 0xcf, 0x78, 0x67, 0x85, 0x78, 0x4b,
0x15, 0xdd, 0x3f, 0x75, 0x60, 0x75, 0x2f, 0x48, 0x33, 0xc9, 0x84, 0x5a, 0x1d, 0xbf, 0x09, 0x4d,
0xc1, 0x7e, 0xbd, 0x28, 0x1c, 0x4d, 0x25, 0x47, 0x82, 0x80, 0x1e, 0x85, 0xa3, 0x29, 0xfb, 0x04,
0x2c, 0x06, 0xa1, 0x49, 0x22, 0x64, 0xb8, 0xa5, 0x40, 0x22, 0x7a, 0x13, 0x9a, 0xf1, 0xe4, 0x70,
0x14, 0xf4, 0x05, 0xc9, 0x8c, 0x68, 0x45, 0x40, 0x44, 0x80, 0x4e, 0x92, 0x18, 0x89, 0xa0, 0xa8,
0x13, 0x45, 0x53, 0x62, 0x48, 0xe2, 0xde, 0x85, 0x35, 0x7b, 0x80, 0x52, 0x59, 0x6d, 0xc0, 0x82,
0xe4, 0xed, 0xb4, 0xd3, 0xa4, 0xf5, 0x59, 0x92, 0xeb, 0x23, 0x49, 0x3d, 0x5d, 0xef, 0xfe, 0x79,
0x1d, 0x56, 0x25, 0xba, 0x35, 0x8a, 0x52, 0x7e, 0x30, 0x19, 0x8f, 0xfd, 0xa4, 0x42, 0x68, 0x9c,
0x73, 0x84, 0xa6, 0x66, 0x0b, 0x0d, 0xb2, 0xf2, 0xb1, 0x1f, 0x84, 0xc2, 0xc3, 0x13, 0x12, 0x67,
0x20, 0xec, 0x06, 0x2c, 0xf7, 0x47, 0x51, 0x2a, 0xbc, 0x1e, 0xf3, 0xf8, 0x54, 0x84, 0xcb, 0x42,
0x3e, 0x5b, 0x25, 0xe4, 0xa6, 0x90, 0xce, 0x15, 0x84, 0xd4, 0x85, 0x16, 0x36, 0xca, 0x95, 0xce,
0x99, 0x17, 0x5e, 0x98, 0x89, 0xe1, 0x78, 0x8a, 0x22, 0x21, 0xe4, 0x6f, 0xb9, 0x4a, 0x20, 0xf0,
0x74, 0x86, 0x3a, 0xcd, 0xa0, 0x6e, 0x48, 0x81, 0x28, 0x57, 0xb1, 0x7b, 0x00, 0xa2, 0x2f, 0x32,
0xe3, 0x40, 0x66, 0xfc, 0x6d, 0x7b, 0x47, 0xcc, 0xb5, 0xbf, 0x89, 0x85, 0x49, 0xc2, 0xc9, 0x90,
0x1b, 0x5f, 0xba, 0x1f, 0x43, 0xd3, 0xa8, 0x62, 0x17, 0x61, 0x65, 0xeb, 0xd1, 0xa3, 0xfd, 0x1d,
0xef, 0xce, 0xe3, 0x07, 0x5f, 0xde, 0xe9, 0x6d, 0xed, 0x3d, 0x3a, 0xd8, 0x69, 0x5f, 0x40, 0x78,
0xef, 0xd1, 0xd6, 0x9d, 0xbd, 0xde, 0xbd, 0x47, 0xde, 0x96, 0x82, 0x1d, 0xb4, 0xf1, 0xde, 0xce,
0x47, 0x8f, 0x1e, 0xef, 0x58, 0x78, 0x8d, 0xb5, 0xa1, 0x75, 0xd7, 0xdb, 0xb9, 0xb3, 0xb5, 0x2b,
0x91, 0x19, 0xb6, 0x06, 0xed, 0x7b, 0x4f, 0x1e, 0x6e, 0x3f, 0x78, 0x78, 0xbf, 0xb7, 0x75, 0xe7,
0xe1, 0xd6, 0xce, 0xde, 0xce, 0x76, 0xbb, 0xee, 0xfe, 0xad, 0x03, 0x17, 0x69, 0x94, 0x83, 0xa2,
0x40, 0x5c, 0x85, 0x66, 0x3f, 0x8a, 0x62, 0x8e, 0xfa, 0x5b, 0xab, 0x68, 0x13, 0x42, 0x66, 0x17,
0x0a, 0xf1, 0x28, 0x4a, 0xfa, 0x5c, 0xca, 0x03, 0x10, 0x74, 0x0f, 0x11, 0x64, 0x76, 0xb9, 0x9d,
0x82, 0x42, 0x88, 0x43, 0x53, 0x60, 0x82, 0x64, 0x1d, 0xe6, 0x0e, 0x13, 0xee, 0xf7, 0x8f, 0xa5,
0x24, 0xc8, 0x12, 0xfb, 0x64, 0xee, 0x90, 0xf7, 0x71, 0xb5, 0x47, 0x7c, 0x40, 0x1c, 0xb2, 0xe0,
0x2d, 0x4b, 0x7c, 0x4b, 0xc2, 0xee, 0x3e, 0xac, 0x17, 0x67, 0x20, 0x25, 0xe6, 0x3d, 0x43, 0x62,
0x84, 0x6f, 0xdc, 0x3d, 0x7b, 0x7f, 0x0c, 0xe9, 0xf9, 0x77, 0x07, 0xea, 0x68, 0x3e, 0xcf, 0x36,
0xb5, 0xa6, 0x47, 0x34, 0x63, 0x79, 0x44, 0x14, 0x3c, 0xc0, 0x33, 0x85, 0x50, 0xa8, 0xc2, 0xe8,
0x18, 0x48, 0x5e, 0x9f, 0xf0, 0xfe, 0x09, 0xcd, 0x49, 0xd7, 0x23, 0x82, 0x2c, 0x8f, 0x8e, 0x27,
0x7d, 0x2d, 0x59, 0x5e, 0x95, 0x55, 0x1d, 0x7d, 0x39, 0x9f, 0xd7, 0xd1, 0x77, 0x1d, 0x98, 0x0f,
0xc2, 0xc3, 0x68, 0x12, 0x0e, 0x88, 0xc5, 0x17, 0x3c, 0x55, 0x44, 0x55, 0x19, 0x93, 0xe8, 0x05,
0x63, 0xc5, 0xd0, 0x39, 0xe0, 0x32, 0x3c, 0x98, 0xa4, 0xe4, 0x2e, 0x68, 0x2f, 0xf0, 0x3d, 0x58,
0x31, 0x30, 0xb9, 0x9a, 0x6f, 0xc1, 0x6c, 0x8c, 0x80, 0x5c, 0x4a, 0xa5, 0x9c, 0xc9, 0xcf, 0x10,
0x35, 0x6e, 0x1b, 0x96, 0xee, 0xf3, 0xec, 0x41, 0x78, 0x14, 0xa9, 0x96, 0x7e, 0x34, 0x03, 0xcb,
0x1a, 0x92, 0x0d, 0xdd, 0x80, 0xe5, 0x60, 0xc0, 0xc3, 0x2c, 0xc8, 0xa6, 0x3d, 0xeb, 0xfc, 0x53,
0x84, 0xd1, 0x3f, 0xf3, 0x47, 0x81, 0x9f, 0x4a, 0x0f, 0x40, 0x14, 0xd8, 0x26, 0xac, 0xa1, 0xf1,
0x50, 0xf6, 0x40, 0x6f, 0xb1, 0x38, 0x86, 0x55, 0xd6, 0xa1, 0x78, 0x23, 0x2e, 0xf5, 0xb7, 0xfe,
0x44, 0xf8, 0x29, 0x55, 0x55, 0xb8, 0x6a, 0xa2, 0x25, 0x9c, 0xf2, 0xac, 0x30, 0x30, 0x1a, 0x28,
0x85, 0x80, 0xe6, 0x84, 0xf2, 0x29, 0x86, 0x80, 0x8c, 0x30, 0xd2, 0x42, 0x29, 0x8c, 0x84, 0xca,
0x69, 0x1a, 0xf6, 0xf9, 0xa0, 0x97, 0x45, 0x3d, 0x52, 0xa2, 0xb4, 0x3b, 0x0b, 0x5e, 0x11, 0xa6,
0x80, 0x17, 0x4f, 0xb3, 0x90, 0x67, 0xa4, 0x67, 0x16, 0x3c, 0x55, 0x44, 0xf9, 0x21, 0x12, 0x61,
0x12, 0x1a, 0x9e, 0x2c, 0xa1, 0xa3, 0x39, 0x49, 0x82, 0xb4, 0xd3, 0x22, 0x94, 0x7e, 0xb3, 0x4f,
0xc3, 0xc5, 0x43, 0x9e, 0x66, 0xbd, 0x63, 0xee, 0x0f, 0x78, 0x42, 0xbb, 0x2f, 0xa2, 0x53, 0xc2,
0x7e, 0x57, 0x57, 0x62, 0xdf, 0x27, 0x3c, 0x49, 0x83, 0x28, 0x24, 0xcb, 0xdd, 0xf0, 0x54, 0xd1,
0xfd, 0x26, 0xf9, 0xc3, 0x3a, 0x6e, 0xf6, 0x84, 0x8c, 0x39, 0x7b, 0x0d, 0x1a, 0x62, 0x8e, 0xe9,
0xb1, 0x2f, 0x5d, 0xf4, 0x05, 0x02, 0x0e, 0x8e, 0x7d, 0xd4, 0x08, 0xd6, 0xb2, 0x89, 0x40, 0x64,
0x93, 0xb0, 0x5d, 0xb1, 0x6a, 0xd7, 0x60, 0x49, 0x45, 0xe4, 0xd2, 0xde, 0x88, 0x1f, 0x65, 0xea,
0x78, 0x1d, 0x4e, 0xc6, 0xd8, 0x5d, 0xba, 0xc7, 0x8f, 0x32, 0xf7, 0x21, 0xac, 0x48, 0x19, 0x7e,
0x14, 0x73, 0xd5, 0xf5, 0x67, 0xab, 0xac, 0x5b, 0x73, 0x73, 0xd5, 0x16, 0x7a, 0x8a, 0x11, 0x14,
0x4c, 0x9e, 0xeb, 0x01, 0x33, 0x75, 0x82, 0x6c, 0x50, 0x9a, 0x18, 0x75, 0x88, 0x97, 0xd3, 0xb1,
0x30, 0x5c, 0x9f, 0x74, 0xd2, 0xef, 0xa3, 0x26, 0x10, 0x1a, 0x50, 0x15, 0xdd, 0xef, 0x39, 0xb0,
0x4a, 0xad, 0x29, 0xfb, 0xac, 0x4f, 0x7e, 0xaf, 0x3e, 0xcc, 0x56, 0xdf, 0x0c, 0x6c, 0xac, 0xc1,
0xac, 0xa9, 0x6b, 0x45, 0xe1, 0xc7, 0x3f, 0xcb, 0xd6, 0x4b, 0x67, 0xd9, 0x1f, 0x39, 0xb0, 0x22,
0x94, 0x61, 0xe6, 0x67, 0x93, 0x54, 0x4e, 0xff, 0x17, 0x61, 0x51, 0xd8, 0x29, 0x29, 0x4e, 0x72,
0xa0, 0x6b, 0x5a, 0xf2, 0x09, 0x15, 0xc4, 0xbb, 0x17, 0x3c, 0x9b, 0x98, 0x7d, 0x1e, 0x5a, 0x66,
0x58, 0x95, 0xc6, 0xdc, 0xdc, 0xbc, 0xac, 0x66, 0x59, 0xe2, 0x9c, 0xdd, 0x0b, 0x9e, 0xf5, 0x01,
0xfb, 0x90, 0x9c, 0x8d, 0xb0, 0x47, 0xcd, 0xca, 0xc0, 0xd4, 0xe5, 0x0a, 0x05, 0xae, 0x3f, 0x37,
0xc8, 0xef, 0x2e, 0xc0, 0x9c, 0xf0, 0x2e, 0xdd, 0xfb, 0xb0, 0x68, 0x8d, 0xd4, 0x3a, 0xa3, 0xb7,
0xc4, 0x19, 0xbd, 0x14, 0xd2, 0xa9, 0x95, 0x43, 0x3a, 0xee, 0xbf, 0xd6, 0x80, 0x21, 0xb7, 0x15,
0xb6, 0x13, 0xdd, 0xdb, 0x68, 0x60, 0x1d, 0x56, 0x5a, 0x9e, 0x09, 0xb1, 0x9b, 0xc0, 0x8c, 0xa2,
0x8a, 0x7a, 0x09, 0xbb, 0x51, 0x51, 0x83, 0x0a, 0x4e, 0x1a, 0x56, 0x69, 0x02, 0xe5, 0xb1, 0x4c,
0xec, 0x5b, 0x65, 0x1d, 0x9a, 0x86, 0x78, 0x92, 0x1e, 0xa3, 0xfb, 0xad, 0x8e, 0x33, 0xaa, 0x5c,
0x64, 0x90, 0xb9, 0x73, 0x19, 0x64, 0xbe, 0xc8, 0x20, 0xa6, 0x43, 0xbd, 0x60, 0x39, 0xd4, 0xe8,
0xc8, 0x8d, 0xd1, 0xfd, 0xcb, 0x46, 0xfd, 0xde, 0x18, 0x7b, 0x97, 0xa7, 0x17, 0x0b, 0x64, 0x1b,
0xd0, 0x96, 0xae, 0x40, 0xee, 0xb5, 0x03, 0xad, 0x71, 0x09, 0x77, 0x7f, 0xe8, 0x40, 0x1b, 0xd7,
0xd9, 0xe2, 0xc5, 0x0f, 0x80, 0x44, 0xe1, 0x15, 0x59, 0xd1, 0xa2, 0xfd, 0xe9, 0x39, 0xf1, 0x7d,
0x68, 0x50, 0x83, 0x51, 0xcc, 0x43, 0xc9, 0x88, 0x1d, 0x9b, 0x11, 0x73, 0x2d, 0xb4, 0x7b, 0xc1,
0xcb, 0x89, 0x0d, 0x36, 0xfc, 0x47, 0x07, 0x9a, 0x72, 0x98, 0x3f, 0xf1, 0x49, 0xbc, 0x0b, 0x0b,
0xc8, 0x91, 0xc6, 0x71, 0x57, 0x97, 0xd1, 0x9a, 0x8c, 0xfd, 0x6c, 0x92, 0xa0, 0xf9, 0xb4, 0x4e,
0xe1, 0x45, 0x18, 0x6d, 0x21, 0x29, 0xdc, 0xb4, 0x97, 0x05, 0xa3, 0x9e, 0xaa, 0x95, 0xb7, 0x18,
0x55, 0x55, 0xa8, 0x77, 0xd2, 0xcc, 0x1f, 0x72, 0x69, 0xe6, 0x44, 0xc1, 0xed, 0xc0, 0xba, 0x9c,
0x50, 0xc1, 0x77, 0x74, 0xff, 0xa6, 0x05, 0x97, 0x4a, 0x55, 0xfa, 0x1a, 0x50, 0x1e, 0x2f, 0x47,
0xc1, 0xf8, 0x30, 0xd2, 0x8e, 0xb6, 0x63, 0x9e, 0x3c, 0xad, 0x2a, 0x36, 0x84, 0x8b, 0xca, 0x9e,
0xe3, 0x9a, 0xe6, 0xd6, 0xbb, 0x46, 0x8e, 0xc8, 0xbb, 0x36, 0x0f, 0x14, 0x3b, 0x54, 0xb8, 0x29,
0xb9, 0xd5, 0xed, 0xb1, 0x63, 0xe8, 0x68, 0xc7, 0x41, 0xaa, 0x78, 0xc3, 0xb9, 0xc0, 0xbe, 0xde,
0x39, 0xa7, 0x2f, 0xcb, 0x11, 0xf5, 0xce, 0x6c, 0x8d, 0x4d, 0xe1, 0x8a, 0xaa, 0x23, 0x1d, 0x5e,
0xee, 0xaf, 0xfe, 0x4a, 0x73, 0x23, 0x27, 0xda, 0xee, 0xf4, 0x9c, 0x86, 0xd9, 0xd7, 0x61, 0xfd,
0xd4, 0x0f, 0x32, 0x35, 0x2c, 0xc3, 0x19, 0x9a, 0xa5, 0x2e, 0x37, 0xcf, 0xe9, 0xf2, 0xa9, 0xf8,
0xd8, 0x32, 0x6c, 0x67, 0xb4, 0xd8, 0xfd, 0x7b, 0x07, 0x96, 0xec, 0x76, 0x90, 0x4d, 0xa5, 0xc0,
0x2b, 0xc5, 0xa7, 0x9c, 0xbf, 0x02, 0x5c, 0x3e, 0xab, 0xd6, 0xaa, 0xce, 0xaa, 0xe6, 0x09, 0x71,
0xe6, 0xbc, 0x30, 0x4e, 0xfd, 0xd5, 0xc2, 0x38, 0xb3, 0x55, 0x61, 0x9c, 0xee, 0x7f, 0x3b, 0xc0,
0xca, 0xbc, 0xc4, 0xee, 0x8b, 0xc3, 0x72, 0xc8, 0x47, 0x52, 0x27, 0xfd, 0xfc, 0xab, 0xf1, 0xa3,
0x5a, 0x3b, 0xf5, 0x35, 0x0a, 0x86, 0xa9, 0x74, 0x4c, 0x17, 0x69, 0xd1, 0xab, 0xaa, 0x2a, 0x04,
0x96, 0xea, 0xe7, 0x07, 0x96, 0x66, 0xcf, 0x0f, 0x2c, 0xcd, 0x15, 0x03, 0x4b, 0xdd, 0xdf, 0x71,
0x60, 0xb5, 0x62, 0xd3, 0x7f, 0x76, 0x13, 0xc7, 0x6d, 0xb2, 0x74, 0x41, 0x4d, 0x6e, 0x93, 0x09,
0x76, 0x7f, 0x03, 0x16, 0x2d, 0x46, 0xff, 0xd9, 0xf5, 0x5f, 0xf4, 0xf2, 0x04, 0x9f, 0x59, 0x58,
0xf7, 0x3f, 0x6a, 0xc0, 0xca, 0xc2, 0xf6, 0xff, 0x3a, 0x86, 0xf2, 0x3a, 0xcd, 0x54, 0xac, 0xd3,
0xff, 0xa9, 0x1d, 0x78, 0x07, 0x56, 0x64, 0xce, 0x80, 0x11, 0x22, 0x11, 0x1c, 0x53, 0xae, 0x40,
0x3f, 0xd7, 0x8e, 0xea, 0x2d, 0x58, 0x77, 0xcd, 0x86, 0x31, 0x2c, 0x04, 0xf7, 0xdc, 0x75, 0x58,
0x13, 0x39, 0x08, 0x77, 0x45, 0x53, 0xca, 0xae, 0xfc, 0x89, 0x03, 0x17, 0x0b, 0x15, 0xf9, 0xcd,
0xa8, 0x30, 0x1d, 0xb6, 0x3d, 0xb1, 0x41, 0x1c, 0xbf, 0x94, 0x23, 0x63, 0xfc, 0x82, 0xdb, 0xca,
0x15, 0xb8, 0x3e, 0x93, 0xb0, 0x4c, 0x2f, 0x56, 0xbd, 0xaa, 0xca, 0xbd, 0x24, 0x32, 0x25, 0x42,
0x3e, 0x2a, 0x0c, 0xfc, 0x48, 0xe4, 0x36, 0x98, 0x15, 0xf9, 0xd5, 0x8a, 0x3d, 0x64, 0x55, 0x44,
0x2f, 0xd0, 0x32, 0x53, 0xf6, 0x78, 0x2b, 0xeb, 0xdc, 0xbf, 0x72, 0x80, 0x7d, 0x69, 0xc2, 0x93,
0x29, 0xdd, 0x90, 0xea, 0x58, 0xce, 0xa5, 0x62, 0x1c, 0x63, 0x2e, 0x9e, 0x1c, 0x7e, 0x91, 0x4f,
0xd5, 0x3d, 0x7a, 0x2d, 0xbf, 0x47, 0x7f, 0x03, 0x00, 0x8f, 0x5f, 0xfa, 0xda, 0x15, 0x79, 0x01,
0xcf, 0xbd, 0xa2, 0xc1, 0xca, 0xab, 0xee, 0xfa, 0xf9, 0x57, 0xdd, 0xb3, 0xe7, 0x5d, 0x75, 0x7f,
0x08, 0xab, 0xd6, 0xb8, 0xf5, 0xb6, 0xaa, 0x0b, 0x60, 0xe7, 0x25, 0x17, 0xc0, 0xff, 0xe9, 0xc0,
0xcc, 0x6e, 0x14, 0x9b, 0x71, 0x4b, 0xc7, 0x8e, 0x5b, 0x4a, 0x5b, 0xd2, 0xd3, 0xa6, 0x42, 0xaa,
0x18, 0x0b, 0x64, 0x1b, 0xb0, 0xe4, 0x8f, 0x33, 0x3c, 0x76, 0x1f, 0x45, 0xc9, 0xa9, 0x9f, 0x0c,
0xc4, 0x5e, 0xdf, 0xad, 0x75, 0x1c, 0xaf, 0x50, 0xc3, 0xd6, 0x60, 0x46, 0x2b, 0x5d, 0x22, 0xc0,
0x22, 0x3a, 0x6e, 0x74, 0xe7, 0x31, 0x95, 0x11, 0x03, 0x59, 0x42, 0x56, 0xb2, 0xbf, 0x17, 0xae,
0xb2, 0x10, 0x9d, 0xaa, 0x2a, 0xb4, 0x6b, 0xb8, 0x7c, 0x44, 0x26, 0x43, 0x3d, 0xaa, 0xec, 0xfe,
0x9b, 0x03, 0xb3, 0xb4, 0x02, 0x28, 0xec, 0x82, 0xc3, 0x75, 0x80, 0x92, 0x66, 0xbe, 0xe8, 0x15,
0x61, 0xe6, 0x5a, 0xf9, 0x26, 0x35, 0x3d, 0x6c, 0x33, 0xe7, 0xe4, 0x2a, 0x34, 0x44, 0x49, 0xe7,
0x56, 0x10, 0x49, 0x0e, 0xb2, 0x2b, 0x50, 0x3f, 0x8e, 0x62, 0xe5, 0x9d, 0x80, 0x8a, 0xcf, 0x47,
0xb1, 0x47, 0x78, 0x3e, 0x1e, 0x6c, 0x4f, 0x0c, 0x5e, 0xd8, 0x9c, 0x22, 0x8c, 0x56, 0x57, 0x37,
0x6b, 0x2e, 0x46, 0x01, 0x75, 0x37, 0x60, 0xf9, 0x61, 0x34, 0xe0, 0x46, 0x4c, 0xe9, 0x4c, 0x6e,
0x76, 0xbf, 0xe5, 0xc0, 0x82, 0x22, 0x66, 0x37, 0xa0, 0x8e, 0xae, 0x44, 0xe1, 0xa0, 0xa0, 0xef,
0xe5, 0x90, 0xce, 0x23, 0x0a, 0xd4, 0xbd, 0x14, 0x71, 0xc8, 0xdd, 0x4a, 0x15, 0x6f, 0xc8, 0xbd,
0x26, 0x3d, 0xdc, 0x82, 0xb3, 0x51, 0x40, 0xdd, 0xbf, 0x70, 0x60, 0xd1, 0xea, 0x03, 0x8f, 0x87,
0x23, 0x3f, 0xcd, 0xe4, 0x5d, 0x87, 0xdc, 0x1e, 0x13, 0x32, 0xa3, 0x8c, 0x35, 0x3b, 0xca, 0xa8,
0xe3, 0x5f, 0x33, 0x66, 0xfc, 0xeb, 0x36, 0x34, 0xf2, 0xac, 0xa0, 0xba, 0xa5, 0x53, 0xb1, 0x47,
0x75, 0xe3, 0x98, 0x13, 0x61, 0x3b, 0xfd, 0x68, 0x14, 0x25, 0x32, 0xc8, 0x2e, 0x0a, 0xee, 0x87,
0xd0, 0x34, 0xe8, 0x71, 0x18, 0x21, 0xcf, 0x4e, 0xa3, 0xe4, 0x99, 0x0a, 0x76, 0xca, 0xa2, 0xbe,
0x58, 0xaf, 0xe5, 0x17, 0xeb, 0xee, 0x0f, 0x1c, 0x58, 0x44, 0x1e, 0x0c, 0xc2, 0xe1, 0x7e, 0x34,
0x0a, 0xfa, 0x53, 0xda, 0x7b, 0xc5, 0x6e, 0x52, 0x33, 0x28, 0x5e, 0xb4, 0x61, 0xe4, 0x6d, 0x75,
0x3a, 0x94, 0x82, 0xa8, 0xcb, 0x28, 0xa9, 0xc8, 0xe7, 0x87, 0x7e, 0x2a, 0x99, 0x5f, 0x1a, 0x39,
0x0b, 0x44, 0x79, 0x42, 0x20, 0xf1, 0x33, 0xde, 0x1b, 0x07, 0xa3, 0x51, 0x20, 0x68, 0x85, 0x0b,
0x54, 0x55, 0x85, 0x7d, 0x0e, 0x82, 0xd4, 0x3f, 0xcc, 0x03, 0xc9, 0xba, 0xec, 0x7e, 0xbf, 0x06,
0x4d, 0xa9, 0x9e, 0x77, 0x06, 0x43, 0x2e, 0x6f, 0x39, 0xc8, 0xc9, 0xd4, 0xaa, 0xc4, 0x40, 0x54,
0xbd, 0xe5, 0x96, 0x1a, 0x48, 0x71, 0xcb, 0x67, 0xca, 0x5b, 0xfe, 0x3a, 0x34, 0x90, 0xf5, 0xde,
0x25, 0xff, 0x57, 0xdc, 0x90, 0xe4, 0x80, 0xaa, 0xdd, 0xa4, 0xda, 0xd9, 0xbc, 0x96, 0x80, 0x97,
0xde, 0x89, 0xbc, 0x0f, 0x2d, 0xd9, 0x0c, 0xed, 0x09, 0x69, 0x8e, 0x9c, 0xf9, 0xad, 0xfd, 0xf2,
0x2c, 0x4a, 0xf5, 0xe5, 0xa6, 0xfa, 0x72, 0xe1, 0xbc, 0x2f, 0x15, 0x25, 0xdd, 0x5f, 0x8b, 0xb5,
0xb9, 0x9f, 0xf8, 0xf1, 0xb1, 0x32, 0x79, 0x03, 0x9d, 0x94, 0x43, 0x30, 0xdb, 0x80, 0x59, 0xfc,
0x4c, 0x69, 0xf2, 0x6a, 0x81, 0x14, 0x24, 0xec, 0x06, 0xcc, 0xf2, 0xc1, 0x90, 0xab, 0x13, 0x1e,
0xb3, 0xcf, 0xda, 0xb8, 0x47, 0x9e, 0x20, 0x40, 0xf5, 0x80, 0x68, 0x41, 0x3d, 0xd8, 0x56, 0x60,
0x0e, 0x8b, 0x0f, 0x06, 0xee, 0x1a, 0xb0, 0x87, 0x82, 0xa3, 0xcd, 0x08, 0xf5, 0x6f, 0xcf, 0x40,
0xd3, 0x80, 0x51, 0xd2, 0x87, 0x38, 0xe0, 0xde, 0x20, 0xf0, 0xc7, 0x3c, 0xe3, 0x89, 0xe4, 0xe2,
0x02, 0x8a, 0x74, 0xfe, 0xc9, 0xb0, 0x17, 0x4d, 0xb2, 0xde, 0x80, 0x0f, 0x13, 0x2e, 0x0c, 0x33,
0x1a, 0x0a, 0x0b, 0x45, 0xba, 0xb1, 0xff, 0xdc, 0xa4, 0x13, 0xfc, 0x50, 0x40, 0x55, 0xbc, 0x59,
0xac, 0x51, 0x3d, 0x8f, 0x37, 0x8b, 0x15, 0x29, 0xea, 0xa8, 0xd9, 0x0a, 0x1d, 0xf5, 0x1e, 0xac,
0x0b, 0x6d, 0x24, 0xe5, 0xb6, 0x57, 0x60, 0x93, 0x33, 0x6a, 0xd9, 0x06, 0xb4, 0x71, 0xcc, 0x8a,
0xc1, 0xd3, 0xe0, 0x9b, 0x22, 0x02, 0xe4, 0x78, 0x25, 0x1c, 0x69, 0x51, 0x54, 0x2d, 0x5a, 0x71,
0xa3, 0x56, 0xc2, 0x89, 0xd6, 0x7f, 0x6e, 0xd3, 0x36, 0x24, 0x6d, 0x01, 0x77, 0x17, 0xa1, 0x79,
0x90, 0x45, 0xb1, 0xda, 0x94, 0x25, 0x68, 0x89, 0xa2, 0xcc, 0x5f, 0x78, 0x0d, 0x2e, 0x13, 0x17,
0x3d, 0x8e, 0xe2, 0x68, 0x14, 0x0d, 0xa7, 0x07, 0x93, 0xc3, 0xb4, 0x9f, 0x04, 0x31, 0x9e, 0x86,
0xdc, 0x7f, 0x70, 0x60, 0xd5, 0xaa, 0x95, 0x21, 0xa3, 0x4f, 0x0b, 0x96, 0xd6, 0x17, 0xcf, 0x82,
0xf1, 0x56, 0x0c, 0x55, 0x29, 0x08, 0x45, 0xb0, 0xee, 0x89, 0xbc, 0x8b, 0xbe, 0x03, 0xcb, 0x6a,
0x64, 0xea, 0x43, 0xc1, 0x85, 0x9d, 0x32, 0x17, 0xca, 0xef, 0x97, 0xe4, 0x07, 0xaa, 0x89, 0x5f,
0x92, 0x37, 0x93, 0x03, 0x9a, 0xa3, 0x8a, 0x1d, 0xe8, 0xbb, 0x27, 0xf3, 0x04, 0xa1, 0x46, 0xd0,
0xd7, 0x60, 0xea, 0xfe, 0x9e, 0x03, 0x90, 0x8f, 0x0e, 0x19, 0x23, 0x57, 0xf7, 0x22, 0x59, 0xda,
0x50, 0xed, 0x6f, 0x41, 0x4b, 0xdf, 0x9a, 0xe4, 0x16, 0xa4, 0xa9, 0x30, 0x74, 0xf2, 0xae, 0xc3,
0xf2, 0x70, 0x14, 0x1d, 0x92, 0xf9, 0xa5, 0x84, 0x98, 0x54, 0x66, 0x71, 0x2c, 0x09, 0xf8, 0x9e,
0x44, 0x73, 0x73, 0x53, 0x37, 0xcc, 0x8d, 0xfb, 0xed, 0x9a, 0x8e, 0xb5, 0xe7, 0x73, 0x3e, 0x53,
0xca, 0xd8, 0x66, 0x49, 0x39, 0x9e, 0x11, 0xda, 0xa6, 0x28, 0xd9, 0xfe, 0xb9, 0x87, 0xf8, 0x0f,
0x61, 0x29, 0x11, 0xda, 0x47, 0xa9, 0xa6, 0xfa, 0x4b, 0x54, 0xd3, 0x62, 0x62, 0xd9, 0xa4, 0x4f,
0x42, 0xdb, 0x1f, 0x9c, 0xf0, 0x24, 0x0b, 0xe8, 0x18, 0x45, 0x0e, 0x81, 0x50, 0xa8, 0xcb, 0x06,
0x4e, 0x76, 0xfa, 0x3a, 0x2c, 0xcb, 0xcc, 0x19, 0x4d, 0x29, 0xb3, 0x3d, 0x73, 0x18, 0x09, 0xdd,
0x3f, 0x53, 0x61, 0x7d, 0x7b, 0x0f, 0xcf, 0x5e, 0x11, 0x73, 0x76, 0xb5, 0xc2, 0xec, 0x3e, 0x21,
0x43, 0xec, 0x03, 0x75, 0x56, 0x9b, 0x31, 0x6e, 0xb1, 0x07, 0xf2, 0x4a, 0xc4, 0x5e, 0xd2, 0xfa,
0xab, 0x2c, 0xa9, 0xfb, 0x43, 0x07, 0xe6, 0x77, 0xa3, 0x78, 0x57, 0xde, 0xe7, 0x93, 0x20, 0xe8,
0xbc, 0x34, 0x55, 0x7c, 0xc9, 0x4d, 0x7f, 0xa5, 0x1d, 0x5e, 0x2c, 0xda, 0xe1, 0x5f, 0x86, 0xd7,
0x28, 0x52, 0x90, 0x44, 0x71, 0x94, 0xa0, 0x30, 0xfa, 0x23, 0x61, 0x74, 0xa3, 0x30, 0x3b, 0x56,
0x6a, 0xec, 0x65, 0x24, 0x74, 0x24, 0xc3, 0xa3, 0x84, 0x70, 0x94, 0xa5, 0xdf, 0x20, 0xb4, 0x5b,
0xb9, 0xc2, 0xfd, 0x2c, 0x34, 0xc8, 0xf1, 0xa5, 0x69, 0xbd, 0x03, 0x8d, 0xe3, 0x28, 0xee, 0x1d,
0x07, 0x61, 0xa6, 0x84, 0x7b, 0x29, 0xf7, 0x48, 0x77, 0x69, 0x41, 0x34, 0x81, 0xfb, 0x83, 0x3a,
0xcc, 0x3f, 0x08, 0x4f, 0xa2, 0xa0, 0x4f, 0x37, 0x00, 0x63, 0x3e, 0x8e, 0x54, 0x96, 0x1e, 0xfe,
0xc6, 0xa5, 0xa0, 0x8c, 0x95, 0x38, 0x93, 0x21, 0x7c, 0x55, 0x44, 0x73, 0x9f, 0xe4, 0x99, 0xb4,
0x42, 0x74, 0x0c, 0x04, 0x9d, 0xfe, 0xc4, 0x4c, 0x3a, 0x96, 0xa5, 0x3c, 0xcd, 0x71, 0xd6, 0x48,
0x73, 0xa4, 0xfb, 0x22, 0x91, 0x7b, 0x40, 0xfc, 0xb5, 0xe0, 0xa9, 0x22, 0x1d, 0x52, 0x12, 0x2e,
0x22, 0x3c, 0xe4, 0x38, 0xcc, 0xcb, 0x43, 0x8a, 0x09, 0xa2, 0x73, 0x21, 0x3e, 0x10, 0x34, 0x42,
0xf9, 0x9a, 0x10, 0x3a, 0x62, 0xc5, 0xbc, 0xe5, 0x86, 0xe0, 0xf9, 0x02, 0x8c, 0x1a, 0x7a, 0xc0,
0xb5, 0x22, 0x15, 0x73, 0x00, 0x91, 0x29, 0x5c, 0xc4, 0x8d, 0xa3, 0x8d, 0x48, 0x2a, 0x52, 0x47,
0x1b, 0x64, 0x14, 0x7f, 0x34, 0x3a, 0xf4, 0xfb, 0xcf, 0x28, 0x2d, 0x9d, 0x72, 0x88, 0x1a, 0x9e,
0x0d, 0x52, 0x36, 0x41, 0xbe, 0x9b, 0x74, 0xe3, 0x58, 0xf7, 0x4c, 0x88, 0x6d, 0x42, 0x93, 0x8e,
0x73, 0x72, 0x3f, 0x97, 0x68, 0x3f, 0xdb, 0xe6, 0x79, 0x8f, 0x76, 0xd4, 0x24, 0x32, 0x6f, 0x25,
0x96, 0xed, 0x5b, 0x09, 0xa1, 0x34, 0xe5, 0x65, 0x4e, 0x9b, 0x7a, 0xcb, 0x01, 0xb4, 0xa6, 0x72,
0xc1, 0x04, 0xc1, 0x0a, 0x11, 0x58, 0x18, 0x4a, 0x2d, 0x1e, 0x42, 0x62, 0x3f, 0x18, 0x74, 0x98,
0x90, 0x5a, 0x55, 0x76, 0x33, 0x60, 0x77, 0x06, 0x03, 0xc9, 0x4d, 0xfa, 0xb0, 0x9a, 0xf3, 0x81,
0x63, 0xf1, 0x41, 0xc5, 0x7e, 0xd4, 0xaa, 0xf7, 0xe3, 0xa5, 0xa3, 0x76, 0x77, 0xa0, 0xb9, 0x6f,
0x24, 0x53, 0x13, 0x5b, 0xaa, 0x34, 0x6a, 0xc9, 0xca, 0x06, 0x62, 0x0c, 0xa7, 0x66, 0x0e, 0xc7,
0xfd, 0x05, 0x60, 0x7b, 0x41, 0x9a, 0xe9, 0xd1, 0xe7, 0xd9, 0xdb, 0x2a, 0xa2, 0x90, 0x27, 0x40,
0x35, 0x25, 0x46, 0x89, 0x49, 0x77, 0x44, 0xe6, 0x54, 0x71, 0xda, 0x1b, 0xb0, 0x10, 0x08, 0xa8,
0x28, 0x85, 0x8a, 0x52, 0xd7, 0xbb, 0x4f, 0x61, 0x55, 0x82, 0xa6, 0x05, 0xb7, 0xe7, 0xed, 0x9c,
0xb7, 0x5b, 0xb5, 0xf2, 0x6e, 0xb9, 0xdf, 0x77, 0x60, 0x5e, 0x2e, 0x0e, 0xd2, 0x97, 0x12, 0xd1,
0x1b, 0x9e, 0x85, 0x55, 0xa7, 0x20, 0x97, 0x25, 0x70, 0xa6, 0x4a, 0x02, 0x19, 0xd4, 0x63, 0x3f,
0x3b, 0xa6, 0xa3, 0x57, 0xc3, 0xa3, 0xdf, 0xac, 0x2d, 0xc2, 0x01, 0x42, 0xd2, 0x29, 0x14, 0x50,
0x95, 0x85, 0x2f, 0x0c, 0x4a, 0x09, 0x47, 0x17, 0x9a, 0xf2, 0x2d, 0x04, 0xae, 0xaf, 0x51, 0x64,
0x26, 0x58, 0x0e, 0xe7, 0x2b, 0x2e, 0x9b, 0x28, 0xae, 0xb8, 0x24, 0xf5, 0x74, 0xbd, 0xdb, 0x85,
0xce, 0x36, 0x1f, 0xf1, 0x8c, 0xdf, 0x19, 0x8d, 0x8a, 0xed, 0xbf, 0x06, 0x97, 0x2b, 0xea, 0xa4,
0xcb, 0x75, 0x0f, 0x56, 0xb6, 0xf9, 0xe1, 0x64, 0xb8, 0xc7, 0x4f, 0xf2, 0xbb, 0x4e, 0x06, 0xf5,
0xf4, 0x38, 0x3a, 0x95, 0xdc, 0x41, 0xbf, 0xd9, 0x1b, 0x00, 0x23, 0xa4, 0xe9, 0xa5, 0x31, 0xef,
0xab, 0xe4, 0x5b, 0x42, 0x0e, 0x62, 0xde, 0x77, 0xdf, 0x03, 0x66, 0xb6, 0x23, 0xa7, 0x80, 0x5a,
0x6c, 0x72, 0xd8, 0x4b, 0xa7, 0x69, 0xc6, 0xc7, 0x2a, 0xab, 0xd8, 0x84, 0xdc, 0xeb, 0xd0, 0xda,
0xf7, 0xa7, 0x1e, 0xff, 0x86, 0x7c, 0x0b, 0x80, 0xa7, 0x7e, 0x7f, 0x8a, 0xa2, 0xa2, 0x4f, 0xfd,
0x54, 0xed, 0xfe, 0x57, 0x0d, 0xe6, 0x04, 0x25, 0xb6, 0x3a, 0xe0, 0x69, 0x16, 0x84, 0xe2, 0x9e,
0x4f, 0xb6, 0x6a, 0x40, 0x25, 0xde, 0xa8, 0x55, 0xf0, 0x86, 0xf4, 0xb5, 0x55, 0x22, 0xa3, 0x64,
0x02, 0x0b, 0x43, 0x8e, 0xcd, 0xf3, 0x27, 0xc4, 0xb1, 0x33, 0x07, 0x0a, 0x61, 0xa0, 0x5c, 0x57,
0x8a, 0xf1, 0x29, 0xb6, 0x97, 0xec, 0x60, 0x42, 0x95, 0x1a, 0x79, 0x5e, 0x70, 0x4d, 0x49, 0x23,
0x97, 0x34, 0xef, 0xc2, 0x2b, 0x68, 0x5e, 0xe1, 0x80, 0xbf, 0x4c, 0xf3, 0xc2, 0x2b, 0x68, 0x5e,
0x97, 0x41, 0xfb, 0x1e, 0xe7, 0x1e, 0x47, 0x9b, 0xae, 0xd8, 0xe9, 0x3b, 0x0e, 0xb4, 0xa5, 0x3b,
0xa2, 0xeb, 0xd8, 0x5b, 0x96, 0xef, 0x52, 0x99, 0x6e, 0x78, 0x0d, 0x16, 0xc9, 0xa3, 0xd0, 0xf1,
0x2e, 0x19, 0x9c, 0xb3, 0x40, 0x9c, 0x87, 0xba, 0x94, 0x18, 0x07, 0x23, 0xb9, 0x29, 0x26, 0xa4,
0x42, 0x66, 0x78, 0xf2, 0xa7, 0x2d, 0x71, 0x3c, 0x5d, 0x76, 0xff, 0xda, 0x81, 0x15, 0x63, 0xc0,
0x92, 0x0b, 0x3f, 0x04, 0x95, 0x5f, 0x21, 0xc2, 0x62, 0x42, 0x98, 0x2e, 0xd9, 0xae, 0x55, 0xfe,
0x99, 0x45, 0x4c, 0x9b, 0xe9, 0x4f, 0x69, 0x80, 0xe9, 0x64, 0x2c, 0xb5, 0x92, 0x09, 0x21, 0x23,
0x9d, 0x72, 0xfe, 0x4c, 0x93, 0xcc, 0x08, 0xc5, 0x65, 0x62, 0x74, 0x7d, 0x8e, 0x9e, 0x90, 0x26,
0x12, 0x19, 0x63, 0x36, 0xe8, 0xfe, 0x93, 0x03, 0xab, 0xc2, 0xa5, 0x95, 0x07, 0x06, 0x9d, 0x0b,
0x3e, 0x27, 0x7c, 0x78, 0x21, 0x91, 0xbb, 0x17, 0x3c, 0x59, 0x66, 0x9f, 0x79, 0x45, 0x37, 0x5c,
0xa7, 0x4d, 0x9c, 0xb1, 0x17, 0x33, 0x55, 0x7b, 0xf1, 0x92, 0x95, 0xae, 0x0a, 0x03, 0xcd, 0x56,
0x86, 0x81, 0xee, 0xce, 0xc3, 0x6c, 0xda, 0x8f, 0x62, 0xee, 0xae, 0xc3, 0x9a, 0x3d, 0x39, 0xa9,
0x82, 0xbe, 0xeb, 0x40, 0xe7, 0x9e, 0x08, 0x8a, 0x06, 0xe1, 0x70, 0x37, 0x48, 0xb3, 0x28, 0xd1,
0x8f, 0x5f, 0xae, 0x00, 0xa4, 0x99, 0x9f, 0x64, 0x22, 0xad, 0x4d, 0x06, 0x69, 0x72, 0x04, 0xc7,
0xc8, 0xc3, 0x81, 0xa8, 0x15, 0x7b, 0xa3, 0xcb, 0xb8, 0x31, 0x64, 0x36, 0x7a, 0xd1, 0xd1, 0x51,
0xca, 0xb5, 0xd3, 0x6d, 0x62, 0x78, 0x6e, 0x47, 0x89, 0xc7, 0x93, 0x2a, 0x3f, 0x21, 0x55, 0x2b,
0xbc, 0xd9, 0x02, 0xea, 0xfe, 0xa5, 0x03, 0xcb, 0xf9, 0x20, 0x77, 0x10, 0xb4, 0xb5, 0x83, 0xb4,
0x67, 0xb9, 0x76, 0x50, 0xe1, 0xa3, 0x00, 0x0d, 0x9c, 0x1c, 0x9b, 0x81, 0x90, 0xc4, 0xca, 0x52,
0x34, 0x51, 0x29, 0x84, 0x26, 0x24, 0xf2, 0x03, 0x32, 0xfc, 0x5a, 0xe4, 0x0f, 0xca, 0x12, 0x65,
0x25, 0x8e, 0x33, 0xfa, 0x6a, 0x4e, 0xb8, 0xf3, 0xb2, 0xa8, 0xec, 0xd3, 0x3c, 0xa1, 0xf8, 0xd3,
0xfd, 0x7d, 0x07, 0x2e, 0x57, 0x2c, 0xae, 0x94, 0x8c, 0x6d, 0x58, 0x39, 0xd2, 0x95, 0x6a, 0x01,
0x84, 0x78, 0xac, 0xab, 0x28, 0xbe, 0x3d, 0x69, 0xaf, 0xfc, 0x01, 0x3a, 0xf7, 0x14, 0xf5, 0x12,
0x4b, 0x6a, 0xa5, 0xd6, 0x94, 0x2b, 0x36, 0xff, 0x60, 0x06, 0x96, 0xc4, 0xed, 0x8e, 0x78, 0x86,
0xca, 0x13, 0xf6, 0x11, 0xcc, 0xcb, 0x67, 0xc4, 0xec, 0xa2, 0xec, 0xd6, 0x7e, 0xb8, 0xdc, 0x5d,
0x2f, 0xc2, 0x92, 0x77, 0x56, 0x7f, 0xeb, 0x87, 0xff, 0xf2, 0x87, 0xb5, 0x45, 0xd6, 0xbc, 0x75,
0xf2, 0xee, 0xad, 0x21, 0x0f, 0x53, 0x6c, 0xe3, 0xd7, 0x00, 0xf2, 0x07, 0xb6, 0xac, 0xa3, 0xdd,
0x94, 0xc2, 0xcb, 0xe1, 0xee, 0xe5, 0x8a, 0x1a, 0xd9, 0xee, 0x65, 0x6a, 0x77, 0xd5, 0x5d, 0xc2,
0x76, 0x83, 0x30, 0xc8, 0xc4, 0x6b, 0xdb, 0x0f, 0x9c, 0x0d, 0x36, 0x80, 0x96, 0xf9, 0x7e, 0x96,
0xa9, 0x03, 0x7f, 0xc5, 0xeb, 0xdd, 0xee, 0x6b, 0x95, 0x75, 0x2a, 0xda, 0x41, 0x7d, 0x5c, 0x74,
0xdb, 0xd8, 0xc7, 0x84, 0x28, 0xf2, 0x5e, 0x46, 0xb0, 0x64, 0x3f, 0x93, 0x65, 0xaf, 0x1b, 0x62,
0x5d, 0x7a, 0xa4, 0xdb, 0x7d, 0xe3, 0x8c, 0x5a, 0xd9, 0xd7, 0x1b, 0xd4, 0xd7, 0x25, 0x97, 0x61,
0x5f, 0x7d, 0xa2, 0x51, 0x8f, 0x74, 0x3f, 0x70, 0x36, 0x36, 0xbf, 0x75, 0x05, 0x1a, 0x3a, 0x44,
0xc7, 0xbe, 0x0e, 0x8b, 0xd6, 0xf5, 0x1b, 0x53, 0xd3, 0xa8, 0xba, 0xad, 0xeb, 0xbe, 0x5e, 0x5d,
0x29, 0x3b, 0xbe, 0x42, 0x1d, 0x77, 0xd8, 0x3a, 0x76, 0x2c, 0xef, 0xaf, 0x6e, 0xd1, 0xa5, 0xa3,
0xc8, 0x79, 0x7c, 0x26, 0xe6, 0x99, 0x5f, 0x99, 0x59, 0xf3, 0x2c, 0x5d, 0xb1, 0x59, 0xf3, 0x2c,
0xdf, 0xb3, 0xb9, 0xaf, 0x53, 0x77, 0xeb, 0x6c, 0xcd, 0xec, 0x4e, 0x87, 0xce, 0x38, 0x65, 0xa9,
0x9a, 0xaf, 0x68, 0xd9, 0x1b, 0x9a, 0xb1, 0xaa, 0x5e, 0xd7, 0x6a, 0x16, 0x29, 0x3f, 0xb1, 0x75,
0x3b, 0xd4, 0x15, 0x63, 0xb4, 0x7d, 0xe6, 0x23, 0x5a, 0xf6, 0x55, 0x68, 0xe8, 0x27, 0x63, 0xec,
0x92, 0xf1, 0x4e, 0xcf, 0x7c, 0xc7, 0xd6, 0xed, 0x94, 0x2b, 0xaa, 0x18, 0xc3, 0x6c, 0x19, 0x19,
0x63, 0x0f, 0x2e, 0x4a, 0xa7, 0xfa, 0x90, 0xff, 0x38, 0x33, 0xa9, 0x78, 0xfb, 0x7b, 0xdb, 0x61,
0x1f, 0xc2, 0x82, 0x7a, 0x89, 0xc7, 0xd6, 0xab, 0x5f, 0x14, 0x76, 0x2f, 0x95, 0x70, 0xa9, 0x3d,
0xee, 0x00, 0xe4, 0xaf, 0xc8, 0xb4, 0x9c, 0x95, 0xde, 0xb6, 0xe9, 0x45, 0xac, 0x78, 0x72, 0x36,
0xa4, 0x37, 0x73, 0xf6, 0x23, 0x35, 0xf6, 0x66, 0x4e, 0x5f, 0xf9, 0x7c, 0xed, 0x25, 0x0d, 0xba,
0xeb, 0xb4, 0x76, 0x6d, 0x46, 0x82, 0x1b, 0xf2, 0x53, 0x95, 0xaf, 0xbd, 0x0d, 0x4d, 0xe3, 0x65,
0x1a, 0x53, 0x2d, 0x94, 0x5f, 0xb5, 0x75, 0xbb, 0x55, 0x55, 0x72, 0xb8, 0x5f, 0x80, 0x45, 0xeb,
0x89, 0x99, 0x96, 0x8c, 0xaa, 0x07, 0x6c, 0x5a, 0x32, 0xaa, 0x5f, 0xa5, 0x7d, 0x05, 0x9a, 0xc6,
0x83, 0x30, 0x66, 0xe4, 0xa9, 0x15, 0x9e, 0x82, 0xe9, 0x11, 0x55, 0xbd, 0x1f, 0x5b, 0xa3, 0xf9,
0x2e, 0xb9, 0x0d, 0x9c, 0x2f, 0x25, 0x2d, 0x23, 0x93, 0x7c, 0x1d, 0x96, 0xec, 0x27, 0x62, 0x5a,
0xaa, 0x2a, 0x1f, 0x9b, 0x69, 0xa9, 0x3a, 0xe3, 0x5d, 0x99, 0x64, 0xc8, 0x8d, 0x55, 0xdd, 0xc9,
0xad, 0x8f, 0xe5, 0xe5, 0xd5, 0x0b, 0xf6, 0x25, 0x54, 0x1d, 0x32, 0x8b, 0x9c, 0xe5, 0x0f, 0xe3,
0xec, 0x5c, 0x73, 0xcd, 0xed, 0xa5, 0x84, 0x73, 0x77, 0x85, 0x1a, 0x6f, 0xb2, 0x7c, 0x06, 0xc2,
0x1e, 0x50, 0x36, 0xb9, 0x61, 0x0f, 0xcc, 0x84, 0x73, 0xc3, 0x1e, 0x58, 0x49, 0xe7, 0x45, 0x7b,
0x90, 0x05, 0xd8, 0x46, 0x08, 0xcb, 0x85, 0x44, 0x0d, 0x2d, 0x2c, 0xd5, 0x99, 0x6d, 0xdd, 0x2b,
0x2f, 0xcf, 0xef, 0xb0, 0xd5, 0x8c, 0x52, 0x2f, 0xb7, 0x54, 0x22, 0xe2, 0xaf, 0x43, 0xcb, 0x7c,
0xda, 0xa3, 0x2d, 0x44, 0xc5, 0x83, 0x24, 0x6d, 0x21, 0xaa, 0xde, 0x02, 0xa9, 0xcd, 0x65, 0x2d,
0xb3, 0x1b, 0xdc, 0x5c, 0xfb, 0x25, 0x44, 0xae, 0x32, 0xab, 0x9e, 0x78, 0xe4, 0x2a, 0xb3, 0xf2,
0xf9, 0x84, 0xda, 0x5c, 0xb6, 0x6a, 0xcd, 0x45, 0x44, 0x26, 0xd9, 0x57, 0x60, 0xd9, 0xc8, 0x82,
0x3a, 0x98, 0x86, 0x7d, 0xcd, 0xa8, 0xe5, 0x1c, 0xd9, 0x6e, 0x95, 0xe7, 0xe9, 0x5e, 0xa2, 0xf6,
0x57, 0x5c, 0x6b, 0x12, 0xc8, 0xa4, 0x5b, 0xd0, 0x34, 0x33, 0xac, 0x5e, 0xd2, 0xee, 0x25, 0xa3,
0xca, 0x4c, 0x17, 0xbd, 0xed, 0xb0, 0x3f, 0x76, 0xa0, 0x65, 0xe5, 0x2b, 0x59, 0xf1, 0xf7, 0x42,
0x3b, 0x1d, 0xb3, 0xce, 0x6c, 0xc8, 0xf5, 0x68, 0x90, 0x7b, 0x1b, 0x5f, 0xb0, 0x16, 0xe1, 0x63,
0xeb, 0x04, 0x73, 0xb3, 0xf8, 0x42, 0xfc, 0x45, 0x91, 0xc0, 0xcc, 0x23, 0x7e, 0x71, 0xdb, 0x61,
0x1f, 0x88, 0xff, 0x40, 0x50, 0x11, 0x0b, 0x66, 0x28, 0xd2, 0xe2, 0x92, 0x99, 0x7f, 0x00, 0x70,
0xc3, 0xb9, 0xed, 0xb0, 0xaf, 0x89, 0x87, 0xe0, 0xf2, 0x5b, 0x5a, 0xf9, 0x57, 0xfd, 0xde, 0xbd,
0x46, 0xb3, 0xb9, 0xe2, 0x5e, 0xb6, 0x66, 0x53, 0xb4, 0x24, 0x77, 0xc4, 0xe8, 0xe4, 0xfb, 0xfe,
0x5c, 0x25, 0x96, 0xde, 0xfc, 0x9f, 0x3d, 0xc8, 0xb1, 0x18, 0xa4, 0x24, 0xb7, 0xd8, 0xe3, 0x15,
0x9b, 0x71, 0x37, 0x68, 0xac, 0xd7, 0xdc, 0x37, 0xcf, 0x1c, 0xeb, 0x2d, 0x3a, 0x91, 0xe2, 0x88,
0xf7, 0x01, 0xf2, 0x80, 0x1c, 0x2b, 0xc4, 0x9f, 0xb4, 0x55, 0x28, 0xc7, 0xec, 0x6c, 0x1e, 0x54,
0x61, 0x2a, 0x6c, 0xf1, 0xab, 0x42, 0x54, 0x25, 0x7d, 0xaa, 0x47, 0x5f, 0x0e, 0x9d, 0x75, 0xbb,
0x55, 0x55, 0x55, 0x82, 0xaa, 0xda, 0x67, 0x4f, 0x60, 0x71, 0x2f, 0x8a, 0x9e, 0x4d, 0x62, 0x1d,
0x90, 0xb6, 0xe3, 0x37, 0xbb, 0x7e, 0x7a, 0xdc, 0x2d, 0xcc, 0xc2, 0xbd, 0x4a, 0x4d, 0x75, 0x59,
0xc7, 0x68, 0xea, 0xd6, 0xc7, 0x79, 0xc0, 0xef, 0x05, 0xf3, 0x61, 0x45, 0x7b, 0x00, 0x7a, 0xe0,
0x5d, 0xbb, 0x19, 0x33, 0xee, 0x56, 0xea, 0xc2, 0xf2, 0xc9, 0xd4, 0x68, 0x6f, 0xa5, 0xaa, 0xcd,
0xdb, 0x0e, 0xdb, 0x87, 0xd6, 0x36, 0xef, 0x47, 0x03, 0x2e, 0x23, 0x2e, 0xab, 0xf9, 0xc0, 0x75,
0xa8, 0xa6, 0xbb, 0x68, 0x81, 0xb6, 0x4e, 0x8c, 0xfd, 0x69, 0xc2, 0xbf, 0x71, 0xeb, 0x63, 0x19,
0xcb, 0x79, 0xa1, 0x74, 0xa2, 0x8a, 0x3f, 0x59, 0x3a, 0xb1, 0x10, 0xb0, 0xb2, 0x74, 0x62, 0x29,
0x60, 0x65, 0x2d, 0xb5, 0x8a, 0x7f, 0xb1, 0x11, 0xac, 0x94, 0x62, 0x5c, 0xda, 0x8f, 0x38, 0x2b,
0x32, 0xd6, 0xbd, 0x7a, 0x36, 0x81, 0xdd, 0xdb, 0x86, 0xdd, 0xdb, 0x01, 0x2c, 0x6e, 0x73, 0xb1,
0x58, 0xe2, 0xd6, 0xbb, 0xf0, 0xe0, 0xcc, 0xbc, 0x21, 0x2f, 0x2a, 0x45, 0xaa, 0xb3, 0x8d, 0x1e,
0x5d, 0x39, 0xb3, 0xaf, 0x42, 0xf3, 0x3e, 0xcf, 0xd4, 0x35, 0xb7, 0xf6, 0xc6, 0x0a, 0xf7, 0xde,
0xdd, 0x8a, 0x5b, 0x72, 0x9b, 0x67, 0xa8, 0xb5, 0x5b, 0x7c, 0x30, 0xe4, 0x42, 0x3d, 0xf5, 0x82,
0xc1, 0x0b, 0xf6, 0x2b, 0xd4, 0xb8, 0xce, 0x9a, 0x59, 0x37, 0x6e, 0x47, 0xcd, 0xc6, 0x97, 0x0b,
0x78, 0x55, 0xcb, 0x61, 0x34, 0xe0, 0x86, 0xf9, 0x0f, 0xa1, 0x69, 0xa4, 0x74, 0x69, 0x01, 0x2a,
0xa7, 0xa7, 0x69, 0x01, 0xaa, 0xc8, 0x00, 0x73, 0x6f, 0x50, 0x3f, 0x2e, 0xbb, 0x9a, 0xf7, 0x23,
0xb2, 0xbe, 0xf2, 0x9e, 0x6e, 0x7d, 0xec, 0x8f, 0xb3, 0x17, 0xec, 0x29, 0x3d, 0x3e, 0x33, 0xaf,
0xf2, 0x73, 0x6f, 0xb0, 0x78, 0xeb, 0xaf, 0x17, 0xcb, 0xa8, 0xb2, 0x3d, 0x44, 0xd1, 0x15, 0x79,
0x09, 0x9f, 0x01, 0x38, 0xc8, 0xa2, 0x78, 0xdb, 0xe7, 0xe3, 0x28, 0xcc, 0x75, 0x6d, 0x7e, 0x5d,
0x9d, 0xeb, 0x2f, 0xe3, 0xce, 0x9a, 0x3d, 0x35, 0xfc, 0x71, 0x2b, 0x13, 0x42, 0x31, 0xd7, 0x99,
0x37, 0xda, 0x7a, 0x41, 0x2a, 0x6e, 0xb5, 0x6f, 0x3b, 0xe8, 0x5d, 0xe7, 0x11, 0x55, 0xed, 0x5d,
0x97, 0x82, 0xb5, 0x5a, 0xed, 0x55, 0x84, 0x5f, 0xf7, 0xa1, 0x91, 0x87, 0xe8, 0x2e, 0xe5, 0x69,
0x79, 0x56, 0x40, 0x4f, 0x5b, 0xc5, 0x52, 0xe0, 0xcc, 0x6d, 0xd3, 0x52, 0x01, 0x5b, 0xc0, 0xa5,
0xa2, 0x68, 0x58, 0x00, 0xab, 0x62, 0x80, 0xda, 0xc4, 0xd3, 0x05, 0xac, 0x9a, 0x49, 0x45, 0xf0,
0x4a, 0x4b, 0x73, 0x65, 0xec, 0xc7, 0x3a, 0x67, 0x23, 0xb7, 0x8a, 0xcb, 0x5f, 0x54, 0xcd, 0x63,
0x58, 0x29, 0x05, 0x2e, 0xb4, 0x48, 0x9f, 0x15, 0x2f, 0xd2, 0x22, 0x7d, 0x66, 0xcc, 0xc3, 0xbd,
0x48, 0x5d, 0x2e, 0xbb, 0x80, 0x5d, 0xa6, 0xa7, 0x41, 0xd6, 0x3f, 0xfe, 0xc0, 0xd9, 0x38, 0x9c,
0xa3, 0xff, 0x4c, 0xfb, 0xd4, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x2e, 0xa2, 0xa7, 0xf7, 0x65,
0x4d, 0x00, 0x00,
// 6239 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5c, 0xdd, 0x8f, 0x1c, 0xd9,
0x55, 0x77, 0x75, 0xf7, 0x7c, 0xf4, 0xe9, 0x9e, 0x99, 0x9e, 0x3b, 0xe3, 0x71, 0xbb, 0x77, 0xd7,
0xeb, 0xad, 0x58, 0x6b, 0x67, 0x58, 0x6c, 0xef, 0x24, 0x59, 0x36, 0xbb, 0x90, 0x60, 0xcf, 0x8c,
0x3d, 0x4e, 0x66, 0xed, 0x49, 0x8d, 0x1d, 0x43, 0x02, 0xea, 0xd4, 0x74, 0xdf, 0xe9, 0xa9, 0xb8,
0xbb, 0xaa, 0x53, 0x55, 0x3d, 0xe3, 0xce, 0x62, 0x29, 0x10, 0xc4, 0x13, 0x11, 0x42, 0xf0, 0x12,
0x24, 0x84, 0x14, 0x24, 0x14, 0xfe, 0x00, 0x78, 0x09, 0x48, 0x3c, 0xf0, 0x12, 0x24, 0xc4, 0x43,
0x9e, 0x22, 0x1e, 0xe1, 0x05, 0x10, 0x2f, 0x48, 0xbc, 0x22, 0x74, 0xce, 0xfd, 0xa8, 0x7b, 0xab,
0xaa, 0x3d, 0xce, 0x07, 0xbc, 0xf5, 0xfd, 0xdd, 0x53, 0xf7, 0xf3, 0x7c, 0xdd, 0x73, 0xcf, 0x6d,
0xa8, 0xc7, 0xe3, 0xde, 0xcd, 0x71, 0x1c, 0xa5, 0x11, 0x9b, 0x1b, 0x86, 0xf1, 0xb8, 0xd7, 0x79,
0x7d, 0x10, 0x45, 0x83, 0x21, 0xbf, 0xe5, 0x8f, 0x83, 0x5b, 0x7e, 0x18, 0x46, 0xa9, 0x9f, 0x06,
0x51, 0x98, 0x08, 0x22, 0xf7, 0x6b, 0xb0, 0x7c, 0x9f, 0x87, 0x87, 0x9c, 0xf7, 0x3d, 0xfe, 0x8d,
0x09, 0x4f, 0x52, 0xf6, 0x0b, 0xb0, 0xea, 0xf3, 0x6f, 0x72, 0xde, 0xef, 0x8e, 0xfd, 0x24, 0x19,
0x9f, 0xc4, 0x7e, 0xc2, 0xdb, 0xce, 0x55, 0xe7, 0x46, 0xd3, 0x6b, 0x89, 0x8a, 0x03, 0x8d, 0xb3,
0xb7, 0xa0, 0x99, 0x20, 0x29, 0x0f, 0xd3, 0x38, 0x1a, 0x4f, 0xdb, 0x15, 0xa2, 0x6b, 0x20, 0xb6,
0x2b, 0x20, 0x77, 0x08, 0x2b, 0xba, 0x87, 0x64, 0x1c, 0x85, 0x09, 0x67, 0xb7, 0x61, 0xbd, 0x17,
0x8c, 0x4f, 0x78, 0xdc, 0xa5, 0x8f, 0x47, 0x21, 0x1f, 0x45, 0x61, 0xd0, 0x6b, 0x3b, 0x57, 0xab,
0x37, 0xea, 0x1e, 0x13, 0x75, 0xf8, 0xc5, 0x47, 0xb2, 0x86, 0x5d, 0x87, 0x15, 0x1e, 0x0a, 0x9c,
0xf7, 0xe9, 0x2b, 0xd9, 0xd5, 0x72, 0x06, 0xe3, 0x07, 0xee, 0xdf, 0x3b, 0xb0, 0xfa, 0x20, 0x0c,
0xd2, 0xa7, 0xfe, 0x70, 0xc8, 0x53, 0x35, 0xa7, 0xeb, 0xb0, 0x72, 0x46, 0x00, 0xcd, 0xe9, 0x2c,
0x8a, 0xfb, 0x72, 0x46, 0xcb, 0x02, 0x3e, 0x90, 0xe8, 0xcc, 0x91, 0x55, 0x66, 0x8e, 0xac, 0x74,
0xb9, 0xaa, 0x33, 0x96, 0xeb, 0x3a, 0xac, 0xc4, 0xbc, 0x17, 0x9d, 0xf2, 0x78, 0xda, 0x3d, 0x0b,
0xc2, 0x7e, 0x74, 0xd6, 0xae, 0x5d, 0x75, 0x6e, 0xcc, 0x79, 0xcb, 0x0a, 0x7e, 0x4a, 0xa8, 0xbb,
0x0e, 0xcc, 0x9c, 0x85, 0x58, 0x37, 0x77, 0x00, 0x6b, 0x4f, 0xc2, 0x61, 0xd4, 0x7b, 0xf6, 0x53,
0xce, 0xae, 0xa4, 0xfb, 0x4a, 0x69, 0xf7, 0x1b, 0xb0, 0x6e, 0x77, 0x24, 0x07, 0xc0, 0xe1, 0xe2,
0xf6, 0x89, 0x1f, 0x0e, 0xb8, 0x6a, 0x52, 0x0d, 0xe1, 0x93, 0xd0, 0xea, 0x4d, 0xe2, 0x98, 0x87,
0x85, 0x31, 0xac, 0x48, 0x5c, 0x0f, 0xe2, 0x2d, 0x68, 0x86, 0xfc, 0x2c, 0x23, 0x93, 0x2c, 0x13,
0xf2, 0x33, 0x45, 0xe2, 0xb6, 0x61, 0x23, 0xdf, 0x8d, 0x1c, 0xc0, 0x77, 0x2b, 0xd0, 0x78, 0x1c,
0xfb, 0x61, 0xe2, 0xf7, 0x90, 0x8b, 0x59, 0x1b, 0x16, 0xd2, 0xe7, 0xdd, 0x13, 0x3f, 0x39, 0xa1,
0xee, 0xea, 0x9e, 0x2a, 0xb2, 0x0d, 0x98, 0xf7, 0x47, 0xd1, 0x24, 0x4c, 0xa9, 0x83, 0xaa, 0x27,
0x4b, 0xec, 0x1d, 0x58, 0x0d, 0x27, 0xa3, 0x6e, 0x2f, 0x0a, 0x8f, 0x83, 0x78, 0x24, 0x64, 0x81,
0xf6, 0x6b, 0xce, 0x2b, 0x56, 0xb0, 0x2b, 0x00, 0x47, 0xb8, 0x0e, 0xa2, 0x8b, 0x1a, 0x75, 0x61,
0x20, 0xcc, 0x85, 0xa6, 0x2c, 0xf1, 0x60, 0x70, 0x92, 0xb6, 0xe7, 0xa8, 0x21, 0x0b, 0xc3, 0x36,
0xd2, 0x60, 0xc4, 0xbb, 0x49, 0xea, 0x8f, 0xc6, 0xed, 0x79, 0x1a, 0x8d, 0x81, 0x50, 0x7d, 0x94,
0xfa, 0xc3, 0xee, 0x31, 0xe7, 0x49, 0x7b, 0x41, 0xd6, 0x6b, 0x84, 0xbd, 0x0d, 0xcb, 0x7d, 0x9e,
0xa4, 0x5d, 0xbf, 0xdf, 0x8f, 0x79, 0x92, 0xf0, 0xa4, 0xbd, 0x48, 0xdc, 0x98, 0x43, 0x71, 0xd5,
0xee, 0xf3, 0xd4, 0x58, 0x9d, 0x44, 0xee, 0x8e, 0xbb, 0x0f, 0xcc, 0x80, 0x77, 0x78, 0xea, 0x07,
0xc3, 0x84, 0xbd, 0x07, 0xcd, 0xd4, 0x20, 0x26, 0xe9, 0x6b, 0x6c, 0xb1, 0x9b, 0xa4, 0x36, 0x6e,
0x1a, 0x1f, 0x78, 0x16, 0x9d, 0x7b, 0x1f, 0x16, 0xef, 0x71, 0xbe, 0x1f, 0x8c, 0x82, 0x94, 0x6d,
0xc0, 0xdc, 0x71, 0xf0, 0x9c, 0x8b, 0xcd, 0xae, 0xee, 0x5d, 0xf0, 0x44, 0x91, 0x75, 0x60, 0x61,
0xcc, 0xe3, 0x1e, 0x57, 0xcb, 0xbf, 0x77, 0xc1, 0x53, 0xc0, 0xdd, 0x05, 0x98, 0x1b, 0xe2, 0xc7,
0xee, 0xf7, 0x2b, 0xd0, 0x38, 0xe4, 0xa1, 0x66, 0x22, 0x06, 0x35, 0x9c, 0x92, 0x64, 0x1c, 0xfa,
0xcd, 0xde, 0x84, 0x06, 0x4d, 0x33, 0x49, 0xe3, 0x20, 0x1c, 0x50, 0x63, 0x75, 0x0f, 0x10, 0x3a,
0x24, 0x84, 0xb5, 0xa0, 0xea, 0x8f, 0x52, 0xda, 0xc1, 0xaa, 0x87, 0x3f, 0x91, 0xc1, 0xc6, 0xfe,
0x74, 0x84, 0xbc, 0xa8, 0x77, 0xad, 0xe9, 0x35, 0x24, 0xb6, 0x87, 0xdb, 0x76, 0x13, 0xd6, 0x4c,
0x12, 0xd5, 0xfa, 0x1c, 0xb5, 0xbe, 0x6a, 0x50, 0xca, 0x4e, 0xae, 0xc3, 0x8a, 0xa2, 0x8f, 0xc5,
0x60, 0x69, 0x1f, 0xeb, 0xde, 0xb2, 0x84, 0xd5, 0x14, 0x6e, 0x40, 0xeb, 0x38, 0x08, 0xfd, 0x61,
0xb7, 0x37, 0x4c, 0x4f, 0xbb, 0x7d, 0x3e, 0x4c, 0x7d, 0xda, 0xd1, 0x39, 0x6f, 0x99, 0xf0, 0xed,
0x61, 0x7a, 0xba, 0x83, 0x28, 0x7b, 0x07, 0xea, 0xc7, 0x9c, 0x77, 0x69, 0x25, 0xda, 0x8b, 0x57,
0x9d, 0x1b, 0x8d, 0xad, 0x15, 0xb9, 0xf4, 0x6a, 0x75, 0xbd, 0xc5, 0x63, 0xf9, 0xcb, 0xfd, 0x63,
0x07, 0x9a, 0x62, 0xa9, 0xa4, 0x0a, 0xbd, 0x06, 0x4b, 0x6a, 0x44, 0x3c, 0x8e, 0xa3, 0x58, 0xb2,
0xbf, 0x0d, 0xb2, 0x4d, 0x68, 0x29, 0x60, 0x1c, 0xf3, 0x60, 0xe4, 0x0f, 0xb8, 0x94, 0xb7, 0x02,
0xce, 0xb6, 0xb2, 0x16, 0xe3, 0x68, 0x92, 0x0a, 0x25, 0xd6, 0xd8, 0x6a, 0xca, 0x41, 0x79, 0x88,
0x79, 0x36, 0x89, 0xfb, 0x1d, 0x07, 0x18, 0x0e, 0xeb, 0x71, 0x24, 0xaa, 0xe5, 0x2a, 0xe4, 0x77,
0xc0, 0x79, 0xe5, 0x1d, 0xa8, 0xcc, 0xda, 0x81, 0x6b, 0x30, 0x4f, 0x5d, 0xa2, 0xac, 0x56, 0x0b,
0xc3, 0x92, 0x75, 0xee, 0xf7, 0x1c, 0x68, 0xa2, 0xe6, 0x08, 0xf9, 0xf0, 0x20, 0x0a, 0xc2, 0x94,
0xdd, 0x06, 0x76, 0x3c, 0x09, 0xfb, 0x41, 0x38, 0xe8, 0xa6, 0xcf, 0x83, 0x7e, 0xf7, 0x68, 0x8a,
0x4d, 0xd0, 0x78, 0xf6, 0x2e, 0x78, 0x25, 0x75, 0xec, 0x1d, 0x68, 0x59, 0x68, 0x92, 0xc6, 0x62,
0x54, 0x7b, 0x17, 0xbc, 0x42, 0x0d, 0xca, 0x7f, 0x34, 0x49, 0xc7, 0x93, 0xb4, 0x1b, 0x84, 0x7d,
0xfe, 0x9c, 0xd6, 0x6c, 0xc9, 0xb3, 0xb0, 0xbb, 0xcb, 0xd0, 0x34, 0xbf, 0x73, 0x3f, 0x07, 0xad,
0x7d, 0x54, 0x0c, 0x61, 0x10, 0x0e, 0xee, 0x08, 0xe9, 0x45, 0x6d, 0x35, 0x9e, 0x1c, 0x3d, 0xe3,
0x53, 0xb9, 0x8f, 0xb2, 0x84, 0x22, 0x71, 0x12, 0x25, 0xa9, 0x5c, 0x17, 0xfa, 0xed, 0xfe, 0x8b,
0x03, 0x2b, 0xb8, 0xe8, 0x1f, 0xf9, 0xe1, 0x54, 0xad, 0xf8, 0x3e, 0x34, 0xb1, 0xa9, 0xc7, 0xd1,
0x1d, 0xa1, 0xf3, 0x84, 0x2c, 0xdf, 0x90, 0x8b, 0x94, 0xa3, 0xbe, 0x69, 0x92, 0xa2, 0x99, 0x9e,
0x7a, 0xd6, 0xd7, 0x28, 0x74, 0xa9, 0x1f, 0x0f, 0x78, 0x4a, 0xda, 0x50, 0x6a, 0x47, 0x10, 0xd0,
0x76, 0x14, 0x1e, 0xb3, 0xab, 0xd0, 0x4c, 0xfc, 0xb4, 0x3b, 0xe6, 0x31, 0xad, 0x1a, 0x09, 0x4e,
0xd5, 0x83, 0xc4, 0x4f, 0x0f, 0x78, 0x7c, 0x77, 0x9a, 0xf2, 0xce, 0xe7, 0x61, 0xb5, 0xd0, 0x0b,
0xca, 0x6a, 0x36, 0x45, 0xfc, 0xc9, 0xd6, 0x61, 0xee, 0xd4, 0x1f, 0x4e, 0xb8, 0x54, 0xd2, 0xa2,
0xf0, 0x41, 0xe5, 0x7d, 0xc7, 0x7d, 0x1b, 0x5a, 0xd9, 0xb0, 0x25, 0xd3, 0x33, 0xa8, 0xe1, 0x0a,
0xca, 0x06, 0xe8, 0xb7, 0xfb, 0xdb, 0x8e, 0x20, 0xdc, 0x8e, 0x02, 0xad, 0xf0, 0x90, 0x10, 0xf5,
0xa2, 0x22, 0xc4, 0xdf, 0x33, 0x0d, 0xc2, 0xcf, 0x3e, 0x59, 0xf7, 0x3a, 0xac, 0x1a, 0x43, 0x78,
0xc9, 0x60, 0xbf, 0xe3, 0xc0, 0xea, 0x43, 0x7e, 0x26, 0x77, 0x5d, 0x8d, 0xf6, 0x7d, 0xa8, 0xa5,
0xd3, 0xb1, 0x70, 0xb2, 0x96, 0xb7, 0xae, 0xc9, 0x4d, 0x2b, 0xd0, 0xdd, 0x94, 0xc5, 0xc7, 0xd3,
0x31, 0xf7, 0xe8, 0x0b, 0xf7, 0x73, 0xd0, 0x30, 0x40, 0x76, 0x09, 0xd6, 0x9e, 0x3e, 0x78, 0xfc,
0x70, 0xf7, 0xf0, 0xb0, 0x7b, 0xf0, 0xe4, 0xee, 0x17, 0x77, 0x7f, 0xbd, 0xbb, 0x77, 0xe7, 0x70,
0xaf, 0x75, 0x81, 0x6d, 0x00, 0x7b, 0xb8, 0x7b, 0xf8, 0x78, 0x77, 0xc7, 0xc2, 0x1d, 0xb7, 0x03,
0xed, 0x87, 0xfc, 0xec, 0x69, 0x90, 0x86, 0x3c, 0x49, 0xec, 0xde, 0xdc, 0x9b, 0xc0, 0xcc, 0x21,
0xc8, 0x59, 0xb5, 0x61, 0x41, 0x5a, 0x1c, 0x65, 0x70, 0x65, 0xd1, 0x7d, 0x1b, 0xd8, 0x61, 0x30,
0x08, 0x3f, 0xe2, 0x49, 0xe2, 0x0f, 0xb4, 0x2a, 0x68, 0x41, 0x75, 0x94, 0x0c, 0xa4, 0x06, 0xc0,
0x9f, 0xee, 0xa7, 0x60, 0xcd, 0xa2, 0x93, 0x0d, 0xbf, 0x0e, 0xf5, 0x24, 0x18, 0x84, 0x7e, 0x3a,
0x89, 0xb9, 0x6c, 0x3a, 0x03, 0xdc, 0x7b, 0xb0, 0xfe, 0x65, 0x1e, 0x07, 0xc7, 0xd3, 0xf3, 0x9a,
0xb7, 0xdb, 0xa9, 0xe4, 0xdb, 0xd9, 0x85, 0x8b, 0xb9, 0x76, 0x64, 0xf7, 0x82, 0x11, 0xe5, 0x76,
0x2d, 0x7a, 0xa2, 0x60, 0x88, 0x65, 0xc5, 0x14, 0x4b, 0xf7, 0x09, 0xb0, 0xed, 0x28, 0x0c, 0x79,
0x2f, 0x3d, 0xe0, 0x3c, 0xce, 0x3c, 0xe7, 0x8c, 0xeb, 0x1a, 0x5b, 0x97, 0xe4, 0x3e, 0xe6, 0x65,
0x5d, 0xb2, 0x23, 0x83, 0xda, 0x98, 0xc7, 0x23, 0x6a, 0x78, 0xd1, 0xa3, 0xdf, 0xee, 0x45, 0x58,
0xb3, 0x9a, 0x95, 0x4e, 0xcf, 0xbb, 0x70, 0x71, 0x27, 0x48, 0x7a, 0xc5, 0x0e, 0xdb, 0xb0, 0x30,
0x9e, 0x1c, 0x75, 0x33, 0x99, 0x52, 0x45, 0xf4, 0x05, 0xf2, 0x9f, 0xc8, 0xc6, 0x7e, 0xcf, 0x81,
0xda, 0xde, 0xe3, 0xfd, 0x6d, 0xd6, 0x81, 0xc5, 0x20, 0xec, 0x45, 0x23, 0x54, 0xbb, 0x62, 0xd2,
0xba, 0x3c, 0x53, 0x56, 0x5e, 0x87, 0x3a, 0x69, 0x6b, 0x74, 0x6f, 0xa4, 0x93, 0x9b, 0x01, 0xe8,
0x5a, 0xf1, 0xe7, 0xe3, 0x20, 0x26, 0xdf, 0x49, 0x79, 0x44, 0x35, 0xd2, 0x88, 0xc5, 0x0a, 0xf7,
0x7f, 0x6a, 0xb0, 0x20, 0x75, 0x35, 0xf5, 0xd7, 0x4b, 0x83, 0x53, 0x2e, 0x47, 0x22, 0x4b, 0x68,
0xe5, 0x62, 0x3e, 0x8a, 0x52, 0xde, 0xb5, 0xb6, 0xc1, 0x06, 0x91, 0xaa, 0x27, 0x1a, 0xea, 0x8e,
0x51, 0xeb, 0xd3, 0xc8, 0xea, 0x9e, 0x0d, 0xe2, 0x62, 0x21, 0xd0, 0x0d, 0xfa, 0x34, 0xa6, 0x9a,
0xa7, 0x8a, 0xb8, 0x12, 0x3d, 0x7f, 0xec, 0xf7, 0x82, 0x74, 0x2a, 0x85, 0x5b, 0x97, 0xb1, 0xed,
0x61, 0xd4, 0xf3, 0x87, 0xdd, 0x23, 0x7f, 0xe8, 0x87, 0x3d, 0x2e, 0xfd, 0x37, 0x1b, 0x44, 0x17,
0x4d, 0x0e, 0x49, 0x91, 0x09, 0x37, 0x2e, 0x87, 0xa2, 0xab, 0xd7, 0x8b, 0x46, 0xa3, 0x20, 0x45,
0xcf, 0x8e, 0xac, 0x7e, 0xd5, 0x33, 0x10, 0x9a, 0x89, 0x28, 0x9d, 0x89, 0xd5, 0xab, 0x8b, 0xde,
0x2c, 0x10, 0x5b, 0x41, 0xd7, 0x01, 0x15, 0xd2, 0xb3, 0xb3, 0x36, 0x88, 0x56, 0x32, 0x04, 0xf7,
0x61, 0x12, 0x26, 0x3c, 0x4d, 0x87, 0xbc, 0xaf, 0x07, 0xd4, 0x20, 0xb2, 0x62, 0x05, 0xbb, 0x0d,
0x6b, 0xc2, 0xd9, 0x4c, 0xfc, 0x34, 0x4a, 0x4e, 0x82, 0xa4, 0x9b, 0xa0, 0xdb, 0xd6, 0x24, 0xfa,
0xb2, 0x2a, 0xf6, 0x3e, 0x5c, 0xca, 0xc1, 0x31, 0xef, 0xf1, 0xe0, 0x94, 0xf7, 0xdb, 0x4b, 0xf4,
0xd5, 0xac, 0x6a, 0x76, 0x15, 0x1a, 0xe8, 0x63, 0x4f, 0xc6, 0x7d, 0x1f, 0xed, 0xf0, 0x32, 0xed,
0x83, 0x09, 0xb1, 0x77, 0x61, 0x69, 0xcc, 0x85, 0xb1, 0x3c, 0x49, 0x87, 0xbd, 0xa4, 0xbd, 0x42,
0x96, 0xac, 0x21, 0x85, 0x09, 0x39, 0xd7, 0xb3, 0x29, 0x90, 0x29, 0x7b, 0x09, 0x39, 0x5b, 0xfe,
0xb4, 0xdd, 0x22, 0x76, 0xcb, 0x00, 0x92, 0x91, 0x38, 0x38, 0xf5, 0x53, 0xde, 0x5e, 0x25, 0xde,
0x52, 0x45, 0xf7, 0xcf, 0x1c, 0x58, 0xdb, 0x0f, 0x92, 0x54, 0x32, 0xa1, 0x56, 0xc7, 0x6f, 0x42,
0x43, 0xb0, 0x5f, 0x37, 0x0a, 0x87, 0x53, 0xc9, 0x91, 0x20, 0xa0, 0x47, 0xe1, 0x70, 0xca, 0x3e,
0x01, 0x4b, 0x41, 0x68, 0x92, 0x08, 0x19, 0x6e, 0x2a, 0x90, 0x88, 0xde, 0x84, 0xc6, 0x78, 0x72,
0x34, 0x0c, 0x7a, 0x82, 0xa4, 0x2a, 0x5a, 0x11, 0x10, 0x11, 0xa0, 0x93, 0x24, 0x46, 0x22, 0x28,
0x6a, 0x44, 0xd1, 0x90, 0x18, 0x92, 0xb8, 0x77, 0x61, 0xdd, 0x1e, 0xa0, 0x54, 0x56, 0x9b, 0xb0,
0x28, 0x79, 0x3b, 0x69, 0x37, 0x68, 0x7d, 0x96, 0xe5, 0xfa, 0x48, 0x52, 0x4f, 0xd7, 0xbb, 0x7f,
0x51, 0x83, 0x35, 0x89, 0x6e, 0x0f, 0xa3, 0x84, 0x1f, 0x4e, 0x46, 0x23, 0x3f, 0x2e, 0x11, 0x1a,
0xe7, 0x1c, 0xa1, 0xa9, 0xd8, 0x42, 0x83, 0xac, 0x7c, 0xe2, 0x07, 0xa1, 0xf0, 0xf0, 0x84, 0xc4,
0x19, 0x08, 0xbb, 0x01, 0x2b, 0xbd, 0x61, 0x94, 0x08, 0xaf, 0xc7, 0x3c, 0x3e, 0xe5, 0xe1, 0xa2,
0x90, 0xcf, 0x95, 0x09, 0xb9, 0x29, 0xa4, 0xf3, 0x39, 0x21, 0x75, 0xa1, 0x89, 0x8d, 0x72, 0xa5,
0x73, 0x16, 0x84, 0x17, 0x66, 0x62, 0x38, 0x9e, 0xbc, 0x48, 0x08, 0xf9, 0x5b, 0x29, 0x13, 0x08,
0x3c, 0x9d, 0xa1, 0x4e, 0x33, 0xa8, 0xeb, 0x52, 0x20, 0x8a, 0x55, 0xec, 0x1e, 0x80, 0xe8, 0x8b,
0xcc, 0x38, 0x90, 0x19, 0x7f, 0xdb, 0xde, 0x11, 0x73, 0xed, 0x6f, 0x62, 0x61, 0x12, 0x73, 0x32,
0xe4, 0xc6, 0x97, 0xee, 0xc7, 0xd0, 0x30, 0xaa, 0xd8, 0x45, 0x58, 0xdd, 0x7e, 0xf4, 0xe8, 0x60,
0xd7, 0xbb, 0xf3, 0xf8, 0xc1, 0x97, 0x77, 0xbb, 0xdb, 0xfb, 0x8f, 0x0e, 0x77, 0x5b, 0x17, 0x10,
0xde, 0x7f, 0xb4, 0x7d, 0x67, 0xbf, 0x7b, 0xef, 0x91, 0xb7, 0xad, 0x60, 0x07, 0x6d, 0xbc, 0xb7,
0xfb, 0xd1, 0xa3, 0xc7, 0xbb, 0x16, 0x5e, 0x61, 0x2d, 0x68, 0xde, 0xf5, 0x76, 0xef, 0x6c, 0xef,
0x49, 0xa4, 0xca, 0xd6, 0xa1, 0x75, 0xef, 0xc9, 0xc3, 0x9d, 0x07, 0x0f, 0xef, 0x77, 0xb7, 0xef,
0x3c, 0xdc, 0xde, 0xdd, 0xdf, 0xdd, 0x69, 0xd5, 0xdc, 0xbf, 0x73, 0xe0, 0x22, 0x8d, 0xb2, 0x9f,
0x17, 0x88, 0xab, 0xd0, 0xe8, 0x45, 0xd1, 0x98, 0xa3, 0xfe, 0xd6, 0x2a, 0xda, 0x84, 0x90, 0xd9,
0x85, 0x42, 0x3c, 0x8e, 0xe2, 0x1e, 0x97, 0xf2, 0x00, 0x04, 0xdd, 0x43, 0x04, 0x99, 0x5d, 0x6e,
0xa7, 0xa0, 0x10, 0xe2, 0xd0, 0x10, 0x98, 0x20, 0xd9, 0x80, 0xf9, 0xa3, 0x98, 0xfb, 0xbd, 0x13,
0x29, 0x09, 0xb2, 0xc4, 0x3e, 0x99, 0x39, 0xe4, 0x3d, 0x5c, 0xed, 0x21, 0xef, 0x13, 0x87, 0x2c,
0x7a, 0x2b, 0x12, 0xdf, 0x96, 0xb0, 0x7b, 0x00, 0x1b, 0xf9, 0x19, 0x48, 0x89, 0x79, 0xcf, 0x90,
0x18, 0xe1, 0x1b, 0x77, 0x66, 0xef, 0x8f, 0x21, 0x3d, 0xff, 0xee, 0x40, 0x0d, 0xcd, 0xe7, 0x6c,
0x53, 0x6b, 0x7a, 0x44, 0x55, 0xcb, 0x23, 0xa2, 0xe0, 0x01, 0x9e, 0x29, 0x84, 0x42, 0x15, 0x46,
0xc7, 0x40, 0xb2, 0xfa, 0x98, 0xf7, 0x4e, 0x69, 0x4e, 0xba, 0x1e, 0x11, 0x64, 0x79, 0x74, 0x3c,
0xe9, 0x6b, 0xc9, 0xf2, 0xaa, 0xac, 0xea, 0xe8, 0xcb, 0x85, 0xac, 0x8e, 0xbe, 0x6b, 0xc3, 0x42,
0x10, 0x1e, 0x45, 0x93, 0xb0, 0x4f, 0x2c, 0xbe, 0xe8, 0xa9, 0x22, 0xaa, 0xca, 0x31, 0x89, 0x5e,
0x30, 0x52, 0x0c, 0x9d, 0x01, 0x2e, 0xc3, 0x83, 0x49, 0x42, 0xee, 0x82, 0xf6, 0x02, 0xdf, 0x83,
0x55, 0x03, 0x93, 0xab, 0xf9, 0x16, 0xcc, 0x8d, 0x11, 0x90, 0x4b, 0xa9, 0x94, 0x33, 0xf9, 0x19,
0xa2, 0xc6, 0x6d, 0xc1, 0xf2, 0x7d, 0x9e, 0x3e, 0x08, 0x8f, 0x23, 0xd5, 0xd2, 0x8f, 0xab, 0xb0,
0xa2, 0x21, 0xd9, 0xd0, 0x0d, 0x58, 0x09, 0xfa, 0x3c, 0x4c, 0x83, 0x74, 0xda, 0xb5, 0xce, 0x3f,
0x79, 0x18, 0xfd, 0x33, 0x7f, 0x18, 0xf8, 0x89, 0xf4, 0x00, 0x44, 0x81, 0x6d, 0xc1, 0x3a, 0x1a,
0x0f, 0x65, 0x0f, 0xf4, 0x16, 0x8b, 0x63, 0x58, 0x69, 0x1d, 0x8a, 0x37, 0xe2, 0x52, 0x7f, 0xeb,
0x4f, 0x84, 0x9f, 0x52, 0x56, 0x85, 0xab, 0x26, 0x5a, 0xc2, 0x29, 0xcf, 0x09, 0x03, 0xa3, 0x81,
0x42, 0x08, 0x68, 0x5e, 0x28, 0x9f, 0x7c, 0x08, 0xc8, 0x08, 0x23, 0x2d, 0x16, 0xc2, 0x48, 0xa8,
0x9c, 0xa6, 0x61, 0x8f, 0xf7, 0xbb, 0x69, 0xd4, 0x25, 0x25, 0x4a, 0xbb, 0xb3, 0xe8, 0xe5, 0x61,
0x0a, 0x78, 0xf1, 0x24, 0x0d, 0x79, 0x4a, 0x7a, 0x66, 0xd1, 0x53, 0x45, 0x94, 0x1f, 0x22, 0x11,
0x26, 0xa1, 0xee, 0xc9, 0x12, 0x3a, 0x9a, 0x93, 0x38, 0x48, 0xda, 0x4d, 0x42, 0xe9, 0x37, 0xfb,
0x34, 0x5c, 0x3c, 0xe2, 0x49, 0xda, 0x3d, 0xe1, 0x7e, 0x9f, 0xc7, 0xb4, 0xfb, 0x22, 0x3a, 0x25,
0xec, 0x77, 0x79, 0x25, 0xf6, 0x7d, 0xca, 0xe3, 0x24, 0x88, 0x42, 0xb2, 0xdc, 0x75, 0x4f, 0x15,
0xdd, 0x6f, 0x92, 0x3f, 0xac, 0xe3, 0x66, 0x4f, 0xc8, 0x98, 0xb3, 0xd7, 0xa0, 0x2e, 0xe6, 0x98,
0x9c, 0xf8, 0xd2, 0x45, 0x5f, 0x24, 0xe0, 0xf0, 0xc4, 0x47, 0x8d, 0x60, 0x2d, 0x9b, 0x08, 0x44,
0x36, 0x08, 0xdb, 0x13, 0xab, 0x76, 0x0d, 0x96, 0x55, 0x44, 0x2e, 0xe9, 0x0e, 0xf9, 0x71, 0xaa,
0x8e, 0xd7, 0xe1, 0x64, 0x84, 0xdd, 0x25, 0xfb, 0xfc, 0x38, 0x75, 0x1f, 0xc2, 0xaa, 0x94, 0xe1,
0x47, 0x63, 0xae, 0xba, 0xfe, 0x6c, 0x99, 0x75, 0x6b, 0x6c, 0xad, 0xd9, 0x42, 0x4f, 0x31, 0x82,
0x9c, 0xc9, 0x73, 0x3d, 0x60, 0xa6, 0x4e, 0x90, 0x0d, 0x4a, 0x13, 0xa3, 0x0e, 0xf1, 0x72, 0x3a,
0x16, 0x86, 0xeb, 0x93, 0x4c, 0x7a, 0x3d, 0xd4, 0x04, 0x42, 0x03, 0xaa, 0xa2, 0xfb, 0x7d, 0x07,
0xd6, 0xa8, 0x35, 0x65, 0x9f, 0xf5, 0xc9, 0xef, 0xd5, 0x87, 0xd9, 0xec, 0x99, 0x81, 0x8d, 0x75,
0x98, 0x33, 0x75, 0xad, 0x28, 0xfc, 0xe4, 0x67, 0xd9, 0x5a, 0xe1, 0x2c, 0xfb, 0x63, 0x07, 0x56,
0x85, 0x32, 0x4c, 0xfd, 0x74, 0x92, 0xc8, 0xe9, 0xff, 0x32, 0x2c, 0x09, 0x3b, 0x25, 0xc5, 0x49,
0x0e, 0x74, 0x5d, 0x4b, 0x3e, 0xa1, 0x82, 0x78, 0xef, 0x82, 0x67, 0x13, 0xb3, 0xcf, 0x43, 0xd3,
0x0c, 0xab, 0xd2, 0x98, 0x1b, 0x5b, 0x97, 0xd5, 0x2c, 0x0b, 0x9c, 0xb3, 0x77, 0xc1, 0xb3, 0x3e,
0x60, 0x1f, 0x92, 0xb3, 0x11, 0x76, 0xa9, 0x59, 0x19, 0x98, 0xba, 0x5c, 0xa2, 0xc0, 0xf5, 0xe7,
0x06, 0xf9, 0xdd, 0x45, 0x98, 0x17, 0xde, 0xa5, 0x7b, 0x1f, 0x96, 0xac, 0x91, 0x5a, 0x67, 0xf4,
0xa6, 0x38, 0xa3, 0x17, 0x42, 0x3a, 0x95, 0x62, 0x48, 0xc7, 0xfd, 0x76, 0x15, 0x18, 0x72, 0x5b,
0x6e, 0x3b, 0xd1, 0xbd, 0x8d, 0xfa, 0xd6, 0x61, 0xa5, 0xe9, 0x99, 0x10, 0xbb, 0x09, 0xcc, 0x28,
0xaa, 0xa8, 0x97, 0xb0, 0x1b, 0x25, 0x35, 0xa8, 0xe0, 0xa4, 0x61, 0x95, 0x26, 0x50, 0x1e, 0xcb,
0xc4, 0xbe, 0x95, 0xd6, 0xa1, 0x69, 0x18, 0x4f, 0x92, 0x13, 0x74, 0xbf, 0xd5, 0x71, 0x46, 0x95,
0xf3, 0x0c, 0x32, 0x7f, 0x2e, 0x83, 0x2c, 0xe4, 0x19, 0xc4, 0x74, 0xa8, 0x17, 0x2d, 0x87, 0x1a,
0x1d, 0xb9, 0x11, 0xba, 0x7f, 0xe9, 0xb0, 0xd7, 0x1d, 0x61, 0xef, 0xf2, 0xf4, 0x62, 0x81, 0x6c,
0x13, 0x5a, 0xd2, 0x15, 0xc8, 0xbc, 0x76, 0xa0, 0x35, 0x2e, 0xe0, 0xa8, 0x79, 0xf1, 0x63, 0xd2,
0x00, 0x74, 0x82, 0x99, 0xf3, 0x32, 0xc0, 0xfd, 0x91, 0x03, 0x2d, 0xdc, 0x05, 0x8b, 0x53, 0x3f,
0x00, 0x12, 0x94, 0x57, 0x64, 0x54, 0x8b, 0xf6, 0x67, 0xe7, 0xd3, 0xf7, 0xa1, 0x4e, 0x0d, 0x46,
0x63, 0x1e, 0x4a, 0x36, 0x6d, 0xdb, 0x6c, 0x9a, 0xe9, 0xa8, 0xbd, 0x0b, 0x5e, 0x46, 0x6c, 0x30,
0xe9, 0x3f, 0x39, 0xd0, 0x90, 0xc3, 0xfc, 0xa9, 0xcf, 0xe9, 0x1d, 0x58, 0x44, 0x7e, 0x35, 0x0e,
0xc3, 0xba, 0x8c, 0xb6, 0x66, 0xe4, 0xa7, 0x93, 0x18, 0x8d, 0xab, 0x75, 0x46, 0xcf, 0xc3, 0x68,
0x29, 0x49, 0x1d, 0x27, 0xdd, 0x34, 0x18, 0x76, 0x55, 0xad, 0xbc, 0xe3, 0x28, 0xab, 0x42, 0xad,
0x94, 0xa4, 0xfe, 0x80, 0x4b, 0x23, 0x28, 0x0a, 0x6e, 0x1b, 0x36, 0xe4, 0x84, 0x72, 0x9e, 0xa5,
0xfb, 0xb7, 0x4d, 0xb8, 0x54, 0xa8, 0xd2, 0x97, 0x84, 0xf2, 0xf0, 0x39, 0x0c, 0x46, 0x47, 0x91,
0x76, 0xc3, 0x1d, 0xf3, 0x5c, 0x6a, 0x55, 0xb1, 0x01, 0x5c, 0x54, 0xd6, 0x1e, 0xd7, 0x34, 0xb3,
0xed, 0x15, 0x72, 0x53, 0xde, 0xb5, 0x79, 0x20, 0xdf, 0xa1, 0xc2, 0x4d, 0xb9, 0x2e, 0x6f, 0x8f,
0x9d, 0x40, 0x5b, 0xbb, 0x15, 0xd2, 0x00, 0x18, 0xae, 0x07, 0xf6, 0xf5, 0xce, 0x39, 0x7d, 0x59,
0x6e, 0xaa, 0x37, 0xb3, 0x35, 0x36, 0x85, 0x2b, 0xaa, 0x8e, 0x34, 0x7c, 0xb1, 0xbf, 0xda, 0x2b,
0xcd, 0x8d, 0x5c, 0x6c, 0xbb, 0xd3, 0x73, 0x1a, 0x66, 0x5f, 0x87, 0x8d, 0x33, 0x3f, 0x48, 0xd5,
0xb0, 0x0c, 0x57, 0x69, 0x8e, 0xba, 0xdc, 0x3a, 0xa7, 0xcb, 0xa7, 0xe2, 0x63, 0xcb, 0xec, 0xcd,
0x68, 0xb1, 0xf3, 0x0f, 0x0e, 0x2c, 0xdb, 0xed, 0x20, 0x9b, 0x4a, 0x75, 0xa0, 0xd4, 0xa2, 0x72,
0x0d, 0x73, 0x70, 0xf1, 0x24, 0x5b, 0x29, 0x3b, 0xc9, 0x9a, 0xe7, 0xc7, 0xea, 0x79, 0x41, 0x9e,
0xda, 0xab, 0x05, 0x79, 0xe6, 0xca, 0x82, 0x3c, 0x9d, 0xff, 0x76, 0x80, 0x15, 0x79, 0x89, 0xdd,
0x17, 0x47, 0xe9, 0x90, 0x0f, 0xa5, 0x4e, 0xfa, 0xc5, 0x57, 0xe3, 0x47, 0xb5, 0x76, 0xea, 0x6b,
0x14, 0x0c, 0x53, 0xe9, 0x98, 0x0e, 0xd4, 0x92, 0x57, 0x56, 0x95, 0x0b, 0x3b, 0xd5, 0xce, 0x0f,
0x3b, 0xcd, 0x9d, 0x1f, 0x76, 0x9a, 0xcf, 0x87, 0x9d, 0x3a, 0xbf, 0xeb, 0xc0, 0x5a, 0xc9, 0xa6,
0xff, 0xfc, 0x26, 0x8e, 0xdb, 0x64, 0xe9, 0x82, 0x8a, 0xdc, 0x26, 0x13, 0xec, 0xfc, 0x16, 0x2c,
0x59, 0x8c, 0xfe, 0xf3, 0xeb, 0x3f, 0xef, 0x03, 0x0a, 0x3e, 0xb3, 0xb0, 0xce, 0x7f, 0x54, 0x80,
0x15, 0x85, 0xed, 0xff, 0x75, 0x0c, 0xc5, 0x75, 0xaa, 0x96, 0xac, 0xd3, 0xff, 0xa9, 0x1d, 0x78,
0x07, 0x56, 0x65, 0x46, 0x81, 0x11, 0x40, 0x11, 0x1c, 0x53, 0xac, 0x40, 0x2f, 0xd8, 0x8e, 0xf9,
0x2d, 0x5a, 0x37, 0xd1, 0x86, 0x31, 0xcc, 0x85, 0xfe, 0xdc, 0x0d, 0x58, 0x17, 0x19, 0x0a, 0x77,
0x45, 0x53, 0xca, 0xae, 0xfc, 0xa9, 0x03, 0x17, 0x73, 0x15, 0xd9, 0xbd, 0xa9, 0x30, 0x1d, 0xb6,
0x3d, 0xb1, 0x41, 0x1c, 0xbf, 0x94, 0x23, 0x63, 0xfc, 0x82, 0xdb, 0x8a, 0x15, 0xb8, 0x3e, 0x93,
0xb0, 0x48, 0x2f, 0x56, 0xbd, 0xac, 0xca, 0xbd, 0x24, 0xf2, 0x28, 0x42, 0x3e, 0xcc, 0x0d, 0xfc,
0x58, 0x64, 0x3e, 0x98, 0x15, 0xd9, 0xc5, 0x8b, 0x3d, 0x64, 0x55, 0x44, 0x1f, 0xd1, 0x32, 0x53,
0xf6, 0x78, 0x4b, 0xeb, 0xdc, 0xbf, 0x76, 0x80, 0x7d, 0x69, 0xc2, 0xe3, 0x29, 0xdd, 0x9f, 0xea,
0x48, 0xcf, 0xa5, 0x7c, 0x94, 0x63, 0x7e, 0x3c, 0x39, 0xfa, 0x22, 0x9f, 0xaa, 0x5b, 0xf6, 0x4a,
0x76, 0xcb, 0xfe, 0x06, 0x00, 0x1e, 0xce, 0xf4, 0xa5, 0x2c, 0xf9, 0x66, 0xe1, 0x64, 0x24, 0x1a,
0x2c, 0xbd, 0x08, 0xaf, 0x9d, 0x7f, 0x11, 0x3e, 0x77, 0xde, 0x45, 0xf8, 0x87, 0xb0, 0x66, 0x8d,
0x5b, 0x6f, 0xab, 0xba, 0x1e, 0x76, 0x5e, 0x72, 0x3d, 0xfc, 0x9f, 0x0e, 0x54, 0xf7, 0xa2, 0xb1,
0x19, 0xd5, 0x74, 0xec, 0xa8, 0xa6, 0xb4, 0x25, 0x5d, 0x6d, 0x2a, 0xa4, 0x8a, 0xb1, 0x40, 0xb6,
0x09, 0xcb, 0xfe, 0x28, 0xc5, 0x43, 0xf9, 0x71, 0x14, 0x9f, 0xf9, 0x71, 0x5f, 0xec, 0xf5, 0xdd,
0x4a, 0xdb, 0xf1, 0x72, 0x35, 0x6c, 0x1d, 0xaa, 0x5a, 0xe9, 0x12, 0x01, 0x16, 0xd1, 0x71, 0xa3,
0x1b, 0x91, 0xa9, 0x8c, 0x27, 0xc8, 0x12, 0xb2, 0x92, 0xfd, 0xbd, 0x70, 0xa4, 0x85, 0xe8, 0x94,
0x55, 0xa1, 0x5d, 0xc3, 0xe5, 0x23, 0x32, 0x19, 0x08, 0x52, 0x65, 0xf7, 0xdf, 0x1c, 0x98, 0xa3,
0x15, 0x40, 0x61, 0x17, 0x1c, 0xae, 0xc3, 0x97, 0x34, 0xf3, 0x25, 0x2f, 0x0f, 0x33, 0xd7, 0xca,
0x46, 0xa9, 0xe8, 0x61, 0x9b, 0x19, 0x29, 0x57, 0xa1, 0x2e, 0x4a, 0x3a, 0xf3, 0x82, 0x48, 0x32,
0x90, 0x5d, 0x81, 0xda, 0x49, 0x34, 0x56, 0xde, 0x09, 0xa8, 0xe8, 0x7d, 0x34, 0xf6, 0x08, 0xcf,
0xc6, 0x83, 0xed, 0x89, 0xc1, 0x0b, 0x9b, 0x93, 0x87, 0xd1, 0xea, 0xea, 0x66, 0xcd, 0xc5, 0xc8,
0xa1, 0xee, 0x26, 0xac, 0x3c, 0x8c, 0xfa, 0xdc, 0x88, 0x38, 0xcd, 0xe4, 0x66, 0xf7, 0x5b, 0x0e,
0x2c, 0x2a, 0x62, 0x76, 0x03, 0x6a, 0xe8, 0x4a, 0xe4, 0x0e, 0x0a, 0xfa, 0xd6, 0x0e, 0xe9, 0x3c,
0xa2, 0x40, 0xdd, 0x4b, 0xf1, 0x88, 0xcc, 0xad, 0x54, 0xd1, 0x88, 0xcc, 0x6b, 0xd2, 0xc3, 0xcd,
0x39, 0x1b, 0x39, 0xd4, 0xfd, 0x4b, 0x07, 0x96, 0xac, 0x3e, 0xf0, 0xf0, 0x38, 0xf4, 0x93, 0x54,
0xde, 0x84, 0xc8, 0xed, 0x31, 0x21, 0x33, 0x06, 0x59, 0xb1, 0x63, 0x90, 0x3a, 0x3a, 0x56, 0x35,
0xa3, 0x63, 0xb7, 0xa1, 0x9e, 0xe5, 0x0c, 0xd5, 0x2c, 0x9d, 0x8a, 0x3d, 0xaa, 0xfb, 0xc8, 0x8c,
0x08, 0xdb, 0xe9, 0x45, 0xc3, 0x28, 0x96, 0x21, 0x78, 0x51, 0x70, 0x3f, 0x84, 0x86, 0x41, 0x8f,
0xc3, 0x08, 0x79, 0x7a, 0x16, 0xc5, 0xcf, 0x54, 0x28, 0x54, 0x16, 0xf5, 0xb5, 0x7b, 0x25, 0xbb,
0x76, 0x77, 0x7f, 0xe8, 0xc0, 0x12, 0xf2, 0x60, 0x10, 0x0e, 0x0e, 0xa2, 0x61, 0xd0, 0x9b, 0xd2,
0xde, 0x2b, 0x76, 0x93, 0x9a, 0x41, 0xf1, 0xa2, 0x0d, 0x23, 0x6f, 0xab, 0xb3, 0xa3, 0x14, 0x44,
0x5d, 0x46, 0x49, 0x45, 0x3e, 0x3f, 0xf2, 0x13, 0xc9, 0xfc, 0xd2, 0xc8, 0x59, 0x20, 0xca, 0x13,
0x02, 0xb1, 0x9f, 0xf2, 0xee, 0x28, 0x18, 0x0e, 0x03, 0x41, 0x2b, 0x5c, 0xa0, 0xb2, 0x2a, 0xec,
0xb3, 0x1f, 0x24, 0xfe, 0x51, 0x16, 0x66, 0xd6, 0x65, 0xf7, 0x07, 0x15, 0x68, 0x48, 0xf5, 0xbc,
0xdb, 0x1f, 0x70, 0x79, 0x07, 0x42, 0x4e, 0xa6, 0x56, 0x25, 0x06, 0xa2, 0xea, 0x2d, 0xb7, 0xd4,
0x40, 0xf2, 0x5b, 0x5e, 0x2d, 0x6e, 0xf9, 0xeb, 0x50, 0x47, 0xd6, 0x7b, 0x97, 0xfc, 0x5f, 0x71,
0x7f, 0x92, 0x01, 0xaa, 0x76, 0x8b, 0x6a, 0xe7, 0xb2, 0x5a, 0x02, 0x5e, 0x7a, 0x63, 0xf2, 0x3e,
0x34, 0x65, 0x33, 0xb4, 0x27, 0xa4, 0x39, 0x32, 0xe6, 0xb7, 0xf6, 0xcb, 0xb3, 0x28, 0xd5, 0x97,
0x5b, 0xea, 0xcb, 0xc5, 0xf3, 0xbe, 0x54, 0x94, 0x74, 0xbb, 0x2d, 0xd6, 0xe6, 0x7e, 0xec, 0x8f,
0x4f, 0x94, 0xc9, 0xeb, 0xeb, 0x94, 0x1d, 0x82, 0xd9, 0x26, 0xcc, 0xe1, 0x67, 0x4a, 0x93, 0x97,
0x0b, 0xa4, 0x20, 0x61, 0x37, 0x60, 0x8e, 0xf7, 0x07, 0x5c, 0x9d, 0xf0, 0x98, 0x7d, 0xd6, 0xc6,
0x3d, 0xf2, 0x04, 0x01, 0xaa, 0x07, 0x44, 0x73, 0xea, 0xc1, 0xb6, 0x02, 0xf3, 0x58, 0x7c, 0xd0,
0x77, 0xd7, 0x81, 0x3d, 0x14, 0x1c, 0x6d, 0xc6, 0xaf, 0xbf, 0x5d, 0x85, 0x86, 0x01, 0xa3, 0xa4,
0x0f, 0x70, 0xc0, 0xdd, 0x7e, 0xe0, 0x8f, 0x78, 0xca, 0x63, 0xc9, 0xc5, 0x39, 0x14, 0xe9, 0xfc,
0xd3, 0x41, 0x37, 0x9a, 0xa4, 0xdd, 0x3e, 0x1f, 0xc4, 0x5c, 0x18, 0x66, 0x34, 0x14, 0x16, 0x8a,
0x74, 0x23, 0xff, 0xb9, 0x49, 0x27, 0xf8, 0x21, 0x87, 0xaa, 0x68, 0xb4, 0x58, 0xa3, 0x5a, 0x16,
0x8d, 0x16, 0x2b, 0x92, 0xd7, 0x51, 0x73, 0x25, 0x3a, 0xea, 0x3d, 0xd8, 0x10, 0xda, 0x48, 0xca,
0x6d, 0x37, 0xc7, 0x26, 0x33, 0x6a, 0xd9, 0x26, 0xb4, 0x70, 0xcc, 0x8a, 0xc1, 0x93, 0xe0, 0x9b,
0x22, 0x3e, 0xe4, 0x78, 0x05, 0x1c, 0x69, 0x29, 0x50, 0x63, 0xd2, 0x8a, 0xfb, 0xb6, 0x02, 0x4e,
0xb4, 0xfe, 0x73, 0x9b, 0xb6, 0x2e, 0x69, 0x73, 0xb8, 0xbb, 0x04, 0x8d, 0xc3, 0x34, 0x1a, 0xab,
0x4d, 0x59, 0x86, 0xa6, 0x28, 0xca, 0xec, 0x86, 0xd7, 0xe0, 0x32, 0x71, 0xd1, 0xe3, 0x68, 0x1c,
0x0d, 0xa3, 0xc1, 0xf4, 0x70, 0x72, 0x94, 0xf4, 0xe2, 0x60, 0x8c, 0xa7, 0x21, 0xf7, 0x1f, 0x1d,
0x58, 0xb3, 0x6a, 0x65, 0xc8, 0xe8, 0xd3, 0x82, 0xa5, 0xf5, 0xb5, 0xb4, 0x60, 0xbc, 0x55, 0x43,
0x55, 0x0a, 0x42, 0x11, 0xca, 0x7b, 0x22, 0x6f, 0xaa, 0xef, 0xc0, 0x8a, 0x1a, 0x99, 0xfa, 0x50,
0x70, 0x61, 0xbb, 0xc8, 0x85, 0xf2, 0xfb, 0x65, 0xf9, 0x81, 0x6a, 0xe2, 0x57, 0xe4, 0xbd, 0x65,
0x9f, 0xe6, 0xa8, 0x62, 0x07, 0xfa, 0x66, 0xca, 0x3c, 0x41, 0xa8, 0x11, 0xf4, 0x34, 0x98, 0xb8,
0xbf, 0xef, 0x00, 0x64, 0xa3, 0x43, 0xc6, 0xc8, 0xd4, 0xbd, 0x48, 0xa5, 0x36, 0x54, 0xfb, 0x5b,
0xd0, 0xd4, 0x77, 0x2a, 0x99, 0x05, 0x69, 0x28, 0x0c, 0x9d, 0xbc, 0xeb, 0xb0, 0x32, 0x18, 0x46,
0x47, 0x64, 0x7e, 0x29, 0x5d, 0x26, 0x91, 0x39, 0x1e, 0xcb, 0x02, 0xbe, 0x27, 0xd1, 0xcc, 0xdc,
0xd4, 0x0c, 0x73, 0xe3, 0x7e, 0xa7, 0xa2, 0x23, 0xf1, 0xd9, 0x9c, 0x67, 0x4a, 0x19, 0xdb, 0x2a,
0x28, 0xc7, 0x19, 0x81, 0x6f, 0x8a, 0x92, 0x1d, 0x9c, 0x7b, 0x88, 0xff, 0x10, 0x96, 0x63, 0xa1,
0x7d, 0x94, 0x6a, 0xaa, 0xbd, 0x44, 0x35, 0x2d, 0xc5, 0x96, 0x4d, 0xfa, 0x24, 0xb4, 0xfc, 0xfe,
0x29, 0x8f, 0xd3, 0x80, 0x8e, 0x51, 0xe4, 0x10, 0x08, 0x85, 0xba, 0x62, 0xe0, 0x64, 0xa7, 0xaf,
0xc3, 0x8a, 0xcc, 0xab, 0xd1, 0x94, 0x32, 0x17, 0x34, 0x83, 0x91, 0xd0, 0xfd, 0x73, 0x15, 0xf4,
0xb7, 0xf7, 0x70, 0xf6, 0x8a, 0x98, 0xb3, 0xab, 0xe4, 0x66, 0xf7, 0x09, 0x19, 0x80, 0xef, 0xab,
0xb3, 0x5a, 0xd5, 0xb8, 0xe3, 0xee, 0xcb, 0x0b, 0x13, 0x7b, 0x49, 0x6b, 0xaf, 0xb2, 0xa4, 0xee,
0x8f, 0x1c, 0x58, 0xd8, 0x8b, 0xc6, 0x7b, 0xf2, 0xb6, 0x9f, 0x04, 0x41, 0x67, 0xad, 0xa9, 0xe2,
0x4b, 0xf2, 0x00, 0x4a, 0xed, 0xf0, 0x52, 0xde, 0x0e, 0xff, 0x2a, 0xbc, 0x46, 0x91, 0x82, 0x38,
0x1a, 0x47, 0x31, 0x0a, 0xa3, 0x3f, 0x14, 0x46, 0x37, 0x0a, 0xd3, 0x13, 0xa5, 0xc6, 0x5e, 0x46,
0x42, 0x47, 0x32, 0x3c, 0x4a, 0x08, 0x47, 0x59, 0xfa, 0x0d, 0x42, 0xbb, 0x15, 0x2b, 0xdc, 0xcf,
0x42, 0x9d, 0x1c, 0x5f, 0x9a, 0xd6, 0x3b, 0x50, 0x3f, 0x89, 0xc6, 0xdd, 0x93, 0x20, 0x4c, 0x95,
0x70, 0x2f, 0x67, 0x1e, 0xe9, 0x1e, 0x2d, 0x88, 0x26, 0x70, 0x7f, 0x58, 0x83, 0x85, 0x07, 0xe1,
0x69, 0x14, 0xf4, 0xe8, 0x7e, 0x60, 0xc4, 0x47, 0x91, 0xca, 0xe1, 0xc3, 0xdf, 0xb8, 0x14, 0x94,
0xcf, 0x32, 0x4e, 0x65, 0x80, 0x5f, 0x15, 0xd1, 0xdc, 0xc7, 0x59, 0x9e, 0xad, 0x10, 0x1d, 0x03,
0x41, 0xa7, 0x3f, 0x36, 0x53, 0x92, 0x65, 0x29, 0x4b, 0x82, 0x9c, 0x33, 0x92, 0x20, 0xe9, 0x36,
0x49, 0x64, 0x26, 0x10, 0x7f, 0x2d, 0x7a, 0xaa, 0x48, 0x87, 0x94, 0x98, 0x8b, 0x08, 0x0f, 0x39,
0x0e, 0x0b, 0xf2, 0x90, 0x62, 0x82, 0xe8, 0x5c, 0x88, 0x0f, 0x04, 0x8d, 0x50, 0xbe, 0x26, 0x84,
0x8e, 0x58, 0x3e, 0xab, 0xb9, 0x2e, 0x78, 0x3e, 0x07, 0xa3, 0x86, 0xee, 0x73, 0xad, 0x48, 0xc5,
0x1c, 0x40, 0xe4, 0x11, 0xe7, 0x71, 0xe3, 0x68, 0x23, 0x52, 0x8e, 0xd4, 0xd1, 0x06, 0x19, 0xc5,
0x1f, 0x0e, 0x8f, 0xfc, 0xde, 0x33, 0x4a, 0x5a, 0xa7, 0x0c, 0xa3, 0xba, 0x67, 0x83, 0x94, 0x6b,
0x90, 0xed, 0x26, 0xdd, 0x47, 0xd6, 0x3c, 0x13, 0x62, 0x5b, 0xd0, 0xa0, 0xe3, 0x9c, 0xdc, 0xcf,
0x65, 0xda, 0xcf, 0x96, 0x79, 0xde, 0xa3, 0x1d, 0x35, 0x89, 0xcc, 0x3b, 0x8b, 0x15, 0xfb, 0xce,
0x42, 0x28, 0x4d, 0x79, 0xd5, 0xd3, 0xa2, 0xde, 0x32, 0x00, 0xad, 0xa9, 0x5c, 0x30, 0x41, 0xb0,
0x4a, 0x04, 0x16, 0x86, 0x52, 0x8b, 0x87, 0x90, 0xb1, 0x1f, 0xf4, 0xdb, 0x4c, 0x48, 0xad, 0x2a,
0xbb, 0x29, 0xb0, 0x3b, 0xfd, 0xbe, 0xe4, 0x26, 0x7d, 0x58, 0xcd, 0xf8, 0xc0, 0xb1, 0xf8, 0xa0,
0x64, 0x3f, 0x2a, 0xe5, 0xfb, 0xf1, 0xd2, 0x51, 0xbb, 0xbb, 0xd0, 0x38, 0x30, 0x52, 0xad, 0x89,
0x2d, 0x55, 0x92, 0xb5, 0x64, 0x65, 0x03, 0x31, 0x86, 0x53, 0x31, 0x87, 0xe3, 0xfe, 0x12, 0xb0,
0xfd, 0x20, 0x49, 0xf5, 0xe8, 0xb3, 0xdc, 0x6e, 0x15, 0x51, 0xc8, 0xd2, 0xa3, 0x1a, 0x12, 0xa3,
0xb4, 0xa5, 0x3b, 0x22, 0xaf, 0x2a, 0x3f, 0xed, 0x4d, 0x58, 0x0c, 0x04, 0x94, 0x97, 0x42, 0x45,
0xa9, 0xeb, 0xdd, 0xa7, 0xb0, 0x26, 0x41, 0xd3, 0x82, 0xdb, 0xf3, 0x76, 0xce, 0xdb, 0xad, 0x4a,
0x71, 0xb7, 0xdc, 0x1f, 0x38, 0xb0, 0x20, 0x17, 0x07, 0xe9, 0x0b, 0x69, 0xea, 0x75, 0xcf, 0xc2,
0xca, 0x13, 0x94, 0x8b, 0x12, 0x58, 0x2d, 0x93, 0x40, 0x06, 0xb5, 0xb1, 0x9f, 0x9e, 0xd0, 0xd1,
0xab, 0xee, 0xd1, 0x6f, 0xd6, 0x12, 0xe1, 0x00, 0x21, 0xe9, 0x14, 0x0a, 0x28, 0xcb, 0xd1, 0x17,
0x06, 0xa5, 0x80, 0xa3, 0x0b, 0x4d, 0xd9, 0x18, 0x02, 0xd7, 0xd7, 0x28, 0x32, 0x4f, 0x2c, 0x83,
0xb3, 0x15, 0x97, 0x4d, 0xe4, 0x57, 0x5c, 0x92, 0x7a, 0xba, 0xde, 0xed, 0x40, 0x7b, 0x87, 0x0f,
0x79, 0xca, 0xef, 0x0c, 0x87, 0xf9, 0xf6, 0x5f, 0x83, 0xcb, 0x25, 0x75, 0xd2, 0xe5, 0xba, 0x07,
0xab, 0x3b, 0xfc, 0x68, 0x32, 0xd8, 0xe7, 0xa7, 0xd9, 0x4d, 0x28, 0x83, 0x5a, 0x72, 0x12, 0x9d,
0x49, 0xee, 0xa0, 0xdf, 0xec, 0x0d, 0x80, 0x21, 0xd2, 0x74, 0x93, 0x31, 0xef, 0xa9, 0xd4, 0x5c,
0x42, 0x0e, 0xc7, 0xbc, 0xe7, 0xbe, 0x07, 0xcc, 0x6c, 0x47, 0x4e, 0x01, 0xb5, 0xd8, 0xe4, 0xa8,
0x9b, 0x4c, 0x93, 0x94, 0x8f, 0x54, 0xce, 0xb1, 0x09, 0xb9, 0xd7, 0xa1, 0x79, 0xe0, 0x4f, 0x3d,
0xfe, 0x0d, 0xf9, 0x52, 0x00, 0x4f, 0xfd, 0xfe, 0x14, 0x45, 0x45, 0x9f, 0xfa, 0xa9, 0xda, 0xfd,
0xaf, 0x0a, 0xcc, 0x0b, 0x4a, 0x6c, 0xb5, 0xcf, 0x93, 0x34, 0x08, 0xc5, 0x3d, 0x9f, 0x6c, 0xd5,
0x80, 0x0a, 0xbc, 0x51, 0x29, 0xe1, 0x0d, 0xe9, 0x6b, 0xab, 0x34, 0x47, 0xc9, 0x04, 0x16, 0x86,
0x1c, 0x9b, 0x65, 0x57, 0x88, 0x63, 0x67, 0x06, 0xe4, 0xc2, 0x40, 0x99, 0xae, 0x14, 0xe3, 0x53,
0x6c, 0x2f, 0xd9, 0xc1, 0x84, 0x4a, 0x35, 0xf2, 0x82, 0xe0, 0x9a, 0x82, 0x46, 0x2e, 0x68, 0xde,
0xc5, 0x57, 0xd0, 0xbc, 0xc2, 0x01, 0x7f, 0x99, 0xe6, 0x85, 0x57, 0xd0, 0xbc, 0x2e, 0x83, 0xd6,
0x3d, 0xce, 0x3d, 0x8e, 0x36, 0x5d, 0xb1, 0xd3, 0x77, 0x1d, 0x68, 0x49, 0x77, 0x44, 0xd7, 0xb1,
0xb7, 0x2c, 0xdf, 0xa5, 0x34, 0x19, 0xf1, 0x1a, 0x2c, 0x91, 0x47, 0xa1, 0xe3, 0x5d, 0x32, 0x38,
0x67, 0x81, 0x38, 0x0f, 0x75, 0x29, 0x31, 0x0a, 0x86, 0x72, 0x53, 0x4c, 0x48, 0x85, 0xcc, 0xf0,
0xe4, 0x4f, 0x5b, 0xe2, 0x78, 0xba, 0xec, 0xfe, 0x8d, 0x03, 0xab, 0xc6, 0x80, 0x25, 0x17, 0x7e,
0x08, 0x2a, 0xfb, 0x42, 0x84, 0xc5, 0x84, 0x30, 0x5d, 0xb2, 0x5d, 0xab, 0xec, 0x33, 0x8b, 0x98,
0x36, 0xd3, 0x9f, 0xd2, 0x00, 0x93, 0xc9, 0x48, 0x6a, 0x25, 0x13, 0x42, 0x46, 0x3a, 0xe3, 0xfc,
0x99, 0x26, 0xa9, 0x0a, 0xc5, 0x65, 0x62, 0x74, 0xb9, 0x8e, 0x9e, 0x90, 0x26, 0x12, 0xf9, 0x64,
0x36, 0xe8, 0xfe, 0xb3, 0x03, 0x6b, 0xc2, 0xa5, 0x95, 0x07, 0x06, 0x9d, 0x29, 0x3e, 0x2f, 0x7c,
0x78, 0x21, 0x91, 0x7b, 0x17, 0x3c, 0x59, 0x66, 0x9f, 0x79, 0x45, 0x37, 0x5c, 0x27, 0x55, 0xcc,
0xd8, 0x8b, 0x6a, 0xd9, 0x5e, 0xbc, 0x64, 0xa5, 0xcb, 0xc2, 0x40, 0x73, 0xa5, 0x61, 0xa0, 0xbb,
0x0b, 0x30, 0x97, 0xf4, 0xa2, 0x31, 0x77, 0x37, 0x60, 0xdd, 0x9e, 0x9c, 0x54, 0x41, 0xdf, 0x73,
0xa0, 0x7d, 0x4f, 0x04, 0x45, 0x83, 0x70, 0xb0, 0x17, 0x24, 0x69, 0x14, 0xeb, 0xa7, 0x31, 0x57,
0x00, 0x92, 0xd4, 0x8f, 0x53, 0x91, 0xf4, 0x26, 0x83, 0x34, 0x19, 0x82, 0x63, 0xe4, 0x61, 0x5f,
0xd4, 0x8a, 0xbd, 0xd1, 0x65, 0xdc, 0x18, 0x32, 0x1b, 0xdd, 0xe8, 0xf8, 0x38, 0xe1, 0xda, 0xe9,
0x36, 0x31, 0x3c, 0xb7, 0xa3, 0xc4, 0xe3, 0x49, 0x95, 0x9f, 0x92, 0xaa, 0x15, 0xde, 0x6c, 0x0e,
0x75, 0xff, 0xca, 0x81, 0x95, 0x6c, 0x90, 0xbb, 0x08, 0xda, 0xda, 0x41, 0xda, 0xb3, 0x4c, 0x3b,
0xa8, 0xf0, 0x51, 0x80, 0x06, 0x4e, 0x8e, 0xcd, 0x40, 0x48, 0x62, 0x65, 0x29, 0x9a, 0xa8, 0x04,
0x43, 0x13, 0x12, 0xf9, 0x01, 0x29, 0x7e, 0x2d, 0xb2, 0x0b, 0x65, 0x89, 0x72, 0x16, 0x47, 0x29,
0x7d, 0x35, 0x2f, 0xdc, 0x79, 0x59, 0x54, 0xf6, 0x69, 0x81, 0x50, 0xfc, 0xe9, 0xfe, 0x81, 0x03,
0x97, 0x4b, 0x16, 0x57, 0x4a, 0xc6, 0x0e, 0xac, 0x1e, 0xeb, 0x4a, 0xb5, 0x00, 0x42, 0x3c, 0x36,
0x54, 0x14, 0xdf, 0x9e, 0xb4, 0x57, 0xfc, 0x00, 0x9d, 0x7b, 0x8a, 0x7a, 0x89, 0x25, 0xb5, 0x12,
0x6f, 0x8a, 0x15, 0x5b, 0x7f, 0x58, 0x85, 0x65, 0x71, 0xbb, 0x23, 0x1e, 0xa9, 0xf2, 0x98, 0x7d,
0x04, 0x0b, 0xf2, 0x91, 0x31, 0xbb, 0x28, 0xbb, 0xb5, 0x9f, 0x35, 0x77, 0x36, 0xf2, 0xb0, 0xe4,
0x9d, 0xb5, 0xdf, 0xf9, 0xd1, 0xbf, 0xfe, 0x51, 0x65, 0x89, 0x35, 0x6e, 0x9d, 0xbe, 0x7b, 0x6b,
0xc0, 0xc3, 0x04, 0xdb, 0xf8, 0x0d, 0x80, 0xec, 0xf9, 0x2d, 0x6b, 0x6b, 0x37, 0x25, 0xf7, 0xae,
0xb8, 0x73, 0xb9, 0xa4, 0x46, 0xb6, 0x7b, 0x99, 0xda, 0x5d, 0x73, 0x97, 0xb1, 0xdd, 0x20, 0x0c,
0x52, 0xf1, 0x16, 0xf7, 0x03, 0x67, 0x93, 0xf5, 0xa1, 0x69, 0xbe, 0xae, 0x65, 0xea, 0xc0, 0x5f,
0xf2, 0xb6, 0xb7, 0xf3, 0x5a, 0x69, 0x9d, 0x8a, 0x76, 0x50, 0x1f, 0x17, 0xdd, 0x16, 0xf6, 0x31,
0x21, 0x8a, 0xac, 0x97, 0x21, 0x2c, 0xdb, 0x8f, 0x68, 0xd9, 0xeb, 0x86, 0x58, 0x17, 0x9e, 0xf0,
0x76, 0xde, 0x98, 0x51, 0x2b, 0xfb, 0x7a, 0x83, 0xfa, 0xba, 0xe4, 0x32, 0xec, 0xab, 0x47, 0x34,
0xea, 0x09, 0xef, 0x07, 0xce, 0xe6, 0xd6, 0xb7, 0xae, 0x40, 0x5d, 0x87, 0xe8, 0xd8, 0xd7, 0x61,
0xc9, 0xba, 0x7e, 0x63, 0x6a, 0x1a, 0x65, 0xb7, 0x75, 0x9d, 0xd7, 0xcb, 0x2b, 0x65, 0xc7, 0x57,
0xa8, 0xe3, 0x36, 0xdb, 0xc0, 0x8e, 0xe5, 0xfd, 0xd5, 0x2d, 0xba, 0x74, 0x14, 0x19, 0x91, 0xcf,
0xc4, 0x3c, 0xb3, 0x2b, 0x33, 0x6b, 0x9e, 0x85, 0x2b, 0x36, 0x6b, 0x9e, 0xc5, 0x7b, 0x36, 0xf7,
0x75, 0xea, 0x6e, 0x83, 0xad, 0x9b, 0xdd, 0xe9, 0xd0, 0x19, 0xa7, 0x1c, 0x56, 0xf3, 0x8d, 0x2d,
0x7b, 0x43, 0x33, 0x56, 0xd9, 0xdb, 0x5b, 0xcd, 0x22, 0xc5, 0x07, 0xb8, 0x6e, 0x9b, 0xba, 0x62,
0x8c, 0xb6, 0xcf, 0x7c, 0x62, 0xcb, 0xbe, 0x0a, 0x75, 0xfd, 0xa0, 0x8c, 0x5d, 0x32, 0x5e, 0xf1,
0x99, 0xaf, 0xdc, 0x3a, 0xed, 0x62, 0x45, 0x19, 0x63, 0x98, 0x2d, 0x23, 0x63, 0xec, 0xc3, 0x45,
0xe9, 0x54, 0x1f, 0xf1, 0x9f, 0x64, 0x26, 0x25, 0x2f, 0x83, 0x6f, 0x3b, 0xec, 0x43, 0x58, 0x54,
0xef, 0xf4, 0xd8, 0x46, 0xf9, 0x7b, 0xc3, 0xce, 0xa5, 0x02, 0x2e, 0xb5, 0xc7, 0x1d, 0x80, 0xec,
0x8d, 0x99, 0x96, 0xb3, 0xc2, 0xcb, 0x37, 0xbd, 0x88, 0x25, 0x0f, 0xd2, 0x06, 0xf4, 0xa2, 0xce,
0x7e, 0xc2, 0xc6, 0xde, 0xcc, 0xe8, 0x4b, 0x1f, 0xb7, 0xbd, 0xa4, 0x41, 0x77, 0x83, 0xd6, 0xae,
0xc5, 0x48, 0x70, 0x43, 0x7e, 0xa6, 0xb2, 0xb9, 0x77, 0xa0, 0x61, 0xbc, 0x5b, 0x63, 0xaa, 0x85,
0xe2, 0x9b, 0xb7, 0x4e, 0xa7, 0xac, 0x4a, 0x0e, 0xf7, 0x0b, 0xb0, 0x64, 0x3d, 0x40, 0xd3, 0x92,
0x51, 0xf6, 0xbc, 0x4d, 0x4b, 0x46, 0xf9, 0x9b, 0xb5, 0xaf, 0x40, 0xc3, 0x78, 0x2e, 0xc6, 0x8c,
0x3c, 0xb5, 0xdc, 0x43, 0x31, 0x3d, 0xa2, 0xb2, 0xd7, 0x65, 0xeb, 0x34, 0xdf, 0x65, 0xb7, 0x8e,
0xf3, 0xa5, 0x94, 0x66, 0x64, 0x92, 0xaf, 0xc3, 0xb2, 0xfd, 0x80, 0x4c, 0x4b, 0x55, 0xe9, 0x53,
0x34, 0x2d, 0x55, 0x33, 0x5e, 0x9d, 0x49, 0x86, 0xdc, 0x5c, 0xd3, 0x9d, 0xdc, 0xfa, 0x58, 0x5e,
0x5e, 0xbd, 0x60, 0x5f, 0x42, 0xd5, 0x21, 0x73, 0xcc, 0x59, 0xf6, 0x6c, 0xce, 0xce, 0x44, 0xd7,
0xdc, 0x5e, 0x48, 0x47, 0x77, 0x57, 0xa9, 0xf1, 0x06, 0xcb, 0x66, 0x20, 0xec, 0x01, 0xe5, 0x9a,
0x1b, 0xf6, 0xc0, 0x4c, 0x47, 0x37, 0xec, 0x81, 0x95, 0x92, 0x9e, 0xb7, 0x07, 0x69, 0x80, 0x6d,
0x84, 0xb0, 0x92, 0x4b, 0xd4, 0xd0, 0xc2, 0x52, 0x9e, 0xd9, 0xd6, 0xb9, 0xf2, 0xf2, 0xfc, 0x0e,
0x5b, 0xcd, 0x28, 0xf5, 0x72, 0x4b, 0x25, 0x22, 0xfe, 0x26, 0x34, 0xcd, 0x87, 0x3f, 0xda, 0x42,
0x94, 0x3c, 0x57, 0xd2, 0x16, 0xa2, 0xec, 0xa5, 0x90, 0xda, 0x5c, 0xd6, 0x34, 0xbb, 0xc1, 0xcd,
0xb5, 0xdf, 0x49, 0x64, 0x2a, 0xb3, 0xec, 0x01, 0x48, 0xa6, 0x32, 0x4b, 0x1f, 0x57, 0xa8, 0xcd,
0x65, 0x6b, 0xd6, 0x5c, 0x44, 0x64, 0x92, 0x7d, 0x05, 0x56, 0x8c, 0x2c, 0xa8, 0xc3, 0x69, 0xd8,
0xd3, 0x8c, 0x5a, 0xcc, 0xa0, 0xed, 0x94, 0x79, 0x9e, 0xee, 0x25, 0x6a, 0x7f, 0xd5, 0xb5, 0x26,
0x81, 0x4c, 0xba, 0x0d, 0x0d, 0x33, 0xc3, 0xea, 0x25, 0xed, 0x5e, 0x32, 0xaa, 0xcc, 0x74, 0xd1,
0xdb, 0x0e, 0xfb, 0x13, 0x07, 0x9a, 0x56, 0xbe, 0x92, 0x15, 0x7f, 0xcf, 0xb5, 0xd3, 0x36, 0xeb,
0xcc, 0x86, 0x5c, 0x8f, 0x06, 0xb9, 0xbf, 0xf9, 0x05, 0x6b, 0x11, 0x3e, 0xb6, 0x4e, 0x30, 0x37,
0xf3, 0xef, 0xc7, 0x5f, 0xe4, 0x09, 0xcc, 0x2c, 0xe3, 0x17, 0xb7, 0x1d, 0xf6, 0x81, 0xf8, 0x87,
0x04, 0x15, 0xb1, 0x60, 0x86, 0x22, 0xcd, 0x2f, 0x99, 0xf9, 0xf7, 0x00, 0x37, 0x9c, 0xdb, 0x0e,
0xfb, 0x9a, 0x78, 0x26, 0x2e, 0xbf, 0xa5, 0x95, 0x7f, 0xd5, 0xef, 0xdd, 0x6b, 0x34, 0x9b, 0x2b,
0xee, 0x65, 0x6b, 0x36, 0x79, 0x4b, 0x72, 0x47, 0x8c, 0x4e, 0xbe, 0xfe, 0xcf, 0x54, 0x62, 0xe1,
0x1f, 0x01, 0x66, 0x0f, 0x72, 0x24, 0x06, 0x29, 0xc9, 0x2d, 0xf6, 0x78, 0xc5, 0x66, 0xdc, 0x4d,
0x1a, 0xeb, 0x35, 0xf7, 0xcd, 0x99, 0x63, 0xbd, 0x45, 0x27, 0x52, 0x1c, 0xf1, 0x01, 0x40, 0x16,
0x90, 0x63, 0xb9, 0xf8, 0x93, 0xb6, 0x0a, 0xc5, 0x98, 0x9d, 0xcd, 0x83, 0x2a, 0x4c, 0x85, 0x2d,
0x7e, 0x55, 0x88, 0xaa, 0xa4, 0x4f, 0xf4, 0xe8, 0x8b, 0xa1, 0xb3, 0x4e, 0xa7, 0xac, 0xaa, 0x4c,
0x50, 0x55, 0xfb, 0xec, 0x09, 0x2c, 0xed, 0x47, 0xd1, 0xb3, 0xc9, 0x58, 0x07, 0xa4, 0xed, 0xf8,
0xcd, 0x9e, 0x9f, 0x9c, 0x74, 0x72, 0xb3, 0x70, 0xaf, 0x52, 0x53, 0x1d, 0xd6, 0x36, 0x9a, 0xba,
0xf5, 0x71, 0x16, 0xf0, 0x7b, 0xc1, 0x7c, 0x58, 0xd5, 0x1e, 0x80, 0x1e, 0x78, 0xc7, 0x6e, 0xc6,
0x8c, 0xbb, 0x15, 0xba, 0xb0, 0x7c, 0x32, 0x35, 0xda, 0x5b, 0x89, 0x6a, 0xf3, 0xb6, 0xc3, 0x0e,
0xa0, 0xb9, 0xc3, 0x7b, 0x51, 0x9f, 0xcb, 0x88, 0xcb, 0x5a, 0x36, 0x70, 0x1d, 0xaa, 0xe9, 0x2c,
0x59, 0xa0, 0xad, 0x13, 0xc7, 0xfe, 0x34, 0xe6, 0xdf, 0xb8, 0xf5, 0xb1, 0x8c, 0xe5, 0xbc, 0x50,
0x3a, 0x51, 0xc5, 0x9f, 0x2c, 0x9d, 0x98, 0x0b, 0x58, 0x59, 0x3a, 0xb1, 0x10, 0xb0, 0xb2, 0x96,
0x5a, 0xc5, 0xbf, 0xd8, 0x10, 0x56, 0x0b, 0x31, 0x2e, 0xed, 0x47, 0xcc, 0x8a, 0x8c, 0x75, 0xae,
0xce, 0x26, 0xb0, 0x7b, 0xdb, 0xb4, 0x7b, 0x3b, 0x84, 0xa5, 0x1d, 0x2e, 0x16, 0x4b, 0xdc, 0x7a,
0xe7, 0x9e, 0xa3, 0x99, 0x37, 0xe4, 0x79, 0xa5, 0x48, 0x75, 0xb6, 0xd1, 0xa3, 0x2b, 0x67, 0xf6,
0x55, 0x68, 0xdc, 0xe7, 0xa9, 0xba, 0xe6, 0xd6, 0xde, 0x58, 0xee, 0xde, 0xbb, 0x53, 0x72, 0x4b,
0x6e, 0xf3, 0x0c, 0xb5, 0x76, 0x8b, 0xf7, 0x07, 0x5c, 0xa8, 0xa7, 0x6e, 0xd0, 0x7f, 0xc1, 0x7e,
0x8d, 0x1a, 0xd7, 0x59, 0x33, 0x1b, 0xc6, 0xed, 0xa8, 0xd9, 0xf8, 0x4a, 0x0e, 0x2f, 0x6b, 0x39,
0x8c, 0xfa, 0xdc, 0x30, 0xff, 0x21, 0x34, 0x8c, 0x94, 0x2e, 0x2d, 0x40, 0xc5, 0xf4, 0x34, 0x2d,
0x40, 0x25, 0x19, 0x60, 0xee, 0x0d, 0xea, 0xc7, 0x65, 0x57, 0xb3, 0x7e, 0x44, 0xd6, 0x57, 0xd6,
0xd3, 0xad, 0x8f, 0xfd, 0x51, 0xfa, 0x82, 0x3d, 0xa5, 0xa7, 0x69, 0xe6, 0x55, 0x7e, 0xe6, 0x0d,
0xe6, 0x6f, 0xfd, 0xf5, 0x62, 0x19, 0x55, 0xb6, 0x87, 0x28, 0xba, 0x22, 0x2f, 0xe1, 0x33, 0x00,
0x87, 0x69, 0x34, 0xde, 0xf1, 0xf9, 0x28, 0x0a, 0x33, 0x5d, 0x9b, 0x5d, 0x57, 0x67, 0xfa, 0xcb,
0xb8, 0xb3, 0x66, 0x4f, 0x0d, 0x7f, 0xdc, 0xca, 0x84, 0x50, 0xcc, 0x35, 0xf3, 0x46, 0x5b, 0x2f,
0x48, 0xc9, 0xad, 0xf6, 0x6d, 0x07, 0xbd, 0xeb, 0x2c, 0xa2, 0xaa, 0xbd, 0xeb, 0x42, 0xb0, 0x56,
0xab, 0xbd, 0x92, 0xf0, 0xeb, 0x01, 0xd4, 0xb3, 0x10, 0xdd, 0xa5, 0x2c, 0x2d, 0xcf, 0x0a, 0xe8,
0x69, 0xab, 0x58, 0x08, 0x9c, 0xb9, 0x2d, 0x5a, 0x2a, 0x60, 0x8b, 0xb8, 0x54, 0x14, 0x0d, 0x0b,
0x60, 0x4d, 0x0c, 0x50, 0x9b, 0x78, 0xba, 0x80, 0x55, 0x33, 0x29, 0x09, 0x5e, 0x69, 0x69, 0x2e,
0x8d, 0xfd, 0x58, 0xe7, 0x6c, 0xe4, 0x56, 0x71, 0xf9, 0x8b, 0xaa, 0x79, 0x04, 0xab, 0x85, 0xc0,
0x85, 0x16, 0xe9, 0x59, 0xf1, 0x22, 0x2d, 0xd2, 0x33, 0x63, 0x1e, 0xee, 0x45, 0xea, 0x72, 0xc5,
0x05, 0xec, 0x32, 0x39, 0x0b, 0xd2, 0xde, 0xc9, 0x07, 0xce, 0xe6, 0xd1, 0x3c, 0xfd, 0xa3, 0xda,
0xa7, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x2f, 0xeb, 0x5e, 0xe3, 0x83, 0x4d, 0x00, 0x00,
}

@ -1129,11 +1129,10 @@ message PendingUpdate {
}
message OpenChannelRequest {
/// The pubkey of the node to open a channel with
bytes node_pubkey = 2 [json_name = "node_pubkey"];
/// The hex encoded pubkey of the node to open a channel with
/// The hex encoded pubkey of the node to open a channel with
string node_pubkey_string = 3 [json_name = "node_pubkey_string"];
/// The number of satoshis the wallet should commit to the channel
@ -1156,6 +1155,9 @@ message OpenChannelRequest {
/// The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size.
uint32 remote_csv_delay = 10 [json_name = "remote_csv_delay"];
/// The minimum number of confirmations each one of your outputs used for the funding transaction must satisfy.
int32 min_confs = 11 [json_name = "min_confs"];
}
message OpenStatusUpdate {
oneof update {

@ -2164,6 +2164,11 @@
"type": "integer",
"format": "int64",
"description": "/ The delay we require on the remote's commitment transaction. If this is not set, it will be scaled automatically with the channel size."
},
"min_confs": {
"type": "integer",
"format": "int32",
"description": "/ The minimum number of confirmations each one of your outputs used for the funding transaction must satisfy."
}
}
},

@ -676,10 +676,12 @@ func (n *NetworkHarness) WaitForTxBroadcast(ctx context.Context, txid chainhash.
// OpenChannel attempts to open a channel between srcNode and destNode with the
// passed channel funding parameters. If the passed context has a timeout, then
// if the timeout is reached before the channel pending notification is
// received, an error is returned.
// received, an error is returned. The confirmed boolean determines whether we
// should fund the channel with confirmed outputs or not.
func (n *NetworkHarness) OpenChannel(ctx context.Context,
srcNode, destNode *HarnessNode, amt btcutil.Amount,
pushAmt btcutil.Amount, private bool) (lnrpc.Lightning_OpenChannelClient, error) {
pushAmt btcutil.Amount,
private, confirmed bool) (lnrpc.Lightning_OpenChannelClient, error) {
// Wait until srcNode and destNode have the latest chain synced.
// Otherwise, we may run into a check within the funding manager that
@ -692,11 +694,17 @@ func (n *NetworkHarness) OpenChannel(ctx context.Context,
return nil, fmt.Errorf("Unable to sync destNode chain: %v", err)
}
minConfs := int32(0)
if confirmed {
minConfs = 1
}
openReq := &lnrpc.OpenChannelRequest{
NodePubkey: destNode.PubKey[:],
LocalFundingAmount: int64(amt),
PushSat: int64(pushAmt),
Private: private,
MinConfs: minConfs,
}
respStream, err := srcNode.OpenChannel(ctx, openReq)
@ -1104,12 +1112,26 @@ func (n *NetworkHarness) DumpLogs(node *HarnessNode) (string, error) {
}
// SendCoins attempts to send amt satoshis from the internal mining node to the
// targeted lightning node using a P2WKH address.
// targeted lightning node using a P2WKH address. 6 blocks are mined after in
// order to confirm the transaction.
func (n *NetworkHarness) SendCoins(ctx context.Context, amt btcutil.Amount,
target *HarnessNode) error {
return n.sendCoins(
ctx, amt, target, lnrpc.NewAddressRequest_WITNESS_PUBKEY_HASH,
true,
)
}
// SendCoinsUnconfirmed sends coins from the internal mining node to the target
// lightning node using a P2WPKH address. No blocks are mined after, so the
// transaction remains unconfirmed.
func (n *NetworkHarness) SendCoinsUnconfirmed(ctx context.Context,
amt btcutil.Amount, target *HarnessNode) error {
return n.sendCoins(
ctx, amt, target, lnrpc.NewAddressRequest_WITNESS_PUBKEY_HASH,
false,
)
}
@ -1120,14 +1142,16 @@ func (n *NetworkHarness) SendCoinsNP2WKH(ctx context.Context,
return n.sendCoins(
ctx, amt, target, lnrpc.NewAddressRequest_NESTED_PUBKEY_HASH,
true,
)
}
// sendCoins attempts to send amt satoshis from the internal mining node to the
// targeted lightning node.
// targeted lightning node. The confirmed boolean indicates whether the
// transaction that pays to the target should confirm.
func (n *NetworkHarness) sendCoins(ctx context.Context, amt btcutil.Amount,
target *HarnessNode,
addrType lnrpc.NewAddressRequest_AddressType) error {
target *HarnessNode, addrType lnrpc.NewAddressRequest_AddressType,
confirmed bool) error {
balReq := &lnrpc.WalletBalanceRequest{}
initialBalance, err := target.WalletBalance(ctx, balReq)
@ -1165,30 +1189,21 @@ func (n *NetworkHarness) sendCoins(ctx context.Context, amt btcutil.Amount,
return err
}
// Finally, generate 6 new blocks to ensure the output gains a
// sufficient number of confirmations.
// If the transaction should remain unconfirmed, then we'll wait until
// the target node's unconfirmed balance reflects the expected balance
// and exit.
if !confirmed {
expectedBalance := initialBalance.UnconfirmedBalance + int64(amt)
return target.WaitForBalance(expectedBalance, false)
}
// Otherwise, we'll generate 6 new blocks to ensure the output gains a
// sufficient number of confirmations and wait for the balance to
// reflect what's expected.
if _, err := n.Miner.Node.Generate(6); err != nil {
return err
}
// Pause until the nodes current wallet balances reflects the amount
// sent to it above.
// TODO(roasbeef): factor out into helper func
balanceTicker := time.Tick(time.Millisecond * 50)
balanceTimeout := time.After(time.Second * 30)
for {
select {
case <-balanceTicker:
currentBal, err := target.WalletBalance(ctx, balReq)
if err != nil {
return err
}
if currentBal.ConfirmedBalance == initialBalance.ConfirmedBalance+int64(amt) {
return nil
}
case <-balanceTimeout:
return fmt.Errorf("balances not synced after deadline")
}
}
expectedBalance := initialBalance.ConfirmedBalance + int64(amt)
return target.WaitForBalance(expectedBalance, true)
}

@ -895,6 +895,33 @@ func (hn *HarnessNode) WaitForBlockchainSync(ctx context.Context) error {
}
}
// WaitForBalance waits until the node sees the expected confirmed/unconfirmed
// balance within their wallet.
func (hn *HarnessNode) WaitForBalance(expectedBalance int64, confirmed bool) error {
ctx := context.Background()
req := &lnrpc.WalletBalanceRequest{}
doesBalanceMatch := func() bool {
balance, err := hn.WalletBalance(ctx, req)
if err != nil {
return false
}
if confirmed {
return balance.ConfirmedBalance == expectedBalance
}
return balance.UnconfirmedBalance == expectedBalance
}
err := WaitPredicate(doesBalanceMatch, 30*time.Second)
if err != nil {
return errors.New("balances not synced after deadline")
}
return nil
}
// fileExists reports whether the named file or directory exists.
// This function is taken from https://github.com/btcsuite/btcd
func fileExists(name string) bool {

@ -294,10 +294,18 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
if err != nil {
t.Fatalf("unable to query fee estimator: %v", err)
}
aliceChanReservation, err := alice.InitChannelReservation(
fundingAmount*2, fundingAmount, 0, feePerKw, feePerKw, bobPub,
bobAddr, chainHash, lnwire.FFAnnounceChannel,
)
aliceReq := &lnwallet.InitFundingReserveMsg{
ChainHash: chainHash,
NodeID: bobPub,
NodeAddr: bobAddr,
FundingAmount: fundingAmount,
Capacity: fundingAmount * 2,
CommitFeePerKw: feePerKw,
FundingFeePerKw: feePerKw,
PushMSat: 0,
Flags: lnwire.FFAnnounceChannel,
}
aliceChanReservation, err := alice.InitChannelReservation(aliceReq)
if err != nil {
t.Fatalf("unable to initialize funding reservation: %v", err)
}
@ -325,10 +333,18 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
// Bob does the same, generating his own contribution. He then also
// receives' Alice's contribution, and consumes that so we can continue
// the funding process.
bobChanReservation, err := bob.InitChannelReservation(
fundingAmount*2, fundingAmount, 0, feePerKw, feePerKw, alicePub,
aliceAddr, chainHash, lnwire.FFAnnounceChannel,
)
bobReq := &lnwallet.InitFundingReserveMsg{
ChainHash: chainHash,
NodeID: alicePub,
NodeAddr: aliceAddr,
FundingAmount: fundingAmount,
Capacity: fundingAmount * 2,
CommitFeePerKw: feePerKw,
FundingFeePerKw: feePerKw,
PushMSat: 0,
Flags: lnwire.FFAnnounceChannel,
}
bobChanReservation, err := bob.InitChannelReservation(bobReq)
if err != nil {
t.Fatalf("bob unable to init channel reservation: %v", err)
}
@ -481,11 +497,18 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness,
if err != nil {
t.Fatalf("unable to query fee estimator: %v", err)
}
_, err = alice.InitChannelReservation(
fundingAmount, fundingAmount, 0, feePerKw, feePerKw, bobPub,
bobAddr, chainHash, lnwire.FFAnnounceChannel,
)
if err != nil {
req := &lnwallet.InitFundingReserveMsg{
ChainHash: chainHash,
NodeID: bobPub,
NodeAddr: bobAddr,
FundingAmount: fundingAmount,
Capacity: fundingAmount,
CommitFeePerKw: feePerKw,
FundingFeePerKw: feePerKw,
PushMSat: 0,
Flags: lnwire.FFAnnounceChannel,
}
if _, err := alice.InitChannelReservation(req); err != nil {
t.Fatalf("unable to initialize funding reservation 1: %v", err)
}
@ -496,10 +519,18 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness,
if err != nil {
t.Fatalf("unable to create amt: %v", err)
}
failedReservation, err := alice.InitChannelReservation(
amt, amt, 0, feePerKw, feePerKw, bobPub, bobAddr, chainHash,
lnwire.FFAnnounceChannel,
)
failedReq := &lnwallet.InitFundingReserveMsg{
ChainHash: chainHash,
NodeID: bobPub,
NodeAddr: bobAddr,
FundingAmount: amt,
Capacity: amt,
CommitFeePerKw: feePerKw,
FundingFeePerKw: feePerKw,
PushMSat: 0,
Flags: lnwire.FFAnnounceChannel,
}
failedReservation, err := alice.InitChannelReservation(failedReq)
if err == nil {
t.Fatalf("not error returned, should fail on coin selection")
}
@ -524,19 +555,24 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness,
if err != nil {
t.Fatalf("unable to create amt: %v", err)
}
chanReservation, err := alice.InitChannelReservation(
fundingAmount, fundingAmount, 0, feePerKw, feePerKw, bobPub,
bobAddr, chainHash, lnwire.FFAnnounceChannel,
)
req := &lnwallet.InitFundingReserveMsg{
ChainHash: chainHash,
NodeID: bobPub,
NodeAddr: bobAddr,
FundingAmount: fundingAmount,
Capacity: fundingAmount,
CommitFeePerKw: feePerKw,
FundingFeePerKw: feePerKw,
PushMSat: 0,
Flags: lnwire.FFAnnounceChannel,
}
chanReservation, err := alice.InitChannelReservation(req)
if err != nil {
t.Fatalf("unable to initialize funding reservation: %v", err)
}
// Attempt to create another channel with 44 BTC, this should fail.
_, err = alice.InitChannelReservation(
fundingAmount, fundingAmount, 0, feePerKw, feePerKw, bobPub,
bobAddr, chainHash, lnwire.FFAnnounceChannel,
)
_, err = alice.InitChannelReservation(req)
if _, ok := err.(*lnwallet.ErrInsufficientFunds); !ok {
t.Fatalf("coin selection succeeded should have insufficient funds: %v",
err)
@ -565,10 +601,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness,
// attempting coin selection.
// Request to fund a new channel should now succeed.
_, err = alice.InitChannelReservation(fundingAmount, fundingAmount,
0, feePerKw, feePerKw, bobPub, bobAddr, chainHash,
lnwire.FFAnnounceChannel)
if err != nil {
if _, err := alice.InitChannelReservation(req); err != nil {
t.Fatalf("unable to initialize funding reservation: %v", err)
}
}
@ -612,10 +645,18 @@ func testReservationInitiatorBalanceBelowDustCancel(miner *rpctest.Harness,
feePerKw := lnwallet.SatPerKWeight(
numBTC * numBTC * btcutil.SatoshiPerBitcoin,
)
_, err = alice.InitChannelReservation(
fundingAmount, fundingAmount, 0, feePerKw, feePerKw, bobPub,
bobAddr, chainHash, lnwire.FFAnnounceChannel,
)
req := &lnwallet.InitFundingReserveMsg{
ChainHash: chainHash,
NodeID: bobPub,
NodeAddr: bobAddr,
FundingAmount: fundingAmount,
Capacity: fundingAmount,
CommitFeePerKw: feePerKw,
FundingFeePerKw: feePerKw,
PushMSat: 0,
Flags: lnwire.FFAnnounceChannel,
}
_, err = alice.InitChannelReservation(req)
switch {
case err == nil:
t.Fatalf("initialization should have failed due to " +
@ -685,10 +726,18 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
if err != nil {
t.Fatalf("unable to query fee estimator: %v", err)
}
aliceChanReservation, err := alice.InitChannelReservation(
fundingAmt, fundingAmt, pushAmt, feePerKw, feePerKw, bobPub,
bobAddr, chainHash, lnwire.FFAnnounceChannel,
)
aliceReq := &lnwallet.InitFundingReserveMsg{
ChainHash: chainHash,
NodeID: bobPub,
NodeAddr: bobAddr,
FundingAmount: fundingAmt,
Capacity: fundingAmt,
CommitFeePerKw: feePerKw,
FundingFeePerKw: feePerKw,
PushMSat: pushAmt,
Flags: lnwire.FFAnnounceChannel,
}
aliceChanReservation, err := alice.InitChannelReservation(aliceReq)
if err != nil {
t.Fatalf("unable to init channel reservation: %v", err)
}
@ -716,10 +765,18 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
// Next, Bob receives the initial request, generates a corresponding
// reservation initiation, then consume Alice's contribution.
bobChanReservation, err := bob.InitChannelReservation(
fundingAmt, 0, pushAmt, feePerKw, feePerKw, alicePub, aliceAddr,
chainHash, lnwire.FFAnnounceChannel,
)
bobReq := &lnwallet.InitFundingReserveMsg{
ChainHash: chainHash,
NodeID: alicePub,
NodeAddr: aliceAddr,
FundingAmount: 0,
Capacity: fundingAmt,
CommitFeePerKw: feePerKw,
FundingFeePerKw: feePerKw,
PushMSat: pushAmt,
Flags: lnwire.FFAnnounceChannel,
}
bobChanReservation, err := bob.InitChannelReservation(bobReq)
if err != nil {
t.Fatalf("unable to create bob reservation: %v", err)
}

@ -3,24 +3,24 @@ package lnwallet
import (
"bytes"
"crypto/sha256"
"errors"
"fmt"
"net"
"sync"
"sync/atomic"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/hdkeychain"
"github.com/btcsuite/btcutil/txsort"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/txsort"
"github.com/lightningnetwork/lnd/shachain"
)
@ -44,7 +44,7 @@ func (e *ErrInsufficientFunds) Error() string {
e.amountSelected)
}
// initFundingReserveReq is the first message sent to initiate the workflow
// InitFundingReserveMsg is the first message sent to initiate the workflow
// required to open a payment channel with a remote peer. The initial required
// parameters are configurable across channels. These parameters are to be
// chosen depending on the fee climate within the network, and time value of
@ -54,44 +54,48 @@ func (e *ErrInsufficientFunds) Error() string {
// pending reservations. Therefore, all channels in reservation limbo will be
// periodically timed out after an idle period in order to avoid "exhaustion"
// attacks.
type initFundingReserveMsg struct {
// chainHash denotes that chain to be used to ultimately open the
type InitFundingReserveMsg struct {
// ChainHash denotes that chain to be used to ultimately open the
// target channel.
chainHash *chainhash.Hash
ChainHash *chainhash.Hash
// nodeId is the ID of the remote node we would like to open a channel
// NodeID is the ID of the remote node we would like to open a channel
// with.
nodeID *btcec.PublicKey
NodeID *btcec.PublicKey
// nodeAddr is the address port that we used to either establish or
// NodeAddr is the address port that we used to either establish or
// accept the connection which led to the negotiation of this funding
// workflow.
nodeAddr net.Addr
NodeAddr net.Addr
// fundingAmount is the amount of funds requested for this channel.
fundingAmount btcutil.Amount
// FundingAmount is the amount of funds requested for this channel.
FundingAmount btcutil.Amount
// capacity is the total capacity of the channel which includes the
// Capacity is the total capacity of the channel which includes the
// amount of funds the remote party contributes (if any).
capacity btcutil.Amount
Capacity btcutil.Amount
// commitFeePerKw is the starting accepted satoshis/Kw fee for the set
// CommitFeePerKw is the starting accepted satoshis/Kw fee for the set
// of initial commitment transactions. In order to ensure timely
// confirmation, it is recommended that this fee should be generous,
// paying some multiple of the accepted base fee rate of the network.
commitFeePerKw SatPerKWeight
CommitFeePerKw SatPerKWeight
// fundingFeePerKw is the fee rate in sat/kw to use for the initial
// FundingFeePerKw is the fee rate in sat/kw to use for the initial
// funding transaction.
fundingFeePerKw SatPerKWeight
FundingFeePerKw SatPerKWeight
// pushMSat is the number of milli-satoshis that should be pushed over
// PushMSat is the number of milli-satoshis that should be pushed over
// the responder as part of the initial channel creation.
pushMSat lnwire.MilliSatoshi
PushMSat lnwire.MilliSatoshi
// flags are the channel flags specified by the initiator in the
// Flags are the channel flags specified by the initiator in the
// open_channel message.
flags lnwire.FundingFlag
Flags lnwire.FundingFlag
// MinConfs indicates the minimum number of confirmations that each
// output selected to fund the channel should satisfy.
MinConfs int32
// err is a channel in which all errors will be sent across. Will be
// nil if this initial set is successful.
@ -372,7 +376,7 @@ out:
select {
case m := <-l.msgChan:
switch msg := m.(type) {
case *initFundingReserveMsg:
case *InitFundingReserveMsg:
l.handleFundingReserveRequest(msg)
case *fundingReserveCancelMsg:
l.handleFundingCancelRequest(msg)
@ -412,36 +416,25 @@ out:
// transaction, and that the signature we record for our version of the
// commitment transaction is valid.
func (l *LightningWallet) InitChannelReservation(
capacity, ourFundAmt btcutil.Amount, pushMSat lnwire.MilliSatoshi,
commitFeePerKw SatPerKWeight, fundingFeePerKw SatPerKWeight,
theirID *btcec.PublicKey, theirAddr net.Addr,
chainHash *chainhash.Hash, flags lnwire.FundingFlag) (*ChannelReservation, error) {
req *InitFundingReserveMsg) (*ChannelReservation, error) {
errChan := make(chan error, 1)
respChan := make(chan *ChannelReservation, 1)
req.resp = make(chan *ChannelReservation, 1)
req.err = make(chan error, 1)
l.msgChan <- &initFundingReserveMsg{
chainHash: chainHash,
nodeID: theirID,
nodeAddr: theirAddr,
fundingAmount: ourFundAmt,
capacity: capacity,
commitFeePerKw: commitFeePerKw,
fundingFeePerKw: fundingFeePerKw,
pushMSat: pushMSat,
flags: flags,
err: errChan,
resp: respChan,
select {
case l.msgChan <- req:
case <-l.quit:
return nil, errors.New("wallet shutting down")
}
return <-respChan, <-errChan
return <-req.resp, <-req.err
}
// handleFundingReserveRequest processes a message intending to create, and
// validate a funding reservation request.
func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg) {
func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg) {
// It isn't possible to create a channel with zero funds committed.
if req.fundingAmount+req.capacity == 0 {
if req.FundingAmount+req.Capacity == 0 {
err := ErrZeroCapacity()
req.err <- err
req.resp <- nil
@ -450,18 +443,20 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
// If the funding request is for a different chain than the one the
// wallet is aware of, then we'll reject the request.
if !bytes.Equal(l.Cfg.NetParams.GenesisHash[:], req.chainHash[:]) {
err := ErrChainMismatch(l.Cfg.NetParams.GenesisHash,
req.chainHash)
if !bytes.Equal(l.Cfg.NetParams.GenesisHash[:], req.ChainHash[:]) {
err := ErrChainMismatch(
l.Cfg.NetParams.GenesisHash, req.ChainHash,
)
req.err <- err
req.resp <- nil
return
}
id := atomic.AddUint64(&l.nextFundingID, 1)
reservation, err := NewChannelReservation(req.capacity, req.fundingAmount,
req.commitFeePerKw, l, id, req.pushMSat,
l.Cfg.NetParams.GenesisHash, req.flags)
reservation, err := NewChannelReservation(
req.Capacity, req.FundingAmount, req.CommitFeePerKw, l, id,
req.PushMSat, l.Cfg.NetParams.GenesisHash, req.Flags,
)
if err != nil {
req.err <- err
req.resp <- nil
@ -472,17 +467,17 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
reservation.Lock()
defer reservation.Unlock()
reservation.nodeAddr = req.nodeAddr
reservation.partialState.IdentityPub = req.nodeID
reservation.nodeAddr = req.NodeAddr
reservation.partialState.IdentityPub = req.NodeID
// If we're on the receiving end of a single funder channel then we
// don't need to perform any coin selection. Otherwise, attempt to
// obtain enough coins to meet the required funding amount.
if req.fundingAmount != 0 {
if req.FundingAmount != 0 {
// Coin selection is done on the basis of sat/kw, so we'll use
// the fee rate passed in to perform coin selection.
err := l.selectCoinsAndChange(
req.fundingFeePerKw, req.fundingAmount,
req.FundingFeePerKw, req.FundingAmount, req.MinConfs,
reservation.ourContribution,
)
if err != nil {
@ -1265,9 +1260,10 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
// selection is successful/possible, then the selected coins are available
// within the passed contribution's inputs. If necessary, a change address will
// also be generated.
// TODO(roasbeef): remove hardcoded fees and req'd confs for outputs.
// TODO(roasbeef): remove hardcoded fees.
func (l *LightningWallet) selectCoinsAndChange(feeRate SatPerKWeight,
amt btcutil.Amount, contribution *ChannelContribution) error {
amt btcutil.Amount, minConfs int32,
contribution *ChannelContribution) error {
// We hold the coin select mutex while querying for outputs, and
// performing coin selection in order to avoid inadvertent double
@ -1278,10 +1274,9 @@ func (l *LightningWallet) selectCoinsAndChange(feeRate SatPerKWeight,
walletLog.Infof("Performing funding tx coin selection using %v "+
"sat/kw as fee rate", int64(feeRate))
// Find all unlocked unspent witness outputs with greater than 1
// confirmation.
// TODO(roasbeef): make num confs a configuration parameter
coins, err := l.ListUnspentWitness(1)
// Find all unlocked unspent witness outputs that satisfy the minimum
// number of confirmations required.
coins, err := l.ListUnspentWitness(minConfs)
if err != nil {
return err
}

@ -17,8 +17,9 @@ import (
// chanController is an implementation of the autopilot.ChannelController
// interface that's backed by a running lnd instance.
type chanController struct {
server *server
private bool
server *server
private bool
minConfs int32
}
// OpenChannel opens a channel to a target peer, with a capacity of the
@ -37,10 +38,21 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey,
// TODO(halseth): make configurable?
minHtlc := lnwire.NewMSatFromSatoshis(1)
updateStream, errChan := c.server.OpenChannel(
target, amt, 0, minHtlc, feePerKw, c.private, 0,
)
// Construct the open channel request and send it to the server to begin
// the funding workflow.
req := &openChanReq{
targetPubkey: target,
chainHash: *activeNetParams.GenesisHash,
localFundingAmt: amt,
pushAmt: 0,
minHtlc: minHtlc,
fundingFeePerKw: feePerKw,
private: c.private,
remoteCsvDelay: 0,
minConfs: c.minConfs,
}
updateStream, errChan := c.server.OpenChannel(req)
select {
case err := <-errChan:
// If we were not able to actually open a channel to the peer
@ -100,11 +112,12 @@ func initAutoPilot(svr *server, cfg *autoPilotConfig) (*autopilot.Agent, error)
Self: self,
Heuristic: prefAttachment,
ChanController: &chanController{
server: svr,
private: cfg.Private,
server: svr,
private: cfg.Private,
minConfs: cfg.MinConfs,
},
WalletBalance: func() (btcutil.Amount, error) {
return svr.cc.wallet.ConfirmedBalance(1)
return svr.cc.wallet.ConfirmedBalance(cfg.MinConfs)
},
Graph: autopilot.ChannelGraphFromDatabase(svr.chanDB.ChannelGraph()),
MaxPendingOpens: 10,

@ -770,6 +770,12 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
"size is: %v SAT", int64(minChanFundingSize))
}
// Ensure that the MinConfs parameter is non-negative.
if in.MinConfs < 0 {
return errors.New("minimum number of confirmations must be a " +
"non-negative number")
}
var (
nodePubKey *btcec.PublicKey
nodePubKeyBytes []byte
@ -813,11 +819,19 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
// Instruct the server to trigger the necessary events to attempt to
// open a new channel. A stream is returned in place, this stream will
// be used to consume updates of the state of the pending channel.
updateChan, errChan := r.server.OpenChannel(
nodePubKey, localFundingAmt,
lnwire.NewMSatFromSatoshis(remoteInitialBalance),
minHtlc, feeRate, in.Private, remoteCsvDelay,
)
req := &openChanReq{
targetPubkey: nodePubKey,
chainHash: *activeNetParams.GenesisHash,
localFundingAmt: localFundingAmt,
pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance),
minHtlc: minHtlc,
fundingFeePerKw: feeRate,
private: in.Private,
remoteCsvDelay: remoteCsvDelay,
minConfs: in.MinConfs,
}
updateChan, errChan := r.server.OpenChannel(req)
var outpoint wire.OutPoint
out:
@ -929,6 +943,12 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
"size is: %v SAT", int64(minChanFundingSize))
}
// Ensure that the MinConfs parameter is non-negative.
if in.MinConfs < 0 {
return nil, errors.New("minimum number of confirmations must " +
"be a non-negative number")
}
// Based on the passed fee related parameters, we'll determine an
// appropriate fee rate for the funding transaction.
feeRate, err := determineFeePerKw(
@ -941,12 +961,19 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
rpcsLog.Tracef("[openchannel] target sat/kw for funding tx: %v",
int64(feeRate))
updateChan, errChan := r.server.OpenChannel(
nodepubKey, localFundingAmt,
lnwire.NewMSatFromSatoshis(remoteInitialBalance),
minHtlc, feeRate, in.Private, remoteCsvDelay,
)
req := &openChanReq{
targetPubkey: nodepubKey,
chainHash: *activeNetParams.GenesisHash,
localFundingAmt: localFundingAmt,
pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance),
minHtlc: minHtlc,
fundingFeePerKw: feeRate,
private: in.Private,
remoteCsvDelay: remoteCsvDelay,
minConfs: in.MinConfs,
}
updateChan, errChan := r.server.OpenChannel(req)
select {
// If an error occurs them immediately return the error to the client.
case err := <-errChan:

@ -2597,6 +2597,10 @@ type openChanReq struct {
remoteCsvDelay uint16
// minConfs indicates the minimum number of confirmations that each
// output selected to fund the channel should satisfy.
minConfs int32
// TODO(roasbeef): add ability to specify channel constraints as well
updates chan *lnrpc.OpenStatusUpdate
@ -2735,77 +2739,45 @@ func (s *server) DisconnectPeer(pubKey *btcec.PublicKey) error {
// peer identified by nodeKey with the passed channel funding parameters.
//
// NOTE: This function is safe for concurrent access.
func (s *server) OpenChannel(nodeKey *btcec.PublicKey,
localAmt btcutil.Amount, pushAmt, minHtlc lnwire.MilliSatoshi,
fundingFeePerKw lnwallet.SatPerKWeight, private bool,
remoteCsvDelay uint16) (chan *lnrpc.OpenStatusUpdate, chan error) {
func (s *server) OpenChannel(
req *openChanReq) (chan *lnrpc.OpenStatusUpdate, chan error) {
// The updateChan will have a buffer of 2, since we expect a
// ChanPending + a ChanOpen update, and we want to make sure the
// funding process is not blocked if the caller is not reading the
// updates.
updateChan := make(chan *lnrpc.OpenStatusUpdate, 2)
errChan := make(chan error, 1)
var (
targetPeer *peer
pubKeyBytes []byte
err error
)
// If the user is targeting the peer by public key, then we'll need to
// convert that into a string for our map. Otherwise, we expect them to
// target by peer ID instead.
if nodeKey != nil {
pubKeyBytes = nodeKey.SerializeCompressed()
}
// The updateChan will have a buffer of 2, since we expect a ChanPending
// + a ChanOpen update, and we want to make sure the funding process is
// not blocked if the caller is not reading the updates.
req.updates = make(chan *lnrpc.OpenStatusUpdate, 2)
req.err = make(chan error, 1)
// First attempt to locate the target peer to open a channel with, if
// we're unable to locate the peer then this request will fail.
pubKeyBytes := req.targetPubkey.SerializeCompressed()
s.mu.RLock()
if peer, ok := s.peersByPub[string(pubKeyBytes)]; ok {
targetPeer = peer
peer, ok := s.peersByPub[string(pubKeyBytes)]
if !ok {
req.err <- fmt.Errorf("peer %x is not online", pubKeyBytes)
return req.updates, req.err
}
s.mu.RUnlock()
if targetPeer == nil {
errChan <- fmt.Errorf("peer is not connected NodeKey(%x)", pubKeyBytes)
return updateChan, errChan
}
// If the fee rate wasn't specified, then we'll use a default
// confirmation target.
if fundingFeePerKw == 0 {
if req.fundingFeePerKw == 0 {
estimator := s.cc.feeEstimator
fundingFeePerKw, err = estimator.EstimateFeePerKW(6)
feeRate, err := estimator.EstimateFeePerKW(6)
if err != nil {
errChan <- err
return updateChan, errChan
req.err <- err
return req.updates, req.err
}
req.fundingFeePerKw = feeRate
}
// Spawn a goroutine to send the funding workflow request to the
// funding manager. This allows the server to continue handling queries
// instead of blocking on this request which is exported as a
// synchronous request to the outside world.
req := &openChanReq{
targetPubkey: nodeKey,
chainHash: *activeNetParams.GenesisHash,
localFundingAmt: localAmt,
fundingFeePerKw: fundingFeePerKw,
pushAmt: pushAmt,
private: private,
minHtlc: minHtlc,
remoteCsvDelay: remoteCsvDelay,
updates: updateChan,
err: errChan,
}
// Spawn a goroutine to send the funding workflow request to the funding
// manager. This allows the server to continue handling queries instead
// of blocking on this request which is exported as a synchronous
// request to the outside world.
go s.fundingMgr.initFundingWorkflow(peer, req)
// TODO(roasbeef): pass in chan that's closed if/when funding succeeds
// so can track as persistent peer?
go s.fundingMgr.initFundingWorkflow(targetPeer, req)
return updateChan, errChan
return req.updates, req.err
}
// Peers returns a slice of all active peers.