From 0921c911a346d6c89094ec503a3a3b6809753fc1 Mon Sep 17 00:00:00 2001 From: hunjixin <1084400399@qq.com> Date: Wed, 20 Sep 2023 17:29:17 +0800 Subject: [PATCH 01/68] feat: add confidence for init miner --- cmd/lotus-miner/init.go | 29 ++++++++++++++++++----------- cmd/lotus-miner/init_restore.go | 3 +-- cmd/lotus-miner/init_service.go | 2 +- documentation/en/cli-lotus-miner.md | 1 + 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/cmd/lotus-miner/init.go b/cmd/lotus-miner/init.go index c109e85b9..8659e3d29 100644 --- a/cmd/lotus-miner/init.go +++ b/cmd/lotus-miner/init.go @@ -120,6 +120,11 @@ var initCmd = &cli.Command{ Name: "from", Usage: "select which address to send actor creation message from", }, + &cli.Uint64Flag{ + Name: "confidence", + Usage: "number of block confirmations to wait for", + Value: build.MessageConfidence, + }, }, Subcommands: []*cli.Command{ restoreCmd, @@ -146,6 +151,8 @@ var initCmd = &cli.Command{ return xerrors.Errorf("failed to parse gas-price flag: %s", err) } + confidence := cctx.Uint64("confidence") + symlink := cctx.Bool("symlink-imported-sectors") if symlink { log.Info("will attempt to symlink to imported sectors") @@ -265,7 +272,7 @@ var initCmd = &cli.Command{ } } - if err := storageMinerInit(ctx, cctx, api, r, ssize, gasPrice); err != nil { + if err := storageMinerInit(ctx, cctx, api, r, ssize, gasPrice, confidence); err != nil { log.Errorf("Failed to initialize lotus-miner: %+v", err) path, err := homedir.Expand(repoPath) if err != nil { @@ -414,7 +421,7 @@ func findMarketDealID(ctx context.Context, api v1api.FullNode, deal markettypes. return 0, xerrors.New("deal not found") } -func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode, r repo.Repo, ssize abi.SectorSize, gasPrice types.BigInt) error { +func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode, r repo.Repo, ssize abi.SectorSize, gasPrice types.BigInt, confidence uint64) error { lr, err := r.Lock(repo.StorageMiner) if err != nil { return err @@ -501,7 +508,7 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode return xerrors.Errorf("failed to start up genesis miner: %w", err) } - cerr := configureStorageMiner(ctx, api, a, peerid, gasPrice) + cerr := configureStorageMiner(ctx, api, a, peerid, gasPrice, confidence) if err := m.Stop(ctx); err != nil { log.Error("failed to shut down miner: ", err) @@ -541,13 +548,13 @@ func storageMinerInit(ctx context.Context, cctx *cli.Context, api v1api.FullNode } } - if err := configureStorageMiner(ctx, api, a, peerid, gasPrice); err != nil { + if err := configureStorageMiner(ctx, api, a, peerid, gasPrice, confidence); err != nil { return xerrors.Errorf("failed to configure miner: %w", err) } addr = a } else { - a, err := createStorageMiner(ctx, api, ssize, peerid, gasPrice, cctx) + a, err := createStorageMiner(ctx, api, ssize, peerid, gasPrice, confidence, cctx) if err != nil { return xerrors.Errorf("creating miner failed: %w", err) } @@ -589,7 +596,7 @@ func makeHostKey(lr repo.LockedRepo) (crypto.PrivKey, error) { return pk, nil } -func configureStorageMiner(ctx context.Context, api v1api.FullNode, addr address.Address, peerid peer.ID, gasPrice types.BigInt) error { +func configureStorageMiner(ctx context.Context, api v1api.FullNode, addr address.Address, peerid peer.ID, gasPrice types.BigInt, confidence uint64) error { mi, err := api.StateMinerInfo(ctx, addr, types.EmptyTSK) if err != nil { return xerrors.Errorf("getWorkerAddr returned bad address: %w", err) @@ -615,7 +622,7 @@ func configureStorageMiner(ctx context.Context, api v1api.FullNode, addr address } log.Info("Waiting for message: ", smsg.Cid()) - ret, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true) + ret, err := api.StateWaitMsg(ctx, smsg.Cid(), confidence, lapi.LookbackNoLimit, true) if err != nil { return err } @@ -627,7 +634,7 @@ func configureStorageMiner(ctx context.Context, api v1api.FullNode, addr address return nil } -func createStorageMiner(ctx context.Context, api v1api.FullNode, ssize abi.SectorSize, peerid peer.ID, gasPrice types.BigInt, cctx *cli.Context) (address.Address, error) { +func createStorageMiner(ctx context.Context, api v1api.FullNode, ssize abi.SectorSize, peerid peer.ID, gasPrice types.BigInt, confidence uint64, cctx *cli.Context) (address.Address, error) { var err error var owner address.Address if cctx.String("owner") != "" { @@ -679,7 +686,7 @@ func createStorageMiner(ctx context.Context, api v1api.FullNode, ssize abi.Secto log.Infof("Initializing worker account %s, message: %s", worker, signed.Cid()) log.Infof("Waiting for confirmation") - mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true) + mw, err := api.StateWaitMsg(ctx, signed.Cid(), confidence, lapi.LookbackNoLimit, true) if err != nil { return address.Undef, xerrors.Errorf("waiting for worker init: %w", err) } @@ -703,7 +710,7 @@ func createStorageMiner(ctx context.Context, api v1api.FullNode, ssize abi.Secto log.Infof("Initializing owner account %s, message: %s", worker, signed.Cid()) log.Infof("Waiting for confirmation") - mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true) + mw, err := api.StateWaitMsg(ctx, signed.Cid(), confidence, lapi.LookbackNoLimit, true) if err != nil { return address.Undef, xerrors.Errorf("waiting for owner init: %w", err) } @@ -752,7 +759,7 @@ func createStorageMiner(ctx context.Context, api v1api.FullNode, ssize abi.Secto log.Infof("Pushed CreateMiner message: %s", signed.Cid()) log.Infof("Waiting for confirmation") - mw, err := api.StateWaitMsg(ctx, signed.Cid(), build.MessageConfidence, lapi.LookbackNoLimit, true) + mw, err := api.StateWaitMsg(ctx, signed.Cid(), confidence, lapi.LookbackNoLimit, true) if err != nil { return address.Undef, xerrors.Errorf("waiting for createMiner message: %w", err) } diff --git a/cmd/lotus-miner/init_restore.go b/cmd/lotus-miner/init_restore.go index 7e28729bb..272754c23 100644 --- a/cmd/lotus-miner/init_restore.go +++ b/cmd/lotus-miner/init_restore.go @@ -80,8 +80,7 @@ var restoreCmd = &cli.Command{ } log.Info("Configuring miner actor") - - if err := configureStorageMiner(ctx, api, maddr, peerid, big.Zero()); err != nil { + if err := configureStorageMiner(ctx, api, maddr, peerid, big.Zero(), cctx.Uint64("confidence")); err != nil { return err } diff --git a/cmd/lotus-miner/init_service.go b/cmd/lotus-miner/init_service.go index 235e4e4c8..876313941 100644 --- a/cmd/lotus-miner/init_service.go +++ b/cmd/lotus-miner/init_service.go @@ -105,7 +105,7 @@ var serviceCmd = &cli.Command{ if es.Contains(MarketsService) { log.Info("Configuring miner actor") - if err := configureStorageMiner(ctx, api, maddr, peerid, big.Zero()); err != nil { + if err := configureStorageMiner(ctx, api, maddr, peerid, big.Zero(), cctx.Uint64("confidence")); err != nil { return err } } diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 8406b07cc..ecfea092c 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -66,6 +66,7 @@ OPTIONS: --no-local-storage don't use storageminer repo for sector storage (default: false) --gas-premium value set gas premium for initialization messages in AttoFIL (default: "0") --from value select which address to send actor creation message from + --confidence value number of block confirmations to wait for (default: 5) --help, -h show help ``` From e425322c2bd1fba6e4e37baae4a54d00fffde6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 29 Nov 2023 17:17:34 +0100 Subject: [PATCH 02/68] misc: Drop the raft-cluster experiment --- .circleci/config.yml | 6 - api/api_full.go | 3 - api/docgen/docgen.go | 4 - api/mocks/mock_full.go | 30 - api/proxy_gen.go | 26 - api/types.go | 63 -- build/openrpc/full.json.gz | Bin 34820 -> 34608 bytes build/openrpc/gateway.json.gz | Bin 11872 -> 11871 bytes build/openrpc/miner.json.gz | Bin 16371 -> 16373 bytes build/openrpc/worker.json.gz | Bin 6051 -> 6051 bytes .../messagesigner/messagesigner_consensus.go | 98 --- documentation/en/api-v1-unstable-methods.md | 30 - documentation/en/default-lotus-config.toml | 62 -- itests/kit/ensemble.go | 4 - itests/raft_messagesigner_test.go | 577 ------------------ lib/consensus/raft/config.go | 135 ---- lib/consensus/raft/consensus.go | 512 ---------------- lib/consensus/raft/interfaces.go | 41 -- lib/consensus/raft/raft.go | 563 ----------------- node/builder.go | 1 - node/builder_chain.go | 13 - node/config/def.go | 23 - node/config/doc_gen.go | 68 --- node/config/types.go | 28 - node/impl/full.go | 9 - node/impl/full/mpool.go | 16 - node/impl/full/raft.go | 50 -- node/modules/rpc.go | 55 -- 28 files changed, 2417 deletions(-) delete mode 100644 chain/messagesigner/messagesigner_consensus.go delete mode 100644 itests/raft_messagesigner_test.go delete mode 100644 lib/consensus/raft/config.go delete mode 100644 lib/consensus/raft/consensus.go delete mode 100644 lib/consensus/raft/interfaces.go delete mode 100644 lib/consensus/raft/raft.go delete mode 100644 node/impl/full/raft.go delete mode 100644 node/modules/rpc.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 20701f7d5..7987060d4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -858,12 +858,6 @@ workflows: - build suite: itest-pending_deal_allocation target: "./itests/pending_deal_allocation_test.go" - - test: - name: test-itest-raft_messagesigner - requires: - - build - suite: itest-raft_messagesigner - target: "./itests/raft_messagesigner_test.go" - test: name: test-itest-remove_verifreg_datacap requires: diff --git a/api/api_full.go b/api/api_full.go index 4ae2ea531..3dc7f8bb2 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -879,9 +879,6 @@ type FullNode interface { // LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that // the path specified when calling CreateBackup is within the base path CreateBackup(ctx context.Context, fpath string) error //perm:admin - - RaftState(ctx context.Context) (*RaftStateData, error) //perm:read - RaftLeader(ctx context.Context) (peer.ID, error) //perm:read } // reverse interface to the client, called after EthSubscribe diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 018629600..70024d3db 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -355,10 +355,6 @@ func init() { addExample(map[string]bitfield.BitField{ "": bitfield.NewFromSet([]uint64{5, 6, 7, 10}), }) - addExample(&api.RaftStateData{ - NonceMap: make(map[address.Address]uint64), - MsgUuids: make(map[uuid.UUID]*types.SignedMessage), - }) addExample(http.Header{ "Authorization": []string{"Bearer ey.."}, diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 92b719550..ed9fe740e 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -2919,36 +2919,6 @@ func (mr *MockFullNodeMockRecorder) PaychVoucherSubmit(arg0, arg1, arg2, arg3, a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PaychVoucherSubmit", reflect.TypeOf((*MockFullNode)(nil).PaychVoucherSubmit), arg0, arg1, arg2, arg3, arg4) } -// RaftLeader mocks base method. -func (m *MockFullNode) RaftLeader(arg0 context.Context) (peer.ID, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RaftLeader", arg0) - ret0, _ := ret[0].(peer.ID) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RaftLeader indicates an expected call of RaftLeader. -func (mr *MockFullNodeMockRecorder) RaftLeader(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RaftLeader", reflect.TypeOf((*MockFullNode)(nil).RaftLeader), arg0) -} - -// RaftState mocks base method. -func (m *MockFullNode) RaftState(arg0 context.Context) (*api.RaftStateData, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RaftState", arg0) - ret0, _ := ret[0].(*api.RaftStateData) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RaftState indicates an expected call of RaftState. -func (mr *MockFullNodeMockRecorder) RaftState(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RaftState", reflect.TypeOf((*MockFullNode)(nil).RaftState), arg0) -} - // Session mocks base method. func (m *MockFullNode) Session(arg0 context.Context) (uuid.UUID, error) { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 8adcbc189..589ae8f56 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -453,10 +453,6 @@ type FullNodeMethods struct { PaychVoucherSubmit func(p0 context.Context, p1 address.Address, p2 *paych.SignedVoucher, p3 []byte, p4 []byte) (cid.Cid, error) `perm:"sign"` - RaftLeader func(p0 context.Context) (peer.ID, error) `perm:"read"` - - RaftState func(p0 context.Context) (*RaftStateData, error) `perm:"read"` - StateAccountKey func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) `perm:"read"` StateActorCodeCIDs func(p0 context.Context, p1 abinetwork.Version) (map[string]cid.Cid, error) `perm:"read"` @@ -3223,28 +3219,6 @@ func (s *FullNodeStub) PaychVoucherSubmit(p0 context.Context, p1 address.Address return *new(cid.Cid), ErrNotSupported } -func (s *FullNodeStruct) RaftLeader(p0 context.Context) (peer.ID, error) { - if s.Internal.RaftLeader == nil { - return *new(peer.ID), ErrNotSupported - } - return s.Internal.RaftLeader(p0) -} - -func (s *FullNodeStub) RaftLeader(p0 context.Context) (peer.ID, error) { - return *new(peer.ID), ErrNotSupported -} - -func (s *FullNodeStruct) RaftState(p0 context.Context) (*RaftStateData, error) { - if s.Internal.RaftState == nil { - return nil, ErrNotSupported - } - return s.Internal.RaftState(p0) -} - -func (s *FullNodeStub) RaftState(p0 context.Context) (*RaftStateData, error) { - return nil, ErrNotSupported -} - func (s *FullNodeStruct) StateAccountKey(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (address.Address, error) { if s.Internal.StateAccountKey == nil { return *new(address.Address), ErrNotSupported diff --git a/api/types.go b/api/types.go index 93ed4083f..7fd607750 100644 --- a/api/types.go +++ b/api/types.go @@ -69,11 +69,6 @@ type MessageSendSpec struct { MaximizeFeeCap bool } -type MpoolMessageWhole struct { - Msg *types.Message - Spec *MessageSendSpec -} - // GraphSyncDataTransfer provides diagnostics on a data transfer happening over graphsync type GraphSyncDataTransfer struct { // GraphSync request id for this transfer @@ -351,64 +346,6 @@ type ForkUpgradeParams struct { UpgradeWatermelonHeight abi.ChainEpoch } -type NonceMapType map[address.Address]uint64 -type MsgUuidMapType map[uuid.UUID]*types.SignedMessage - -type RaftStateData struct { - NonceMap NonceMapType - MsgUuids MsgUuidMapType -} - -func (n *NonceMapType) MarshalJSON() ([]byte, error) { - marshalled := make(map[string]uint64) - for a, n := range *n { - marshalled[a.String()] = n - } - return json.Marshal(marshalled) -} - -func (n *NonceMapType) UnmarshalJSON(b []byte) error { - unmarshalled := make(map[string]uint64) - err := json.Unmarshal(b, &unmarshalled) - if err != nil { - return err - } - *n = make(map[address.Address]uint64) - for saddr, nonce := range unmarshalled { - a, err := address.NewFromString(saddr) - if err != nil { - return err - } - (*n)[a] = nonce - } - return nil -} - -func (m *MsgUuidMapType) MarshalJSON() ([]byte, error) { - marshalled := make(map[string]*types.SignedMessage) - for u, msg := range *m { - marshalled[u.String()] = msg - } - return json.Marshal(marshalled) -} - -func (m *MsgUuidMapType) UnmarshalJSON(b []byte) error { - unmarshalled := make(map[string]*types.SignedMessage) - err := json.Unmarshal(b, &unmarshalled) - if err != nil { - return err - } - *m = make(map[uuid.UUID]*types.SignedMessage) - for suid, msg := range unmarshalled { - u, err := uuid.Parse(suid) - if err != nil { - return err - } - (*m)[u] = msg - } - return nil -} - // ChainExportConfig holds configuration for chain ranged exports. type ChainExportConfig struct { WriteBufferSize int diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 99426649275b903af8f200301ae779290cfda9cb..3aa6bc16b201c89b6541b5ac3ff4a9c84c666216 100644 GIT binary patch delta 33358 zcmZUaQ*dBWv$kV96HRQ}wr$(CC)v@&=ESybClebJ+nm_RneRJQr~az{W>@cZyU=g< z`*cV=SY0ewJOz+6{O3{bs@wSrKRiS%nmQmXpi7Qs`vU{>DoQA_!5qg`VM>cE6)ODd z)4g!+d9@If#CYc($!A@6u)5ozH*75A5y}6N>qy`X|6V{@z;fsP0;Y?X_wvD)lgjKD zn!2f{?OSt{gHP{kH_je`yY}_Y+YCV@fAwZq7RBJj<@qeDH2*uw2n0`tt7BhR@~oG!KMDt- zhn2vD9Gc zrlZ>G%N!ug3faXPXFL)X5{=bUzDs*ftI^xujWYUs8~NTr0(`z$)^3~Lts;azbq5>Z zI9G^6VP_LFg(C0@{b+H58a4ytDse?>3+v;m@f7#@FaQzdQbp%M9>)5<-HSvuc#D4W zXAl1Ku}3n_{~ay(?Flbz zG=`>~3MK)(-HRnqK(tpT=fU?x!LQf!OvC3IMO>sv`_Vp2=&}bROI>e#VKxPEAy4B zxX#pXlr{fs+`bP=wic$)+3J{dm9pgZjvl?6NB%#Cl)<)iSCF zR`q3Dwt|Lx292=zRE7eN$Dttt${7ht0W2J2mV~2xI6$%tV8p)#)n1JUOF>aS zjWzL6s=fZ+4%iKl|0VzvNJdkkzH>_Qq9P(nnOO3}&V(+=L)bRvf*K%=4D;d< zCr)C49s>(d08v}Ji^S{Z1*TvSeo1mWIfvt2ZG$TWMy)ht(@bJaBndWa} z{5>cl2YN854|{(KtN~b-65IS4Dbc6j$*(YpTeWC#HgLtK)U>Gt?m=^-KR8m`S z84ACinc(NB9>eG45!%|_qi z^;$PndqEKnOGFWfM~!ExzqemQ#6}8&1q3{=G}5G$G1x3(v=1{h1S5z!lhIB)S@s(IPrJ z>l<=FX&df(J7}e(uKe1_Daw!vL^B8Oe!x1H(ZXKD0K}rcE-h?mb7*36KYz@EG!FSf zK<2!y4&qI%h^o|jcj3Rhf+C1|F@`1SKq(r(!rwN4&PA}3@SNdH55wN*7H@39_cnh}t<7&ZrD;|NR+r#w}CXOuT;~#Bs`ko>3ZY^v;P+ z`?nc2KVWG#Zjqzre4LQmBD|uqWqjYRXkH z+pU~MvN_8YYaJ1Nu!6s7rZ93K zb3qbx32P1wqqonDCDqG`@Td+3utH#yFu;KxjFE~&1h@2YDt0^(LlYo?iD`XBD(%q{ z_CtixIiPpN`_Xz1&>s=}J*79nbE1Yc{2lB}WxOJu{~R9V;ue8f^4WMtmq-oLC#MMgJPhpF#Wk`eAt; zN9CmSD?N?vQrnwwUiXXZY5 zhJ~o!GcOClMHw?@$N&1|zRhYdZX__OgmV|>nkzY9_iD58^lI}#|L-*{&Xz(}FYsi+ zDe5Ru`*OL`-5Ki1TlFL>cM0hdbUxYkfE*Fc0l>ZTTO&}f8Xf&Sd4|U`ZWX1lJ^PSi zeD&y4tqv){l(nI6Dy#UD3_B~&*igbRem+-3I0YiHqFZ~}QUkyCgDis*S2GGih%=U; zc`>&=CL^is@)rYn5q+hOhJKDZE1=`_kzF@4^H$ewcqA()z2;#WT?teUhHD|t4jhjSqI0d*~47!j#PR+#EC@5=Sl=g%usX&8s1q3frEDogvaL?FfyXS;-X z@JXV9r({y>j=sIKY{X^fFgWtUzS_X; z;}$)>cAmMEf=9e{x%`eNzs?|7%&$~k>f2M*M&ATs@wl9ndWh2d@=$v*9V5$=U-u@# zS0slgG(0~vE@Y{M<2lw3Gr*`>|8GZ+vsfX6W5cWaoPs7Ga%F;m@jys&A|r?LHJy7Y z<6#%85VwyXPg@X+LS~6U-?yd}kfOh(-azMVPcoSksN0c__2<>S%Fr@mAMw1R&=XpM zCnGyi7Pc!@ec4$wbcCvyx2SzDwzJ$l@?@YIkA!@mS>qhmz1;}`1Bf98C&==q3da4m z)qMP*@#DT~!&$jlWx+A}NO7mQW`8nw?8@2KFgoWxl(?bV!!PxsV*0J89Vwx^V~Cv) z1$t&hb@E%cn_Qyzy>3yw_Wdj>wtd z32~Qqt;TX!uY8bs(-MI$`E6MNZpuT7k6j#;C@E|5Q>y^B7LZ!i#!kUU`<88|pmuAh5 z7S{d=>Sy0dk05PZ8@gWzNuFOI&$-KK_;HDdN%m9;BhIECP|@+y;Npy!_!Ly`~NQ@sUfQxup?I1~Sq6v|}Q5>Im zQiYX)A+H_&Muso6BN{8Bejh28E=`iA>S@9Ryd_|D#+gKM=Z5Tw`UuizbeL2X!WO(^e(YIPh*euXEmv8mFVtZ28Ru`<2I)H>_1^!6qI_X0Bl z65R;%cqbF9ReeP+SMBT~#dUvae>l}+qwyD)MO?9ZuLYTvUO8R-I~b`Z5W=ld=sN}3 zS4J5n6$%dFpYzk*C+|^|24y>9&P9I6IhrNSB4Y!J z>%MR9&>qtR+}7TDk{Z=}HZSubmFE2lZ9D~*pqiCPlx%J&;7Hk!N(S1*&#U=8mA|x2 znyC>+oFa!z3AwY>ot`lwwDGFK2lrRmx^JXhcEbv->T^hum=n^N?vb`yOswa$aMmp{ zTCk?7lascWhbeNWylq)Ema6y6%`brRs8-B|M!Rxc|JZPyq1lQFBL+l%^VW)HNTyvj zzec@Mx%3=N)}AU0zH)2&e^sZ|r#k?Ok*fz>ai zjsSiVG&L0xyyu!Or<`~;rS(PalwJ^awRZ>XF3K1jXKWtHx^7(Zn)J&KTWDVmGoQBS~Zc;kv@5#KmL z&=ux$_9-|QQu0&X3RT_6N`j9^fQc4X61iRGa)5}Y0SMJWs2>Omije<&2o?2u6fCt zA%u#OF1fg;DBOA zzDo=1*)bb;2c6=N-23XRd+~WX9=KXIf2Uf|TVV$i2V`0gJ!*fdLqG7I9PHx~URnyJ zNnO-gru_4iBlCQ4g9}q=3qktduDkXhx1K$PgmT+<%6r&Fxp($=oSG{$C)~(_t9s7* zD)9b(<5dq-7mx@c6yD}8Xk68HT}`O&Bc-c=Ayo?|HPcZJ03R3}!; z;0+IcHyzzIhk?yZCUR3iue32%!Rt(mYB|EU;PEKfl6&0(xp(nzk{@YtyG#KYQB z_rZx|K`&mD(FIP7`!=DDf9S6;+b5ZC%$j6WZZ3f=sTc)Td?PTQE?4pEGX=6cP6O?4 z4OV2j)g}Q!+^6_yD>AVC@lpHra*ca`)9dxu_!=J`_=*!fUf&!Ue8L)xy9n`b>w*^q zI$r(&H`2bj-Xf1D2?gBMaW@N(pZ@Aj`jO%@sL0G6fuGDl!>iUL&n)!n(mhNxY{9$i zd%6V|r}g>K6Ttm!ar{J554IA62+NI8AgxR^u_!|xM47NB#q{{GoB6z5 zYc*RV-;1^Hm%O@FmY&w$LbmZi9_b6{I+JNf#IP`=h$vw;0lZn;N~|=e{{Ev>^XlZe zvcy+nON`E>9-2BB?E zNswyld5z;zpEQX{GdYc&UC$;e5uWT3 zZBIwFOG<4dq=?KtoW$*$tTk;sr#6wM%>I?wO)$*#G0kU7C73aJRPF|B{hZ2k`M7$4 zVmH4eI&eyk{*hBSCNikJboN^#`cxMsH}ML4> z+!FDSd(-T!s94rFfx2vbZRwK1#JO*AEp$B}JUH2N=3D9B zH2D=%93r-X8pjih7j|@C?V9gbrE*A(!>}UyjrSn=7ZptIk8*QpG-g^D9dwY#zH)l~ z3iK&bYMW&5H|noW!@#t%*Oxns@UDpzzPpO=D2a6)WR(KqpxF8l#Bg5H7(F^v8#MP{ zU%Qt@Ehl8UeE_=eO=P&7og+y~rm zN$F~r+F1lbdmbKc0ZV)g+7d=u=t+TId->isaA57SvZhb7Z3rL7nA=3&qWgw@*M>q@ zJ?f~lA7oE)p-B|6P_{dh{=LBbq`MAb>Poa$tK|1|1SZ2K0z7;6*itCzq1M(>)XeUw z@{%$METSNh3q%qdCK2V&?`;2?Lz)KZCSFZm8~C?=49oWPqk2(7vzC^&*J|0#vvS0o z<_bx^m@I(f84BuQ%smA)WV7o!Y+F*e+B}_x-?(!8de0f6IBe$s+|UAq!r&wuS5L zLEUr~DwcA<-7%o#@?kVpDSaq~KZg!UnPjVA6$kO*wl8@RcokHls@EQ>oa5xVB_fu( zj>tlrWL8_3rI){R9RibCT(epY$uqx~tuA|(6SmPFdx}&(mNOvngVAm^+)pkp5s_b^ z?gWHv^v<3L-LAaKhUnF(*?U|V8)nxP{9ermtL?3CKU1WK>Ahvg*VFU6C)nq>`;Kp?qyMnS2&HaFY_ z@(wZ}!~9-{itEa(t9ftL%v|3gHDdv3B0m>j;%&31SuoJVQaFsz8?tr&itv417G>!d zLc{lT1AOQ(TM?!ouiZym+>afrc(=E>Q?O_pp$B>LU3hf&;=?MshzfSdy>4VM_$2M> zwUotqHz=bc^vIOlX1q!iyhp8q+Jz$9y@Eho6!j5Nav$qo%Gq7$hv={K!l-LT`RE{ig3|#5`wea+iq8ywl!m9HvLZzjvN*#s>-HU% zP4a(u9M-PD_**zPcsg?D7-oNmI`-l(=ai*=|1JzrPm-KznqchznrtigF)CQMjgnxi z2BMV0NytQqhPC7ZrS-Hep!C1#a~3OX@HV6zUPCKD=|Tx*gn+GS3E{$9nS$EW<*~DH z%#T_*ny=Ie;bK}LirAv)1kZ*-uKo9S5G+?wYbW%jU832#SHQT$b0O`O6+G2imQS!T5`AcHlSp zRadvp>qQHBR6DHg>-uOhneXLjGS0BBj6deBs=daWHdJKHPYlV*RNT~kj|PDvr4-v9 zaL`m7-w3>kUe3F@O0~I7pW|3x=*~)~fmAbb+7gARsvhB(O2$JX$J0}EvO3oTq95ol zuLp&!;hRrj`Vo|A$)bjQb4A*vHST9MjjFBNyzRmv6JiV1!BQ-GMg=FXRb~gbbplhR z=j-(jna8IKiw(o0vc^)*)w%#pu$|7uC*9$^O`1E)Wim|?_))HaFoC?aS4Iw1refnX z%SQE7I_1LRvY90ZE23+)T6WmnaZ8I^tZuqB>zI+CjAfl;Vz0m--x$<(HMF-qBKcb6 zX>@GuB&L*df!vk_P*!DGo}rGZ?esS|i&6!5x;dMxqgvS}Yh>&i$sFKgZ)t>M=CdRF zqbgw^(e+~e+goO?N$(u7K&ECdDQo}H5jP&C zBlj@>H+jx~y00kYEzs*MHc0T}_cQSK*Nkep;qjicVacjtujJGr83uIe_VkAn^x;=s zwCwEcxRlOMwyap$g*e^9vc=z}IhD!1-H&3c7xsT@rWIwL9|2%Vc!5!gF=j9@hsfD3 zVlf4*bLn#9sGrZA*Oi3&G?C=;m6?59aWF^vn zr(mL~9}vB&XB{=^G&zV=Tg`B^<6YU{xxll6l)9mnHZ2I{q1%QxlB^^T@BXVF<6u*8 zMu*7Ue-B^)hNkB4d^Qu)%|<8EMr{ST*T#uq+QQG)T-bJh;6-o_e(J~ys&~sA3^SV< ziemj7P(cS1;b)Q2!*rj`uTL%TX3m-IHf?SXSEI<~5>TYLi(r7apq7<4G*lce>ttPN zXndjK?&Nu_<>( zM)HrVoVgT_lF~YXYV@ZFZfDjBdh;G!p`u~7sh!Po8za$_ zTNsA}m0C54H%xrhmp>G*y6qD*}F!a9G-R|+zf-h_Hx;19Jz9Jq+30? z=&hH4F??_;Vxb*E)xuAGck}9u=&^6dO9{Fb!z@UCgzcx`xXD9ldQdVb;F97!`luN6 zAfgc1xx9b+vPtK@D?C6_6f{o7Ow?1XmhKv9Wk#{p{JC^I?rnwmE9ig`{= z9QmC^pK+D?lfAyAiw3ss=dTIu>}2`h)YzmufKq*qx2LB_^30#Jjo#(APKdA=8&)U- zDJ*guzf)1Y-pE#iVe;vNc^_DVuE<~&taiS=4*XZX`EQISbwyu76k_ql_BGG+*-drl z_9yRV>3a&Jhl5iy0#EV*(LUE9lU@nykf~F3b~NoLLVc(Yexu6RzRGU%Y4PV9I6f0k z0KXi*c8ucGslMfyuszzIWbU-ZmQAWR?Nf|gxGZCIiG=Odep-$QEdy(zE61fCpLu1g zHSX%LE=NiDCc&JXVnLq0*ZpgVWG(H=YPmcvX%f^+c>N)W;{5LlA;o#o);>zncFQ#6N>*0PL-J#9Mm0X)64fzc>dhwacjw_*N8~lJf3Y-l}n_0)LFn*fC`=};J*Ze zis(c9KEt7JZ%~9;;HOl6u!G689>bN7qgI+%n|Y8 z90G_pM4ij*l4i=kT^5Dlntc+FOLsP*pq{PgF&$OgoEBOO-tM#2@68Pj?vC7mpxp31 z=5kZeDVmX6svcJkYonw962|-s^dOcr6f1_;Al%8PIAmDki@UO382P`Ew9`vdK|h6q zOI-zuTC$cOsG)&Q2JBr|7o*RlM3<9&=y_8Ileu;GZ`QC%jHY+_oySsKd9mSK70m5a z?;|{UPz+}Gd-1KTuj53w_^vjojTzc=IKp+Z3(n`$4hr+QiNBAdP(rMh;Smq^`wu(! zAGjLKC*=}TOLI~k%qJxzt782X0i)nu2S-@~eYLlYtf#l-+`ITBZFJTBsgJO#br&D& zjv?eoqcD^0q`0Q1!_hJcl>`$Y7*LG^=TWXR(1OM5`is)l zAAXazg9eRd^|H}4?7SQq-!^JP!W^=A+APr3m@`?=U&ck?InYh2Wx|Z@^s~&ez+If% z`-uL7sd=v_l#uw&MUO1Whrx(su8#O=^eBTRj=<;x_6ws->O)u#?>#Ag+6P+x-mG`T zdf~h3s2T?F;CUh1i+lgdZ$2Q=t9ROhDfpO4z~t0C(z$MQ`=hTdqkidUl_u!V5HRjc z3W6Q8icB7-VM_l=;xqOep%>M&Y1!rRERUKDC|MsmpJe{(zpl}tr!&O246ji^%3x!bH^m|ZQ%~xzkNCGJHieZd(op1^8_UJL3pqwAY7d~d~oHh(WSXO~g zY_Yi}Gv^|5GvBc_upy~EHW*pRLAk+ej5k9hNoYjdt6JfMaqm7p!H`vbJBKL>(~47>!{=!9c)kADO{J4w zmXcnA&gi@-k64ouBg4hRLM^qv)950@TtjiNp(C?2e>!QgWc%_&A}}lLkpP+v!^Lz{QGKzOW+-^ouwr zCvi=dQgtfb=h-Y%-rPL$C`Hs?+_>8u7lWDAK6mMJ`q4prrSmyDoKS=?F%_P(X4440 zyffCHvlrW>7qagM^Q@1sZGrh{f88b8Xv~*NI|u)wN|L3Ez^7ojlKI`h`|y??>5wG zs^5Z30=*mHxmKcBdNEtdBV%00m`ac%SI7GF;&*YklPvnx_N>QhOY^vco@1Qj|Cd+P zVO}9|-at^;lP_eXJP+aq^}0jPJS36oyNTdiZvm?$v^0~q149A#13RQDEGAgac~TrX zA>bQ_l&PB4a^{^SE{RUaI6!8xHNe;nQmpK3Wz)VSBX-<%o$R^;W z#uFWVv2D{G-28sE?9>|C$-Ys&>wxI_|17-~ z;$AscEJTVOotigr#GYjRJp_ju*JVQ_vU0sB>^V-!fzakUS&Jrxhf%adSDL_`h5beR zd*@sI$yOJpH-ufX$T}6IZ{(pe#OnIlJ=qdpQ`($)R-V9&iDgn1hYbT`WZ_ zop4JfVxRpo6PY%G!Z>(&2Ej;(B3R(CKI^6IUhI4Wm2SX>Qz`eD7`^y=Ff$(&7uj)t z*ZwhfB<+3h>;j(<1&H&D9Uw(cv>pp%Rs~JxkaG*HaPoOa>+(|n;m?3IYm$(A+LFX8 zG9IRi2sKkCLt4$M4=7rd)d2rYzY!{wO`?H7#ZrVay{kp%Bja$rJ|<_Bzr_1Qc|E=E z;s!%w4UVFds4z-g3&SScS$&BOv1c%Oya$uRPhhPpPyN_q9e4?8wEd}bt&I|Q1GF#| zsU9~9K^ciqII+Oz>ztfx`EOp=UWZ?b&RiAKXy{R4if$cQK-)J&zNV^gejW@|4?-2i z2j0pk(?p(p#N5pYN$Fop^kXZ{F0SPB6?#X zw^c|KBe?0Cv;wk_Y6EF=JE6u*3iVhA=l-z~c=xZ${x?TGkP6^*sSN3F{)1A*Z8Oj- zLi%`#DmG4nK+k6GtKQGbnW2k6-KvHqb{>Dsb315PZ7}AcsEal;CdI-54O}|O75*;8 z%PG40Rl|jXgxC2iyChphERU7^*9yYran%8gl2H*W-^~2(sX9^acFjz<^PmM3g}Kgx z4%Vbd=a1r+kHr=PCY@mmBe~s3PlyFpRD1YH=GE$c^@p|ZKN@sp#$Y5p?iL*UYi?xp zRpr|ZGX?1&{gJPc3o$-o+e(MTJ?WQB{R(3mqUjM@I=ghM5YA7T7vs}B=@<70((Aa# z2sYQ4Gz!k~+*+mn8ek@UP>}*ROn*Yn9ibLvv`_=2nU2TCw(cQKS-mv*ym*5>Es0Br zkDi9pW}Q(?bD8!xnIGjhe12tpE&=TB9;KtYvXU37KYf^6GrswYJoWH@CYVj-&ENJW%_Cb}1-z~3ii2oh+e8NZxohw&-=_@*rzoYhE`6np;EY5qYX7-oC z3@@piZY+;+*!o9Wr93L6mV`BX!QI{LaLn+4d)oSGoe$~|F2B|-hcydSJs4Lb+xqb- zpYPk-e@{iAGaw4IUtw{Ay_ zGSsD9ir69ltB3TjM6}L_br_d@>X)OM4XPeYsz}8mPj(S&0kd) z+{V2#G_r-;&5-O&)L4UuDJ1k&%kF%J#Pldbd%7Zw=qzW86hH)KUy) zxp8k}X%1&>h)(unHTFwn;!F>H7dYaENssEaPIzfzR_h3cDXGysZ5lI6p1<_;Pg=T! z77^Lo2v1Y)CC_|f%nE86zeoH+Fgv`Rz11)cOfg^;H%{@j-8(sICo|bJyvuaw5)AKr zGwxagjKee$S&?4&oc-WY(L}-|mkmY7vtI13L}MLi!#2nVUu47P%!2Ur|I!U9>=iS% zziaU&MnScZPE6^UB&(XqUzwFI~78uhdJVH3@{)I)%lK1O&j*Tl(fn3v_ zFs&ODZrBay4VwF5(#CMpMK2y1__{Ivw)l;w!x`;9sP+GUfd5_OOIdpQvB~7S^vBkZ zfmdR7;6r6uA!3~zxPBR+78cO7^frLxWn4lW$iFu@ypMRvJY|c&n3rQ@nr0Jrs zH_Oa>4E=cLvD|0}iVZDF`Q2dTnm73DzRi;Oa529}z;rou#8sZ|$hJ`Quw6sbC$EbuD8*O#B5*yW>i+WV z-We;r?f5STdHFisqX{jAvF=&uF&!3mRx7=S#VFJ*o~|eb75-{40h@2bpBV;|$N9TT zfP?Fj8t#{}duUqJix$C+MD>A;TDwfv`!E$OxaB$CR*v-V@d)(IfD0F5vsho&WXjdw zxU#8>D;1D3BIu=k!~d8(NEQjsIbsi}BZMUCHgQvlY}=t#j08u zY&<>GzdA-IaWEYhc>z_$X(R(nx(!ZBfY2TJ!z2o~7vc{d`HH9v8@fH_9fAWRsP=tO zm@E|6Zzf*i$&<KWla6tv#8nZS|m{SG{iV`=GZSc$#7fVUYy z0RJ@CJV%FLiOPn3V9hop`wWi}>uIRpY)$5$a*m3j*8i(l(4Ymu`o>5Mc)*DqM8zRmg!?XqO?cq!6d-^rgqy*R zJ_zK5XlD~cbxSVLgyCJ&a4R3)V~tkRwtGQr1CLFmdpnkjMzs_75-9{LqWDKr$G~)P zr~+leXG%`(yD=Qkad~9#5MK0B$LT*{NRq{5TG)Bz_30lAE!nFnaJG~~;MGarpo&~> zF;g(i2=#R?2^Gpd%ax|wXXKB|s?CR}BfG3E9c7EE;#dMnNF{h{nzYNv16wJu$*?=h z4fi97jEMnw3n-Ngf(_v5QGcL`M|(m+ImcuM9c35Dokbx!@j87~#LE7YV;r}fgtI)2 zn*0!PXnj7bZq>6GT@^K6A#o&unO9jTc!I4+A^uMPCn>06S%SJ*`G7_{2GyChQ*9yl zy1p9mh6$UpF>id2VJUAdJFwXzo;^5~Gq{TThUy3i8OvX9X5lh{)k8s^=_^^O6{vXO z?WY-N_M3I8flUIb}38+;iDrBR#!2sw`y=zvfomT*c8u|qBl^2Eq& z>8y=bCUn-Me{4ciW5zd>D3Y*>^&=$vmztkJ9%1cpu- zUvaI*s3pb&?GxjDeTh-gKuRlvvs2)6@9c-{UlD%oEa{S2AO=OIbyey$8Ifhp3*|m- zB8S9U>dVXs4(AsU1Rl1Vr-mTwV5sDMp{pG<@1Xy6;v*6X=)!fkCd0||6P9~r9To5_ zd4PBIFwA70VS)pG3(C?Rzn5l7oU!{NC-_VUp6>&_{*e=FByjSU_d|Ajo&0 z`}O{h{^#Z4$1JjN)W(ei$C7s(K;3et5^de+v|QNiJn!7uMrY~D<^ry#974CE4er+K zeLWGcJ+!Vh2jxJon=2c%&xRJ;bOE)cJIg&&8AYpwoPu`F)8nWYjQKgw_ti{dtO;_C z-w>fsltcLp6sj+%IBVs-)BtmK+m=w2_ETG%AP&_-^$O?mpE{r^2_c z-1h%SooLrPlCu770z{*SA@sz|DE{s(2kV(c6AdAOO%}RtLz)&bjf8}P7$m?bIKlCG z1qXzc68ybkzpa-nhd=o*e4hRX3jHsovgF+Gpdct***?3Rq7F1aa8!9Xk!=iZp)>X& zdVVBZ!%p)@{hpi+Yq(k6YZ=8KTfS8_ft8%xuGx5zqT1J*7BPBP^K}H0^q$ zEh=!_5jGpPm&Dl|c#DWFA*pl_Z z=t2v}bSjHoo~B3O$-xU4bpC<*K!14@%m}*P9v$DmaRx|s1XKni3enGlW*XMtW);sl zf5U4N;GH(sFu4xFvJ|YiRDBOnth_g%QSg+pxOaxD!|;)f_Dm#spoxA>`NiVjJi3Eq z+aCPx4hPzOsXhM?Khw#0$9wB)f0=Vi)w@Rqu&YD)Vo0AQFTMsmbDL0g2@fBdl_09n z|AL;$bU6Ojp*5_bu*y{-x*tU*k7}thK8TZzj&wqX_DOI65(>jbqgeZBi!O2+3unLxIfow}jR69ER8)6z9H7H4jhhkBdI!LDY1!aP$@ zP%8*g-J-PJe-O?@{UDKbWElJ&Qd@RZv|=B4T^(9@=; zD;rc4F~agV&sH_GF@ZS0xHBcrn=d(x?8^aaZAHYL5buX z_Xx z_DiB2Mr2|A){^Pl#>%SBH4R?CV5C`4qCnIeJNXF(HTFquGo{Qw!x+IyVE*m+ha*RW=+%gY2Y~CgStd z9-_JYsM1l7LmlMmB2eZ)3Qxs;GZk46Ly+@jk!Gn=f7pTmzyYyYb=#(Z&?)B9xWyFu%lu>5U1En&{$Aq-gpN~!%Mp2h zQLi&+M0vq8!tW*JXjphIZVJ?ld;O`Yp$=NMhyScXJSxq1#(+Lhr4rwuxXB~S`lgV)MthAQ$Ab7zi#p+@*HXN4uN!5KFbsCg9<8_ z_L^h?sX-s$i7dctvYb_CccU73j0nwduk+F1Us703>I4xpzl>O7)(qQ5QVWVZ`CBeP zu)@^!e5k}&OmdWvu27-lH^9TDEfUSuCiyI0b)Kt_aU>F6UTI~a$htu}Sg%ZT!Dd{X zr5{7yefRATS$$}`t%D7EpCE5^zZ;Yi>Jx=6D5dlYxg-N?j>TI=40W2wL!}p!40FmC?AYKy$sm(d>ES8-d>k43&nn`9E@c$pE~j|dc-a{pMIv!_4^os&85*LT^Wlu0u9*hU<&H>EqseX&F zyN;n@>9VXBQKx9Pc$R5xK(Sad?@1}EL=gWa%A}u<8Ic0k^H@iR^Aa=!RvdB^u$IL~ zre+H>p99Kbix@*UT2E9;VrryYZPK_eka^K|XjM0m*W%II+*vKtKr^Mz)x>VoHBm(JA2+Jay?8IQ0U{eMkb4zH9cc~Eg9d#|(^EDf1PK$+i z%dHDD&BDLD*U)g38Qk;^gSFF0=M4%s43Jp#m8xC{5pwOZgC~QOIpfAKDqk~zI*x_t ze$$8@_zV#6V1F5>wMs}3m#__to|kPrVK?ALp+?UoPb?|;6iLs^i8}*&Z1#T$SF);ngoRcUfIrz{EU9PMm8A?^EyZ^1og&dZ zK)q%mY(R6kKBKRSuU_3swuIry52fsuc}oR}8K&eJD&g4MJ_6%TV^Wtn7wgWkqNXrH zeCA*IaFT~K^rMD+fvJi7@JG!bAT052xIbg`g|D7n!(Di2+vF-xiJeI_WL=33H_{?z zm(m15cVXFtAj+En>aMH0!%Mcpn6Q73A`WL1RlQOv=GR?^?ZX~aYL5b={5Z)ZF|XTD zulCO=s%ycy{L4~w^+$9JB?wlcUOum!@w0+rv`x5%ne5#CycPyV=y+m&g@0oM;p0;CqtEa!$;5RjAj)OR~?5 z?M))|KH3iXHz=(u@)Fs63G905_f>1gJCG1ah*zN5UC9XLwMFXD)So`4&QA4H4D;R`>r&1 z=XEJB-zIuUCkgkL&9zdG%84@#XRoRIlYdCLLv>t5y18>wx1iZs%d*Zg&1zT=_kxW^ zrFON2eYN&w_t~StL&|=3c1M$~tfd~SREtHbO?7sqr7{rP%;BpU(^ytqu9TyF^7aJ6 z0-9QMtQ3CTGo(<(h~*qz$`;>2f+e1Wtkd!T`=B zc0kB?LuvSLW=vj9M#nT9ew5<`tNXXhx;KwxG$=Mq1dhol>MtTU@em<5Q1TmxtbJj* zp%D$0)=uF040G3W2JDP|PzRG;d$DQqccJ{lW0h(*j`v`7ibJ(qrDIi3y~ZmKF5v6# zy}={3YmwYt4gSOFNzJu7%Y<{X8{LNkiLs#8Sy zZdk)edWk(6NcO*tP$b@7w4#xocy4)=2SjvrB=>;aKB@|h+Y6U z@C3!NPW9HO^c7 zzuWY`5tAZ#^HIoaJEV;anP_oQoz_N?1P^VErJz!0dn8c4<>BxdFi3QY}29C zIR!obl?wQh*C99zYx6|`IGGkvBa33V_@yHqeHdfOFcY1mCmQxCA*;u&1bYN3k_8yY z@G2y~7u2zh2(sT8ut@_V&`Cz)E7w*x7N(meo_SPxeMCy@(JP`XNB?-odggv>_62N{ zlglnRe%>mzT0GJ73HB=AbU=2_S>toX9rs!Lj|`woJUg~jy2Mc1c|$}5M{>jw_h~k3 zMqj7(-A48>e+_fIP)4szoW%U9mN;{n?HAsI#(; z`G{26@IL^$Kt;b$Dlm4YFiuye2dR^f0jYJnyN10ZZgn3-mS&D5hWT*GBHvC zT6GwF7{zKuuyutfSCf!}xfaD*6uZ{c7SXH4gBA~3JZSNt#e;3};HWBZu>dT~L^(7M zafscW1pwFz_jMhvP#UXHgZAoz6J962#0a`YPQ~#(;2|UoI%2lL>2W6*Fzzqcwk#Ck ze?$dAGxeV-W_t?0yeEL&EO4^G$pR+}oHh|S?NsGMPIUj}9r*~`Bt|YY(G85M+(}kJ z=ZAQDO1KOYEf(5O+I<7Q{}|tMv;->C!|EEGC9_o(Pbx+thOiK~MHDuKZ~b&0!8sE! zZA`hBgI)T3u_ro++;KumAdW(&(iSR5f8Z5SJwbm9T&C`{p%YCQlpE(@j8rX70U~T3 zB5+UVDhZ+@7`>D9JrcuH|1aL|fe=&cbdvFo|~!k%I%AI`^G@Eid^L z!<8eM#IDN7huJVXS5GUaz=6IWd13QI$k8t+L)4K+ZCzAf%_3=wq*vqxU1w^GFMIfD zWn)I_;1L3B*LhC&pCp&PDLG~?V1(J!7ObhZ=`*ZNYHd<$lUkc}6K&GnljlPte^FDz z0wfENEI_gVX%hj`epO!QSkEuxv(L29q02t!o-fbr5Vx_vgnK?Sf{p=~nREWh;jooD ztgDWqS%0+!kxylgi~j0$^Z-Bggb+_*-4^}U)&pz}9BbfM1IHRT9T_-ps*6wwrV0|HyP2e0orZFwfKF0y{~s(u z)qs1DN5T8In0syrZwa6we_#P3{F%DnxxG=!7|i65)|$ewH5H+62Q?Y~KOlal?o?|l zId%2r1m^c2uS9c~$*!Y;*wj7O-(8n$wvEh8Mrb4|BeEh18Qocz+EP{b)(O!$#W#qg zk{~G`$rku3sL z7v|-7rR=i2ViBVm6$aVcyos2$0}U-ZePq#1ud4PJ!zHbCcCU`IJQrIlO^l$YV%co| zJ!5aTcWPDXAE@0$`RUqAC{notv9vX!$XKBb5|7g?Dm@`7ZF9gGofCN{?EBMC%EGu& zr7%fvI>=uR3OU3Ce*`GR)a~ZfFXJ%e00q?XvM&&E(~qs{wW`;2o54<+wFw_akqv9^ zgwO&Plj()yA$RV#_NwKYSt zXUeaZwG^#IXC>q!37J~hg?Y@rGuie#RiP4*pIw=47Xk#Se?9R7xq031{VwAzj&-<& ze%x@+EZX^7G1&^zryE$O>yOfObq3#agEhYbDML*R;00tApZ*5=%B!Q3+Dt+^ z%Up+~_9&p^pn$W?8v%l6@EWPZ2p%L;1SsjJ(QtyrIlUqRo~ssgdQ#DuDxVYsV@()x z`#NW<=8h|ZiHjX5JyOxdNHhe5a@mF$fecdcLc~1kf4iw`k$ifKLga$+J)i_#5$IFV z2wlAR<0ej z_D=c7fA9{kGqq13FTF+i7Uf%%Z&CgxqWry@eCh%vE|F6`ss6ASzb&5cI0t)X_+@Cm z9?93_0xiSwoyLVU%hb6T&Rf840lNk4PZ_XV2y7v+g}@d9Zz2SKQ`-Gxe-_06C)pELhIxy@%ofvbAf{bsYM%g> zwdl~ILyHbAI^0Bb__iY5_!q=KVa5?@lR_(9xda!!1TVyV)?O<@D%mLsYh zrZoUFWm-Xp(PUb<@e;!;v)!Sd2AlrOHU-c_&R+Da%| zf62)AX zAt}@-XG4ZmL0b75y!23rWTrhrIk-n0KynWpI-4QFqvU;<0dX*HJj|ucKzgIC97vmL_BE~O?@te2VzxyETCiWF`Z#vKiY71{01f8f32 zz4Lu4DE#tuS{3O`@Tao2o~j)=st6`c~^(t#7sdMr-}uicCdPeH~HX7ej2N=5=Lr zyVt?)))96WDsA0x&E|w|snO0vj%I7*3cB?~7Kl%tFYq>%ih*ofN7x0SpoYo49S9im zC$CkRF(y;BdXn6z$OSlVe{Bn#a)9NI&`jkyfaqD5n13HaTlE&2$ zZ(j${xkhf>i1CiwzIick*Gp)mH(=+P{`c_rz4iZ}x_Ox@@n!26k4tBx857$bg*5Q&3ke*=iatt)crA;1FU z2u^XM3tQwZWn-E93&|wFQ5rMR5cfhlpL&3j*Nz76j}5YIRJgEnKNV<_v9tQ+b?2#rBYYaDa%^H-wVcN#Qwh z*%bi*z{o=FtA}~zrL`3#iNexnpSP|Ecn!XJhyWUJw)J%~kpUwDD@q7OYREFQbtI!T$0+ zaG;ogF#-V!HGI9r+@o_YwXQ(EFh0r+iCRO^49G6k0zmE-_##+P-ob`$5COMh+;V_a z@`V_6{E^Z_*LOmXeJU~V_&z?}o)F3amB)NCqr8P!<|7p!HlF*Wip?ate$=ipNT@w! zlNPLofFR=be^%!-lFHo$)ms!~QP2`7=xxQx*oZa6T%9B6-nWKBaSK(rC~~QR7X>u5 z7~I6I*ZA!6{=hc4Cq0UlJMgRz>=AunWdgOReAit$ucx@#9#kB)l5F+~vzAtus9Amv z=KGJPLPfMyBTNbnHWw$F+LfGj@|#*8F}+RtQbTLnl^S)+)9U7D=*!Ocq`s5MNuA86Zd3uczSFg( zHYzo^QzEr!aA#kxk-;5@tz>!?A}13OX2_Zs$O#eu2$@%&GGjSL?f2yABzfF0mFOcQ zMB+vF5#g!F6QO~^sh-)AM#LArz*7R1Zu!}}f0V0YSSvLi%2$zmpr4VLdJrj(X zT+Mg2-p|B>8&+gYkYr*-Pg~(G_naP;UO(pXU8~1j%szgsZo+{u`%#Y z`fX=^KV^pBsXO4WO}2M#%c$g}eiP5{t3cGzI%q6FG6Oe@GTT&vQtKNo`_#=Ge@oWIW8mUxBulNI#rj#SpXJ&4S-Ras6N=hQ z_Y~w+Ym=%jK5}iMILq*Lj<_|Yd|eUjZe2ig&B96xD=ndrpsomb30}O)w0SN+p|M9!*6A)FB|kiS)Tk6B zt&gv~&Xio+ODIZXe@eKZ2u{ljf0=;O2+AH z7Aae#Y?1PFL&}?)5PJJfUB*2vBHQPHNHt&{F#Y{U`TnvQU|pChqSRs77RTz5+30E{ z{rDBWy}Y}>wF}Vt02}!LANm-*1vwVvSdjB%LC(fz1sV?OGU`QXQs(0se_jsfs3ukx zNoRT>HABrR&ZXvuYlG z-Z_p?)c-=w6J6)(H{VCU#K8p;Rhy;2&h@*Z1lYyV)yEm;sZuR6c|%1oAN$w=*XTaJ z>w~JhE2j7c5pa4OKcCPLe=y_(a;1-b2B2z^J=5zSax2BugV{-zz0i5}kvpP0BmQqP42C$kyYs>u$Gbs2=^=a=->}Wr-I2r`RwOvq zJkDt-6xh+}ar5*x#U?7{<`@&iZ)teFr8VbE@L~po?@B5CFz{3qe>S+QuYMQ!}l!Y&_vM`+Cc9&r|#ZOrv zsI-WI$3*lOKrTM|S;n^6dR1iBrvf3LaVo&!s3H|$!l0ia!4t&z(dqFL;x5%nBZ=2Y z%%wW%*e6>x5EBWPf2JxYGc>o*8qu0%9+a?2MqBprC;iUf2>UM$&Hz|!q3{s-NjGI zMOPLv6}>Q;J-NKoJ9=vMsQtJ0VL`eTqum`vL9?B!XAp?6Talzv3Z^4ia+bXh72XYtXXxVKJD1f^*=5ZtogaIO)mlDEl?xo#}Uv6Sj!DDf4$ zklcenU>n8-e_rt*nIg7zMXpHFG7JJABh`4+tiAXHhiVG-t&1vvjD~I@oVN8_Q6$&u+8j~xc+V1WO-R$=^J-ni!wcLuoq-ojlKBTks z@6>MpAJCs8z1jZ(vQK!1dGFw@{P7;4BN!wv&q6fAfAd)s8jyq-oasT8#V81~u5ho) zcpSKBdJ~TDjzbx`<=#D;?%rMB1^=Fq;qAovdvA6#^k(#$-;Uk8Yk0TA8pjBzQ8(Rr zPmQ}pRXu+u@-;o7O?xum;cv8e9eu~PTgbHeNc8$^TrFDc53+e|G0{>PyHkp(DC)8= zO$6O%e>N4ycW0M1eP&b9*fWrya;)c${5U6fm>*FW^$rI8-nmq}~|)<@Y{ax ze{EidP>El?%<^j~yVBCj$#8+Fchc3P zmSnOF#jkS&-LJ&Ik9bz@hjhn2?beif7t^d4fd}KD!Y@j6DBS{Xm?Q>_Fd-#f6>shn{yb_x)c&Wt<2*q}bx|JcLRELtl23}2TmchHGZA3V)X}uIA?1YCJt`O_} zu-=cVOQd51x*-?0666_^u~~=Blt45CX6HK{(qhA zV%R8|$BdGx^IqF8^N3$&K}2mz=+s5kW{a7)&G}$^INFPh?CxBw9}(=(8J}{kA3`6> zAJQuqohpc(cE1+H3O6~V8@1gOe~85-Ha>@(Lp5f2D4ObKwU#(OyJ@gyzakaBQolHK z=04<@Oof*BTOL^}G*bm{N=~Vb@zy21MnoNNUyNz;UDX{{%eLJD(3Fg8L3nbJzI1#t zx`Pe}PErOiRftYN^ko3#g~+_ED{?6ijE>fr3zY)N{jG;W6bEO7lv9WLe*kl#kNQ$0 zU3&gVe^^%!rcXM*zMs4$I7w`vowA(``%tVmzQgADl%FtE~K+y-XfQE zx^jbPb-qxE7CYaT4nc1u_hG;-fn}_7QOCY$gPZ z3^Y#1pk)Hwg!CyFW~tyZe;6VV&Iy2`0Xm<0vc?~u!L5*PS{eo+y}>SWfhTiV$RN0H z9wNYjzK`5~=F@>&?E42-ZUfi9tYeuclGR40rAey`d%)snttEp+Csn_eDzpjD6}{ zGaxt~xk5oD!&O}!MaH=kQhmBc3{|wSxbl0UhM?oAl9A?0N{BM=q(V%G9_nUwX%-+y z06#aba0^3Mw-_Szf8$=Ri--jMR1#Y~is)oev>fCNi7$UT$#$IiG9I3KNK}NRSi3Jj z+`ae=qF;iLSRk3N#G-Gimqs)J*&gHR$QD+d6q6$rHR31)3~?q{C|)QrJ;VhLBw&mb zir^G5JQHXn6%?A(!UVW@GC^`kxx-Ryt9oXxi0rRyg47F|Os^U7rC71q3A!S4!m;{X z@lXYai$N$-W#noyF%bvJ$rp5dcuP|b`E zoSjUN!{g?zNRxkC7+(L+u;l&@=yWOJNek%jXuNB+5jsAL4Q zIpe^CH(FlOFhmXqL|9o&t*I$wS44(7FwkjW@RL7Fk_QK-$oLrq=e0i5VR!oMPG844 zK29gxu*E8ST`%%JbTl@##z~I70C)WbGh&CjE31grGGX9D~x3MErsI67j{d*<|KX6 zG5u?*&PUr7m*z=ba;!w*4R%p@M13D}6hi-y&WYRdR99V#brFPT&~=e}hLM9V@ZT!I z-I!9pB6Lu6lW%^ZUazCAM$4D=)m-H-m>9$0!`dOFBdceaNOqaQJK)3x1s`)7!f70y z7hVwu5`Tahn3Bp!x!8{U#z3oDFq84Xtw z;vyEVkp>g3rznUVdv=TdLG@`FgBK>WqL5LxG92%C!aKEj*=!F+U#iyFxz^f2wHc=D zXjpeI)iDxCL;HqW>bj(bre>^ib$yx7^7q6Rb$=ZedSn6}^z)a2ic3i9E=E2#&<4h8 zh91Z{nguF+)0Ho>f#OO*^uZXiB!D$U4i2zHnldUmy2eT>H#vz~ws)w5o}6(Tucp=M z$`zTk>vjR7)tlyeGbNY`^O${Sc%XL} zjE!*CY^p-d@vWI=l`B4kx6x^w-rBf~%kS6Fm|-2D#G2}tow_U6J|JG6Tf|7WM75W@ zjQ3TOyiHM;-5E5gK^P=uiu+GH*dkG=kAG4AgQ??R>Q-Hq6XdyCBo;$AI37}$?B`YU z6h9l1*r%C)%qH(y?wX4=)ndDK*XaqN?EBP#T8_3q3V1HdyOB{|`Y6Euz3bNF!2qF}QY-l!DQE31jWcZ1? zzZ`-<)s+voz`3q128t(FBzl`_NvETk&^d9tjZRqF2uiUE+bV3Uu&u&= zEQP&acb`B;SG3&q%(k(de|iRk@71Q-k8U*gqB{s$5YT)_wJ>We7f~`?rNyG}r;>?ofzyf3Eh@`; zP#K^1h=Vag1Oy><=MHlFaepRLov&5q=uNV@%Ia5Sj2t>c48R+ReK_{fvq~OXvrAgH zzDtXkrO=aEAa;h4TrGx&G`*Epi|2MJOQ=pt@!af#w{;2ZKOlbOLp*CO)@1GWdwjCG z>Gqy1Y$5?=!A@mgG)(jTJVirV?m6;F)h?cTYd7#R>%#8cZLAqm#(&$3yns<56ZMmK z`DGn~kLLgszb`lpdHm!8$vC8gw`=DLY-p+IaXbyHCi5kp9V*xv)McZI)K`0lp{m}s zuTX1+AIrdkX3oKy9$UEt<9RXj25O4S9D$B{m4*}1(evjDA*}jc#tT@p)D3)p^|d$5 z<7f5a^KlOD4C@lTe1Aavi@L37nRA8tR!a1yu!b{bOcY+GLZ|j{p4@shmZd|t8eL!& z-S(suQX|z>YFE^MkHTvcTSC{-3C88J>GgYuK6S2-kq_@LkXW5N!@iIo3=uYGG6m~r zOwQ=7kP|W-Kb~NjCGAp3NS)N|EJR0iHpBeLgT9Z*6v=jD6Mx}74X=M!*Hk4*H}!*y z8NEgy<;_fSdHw1zMCk8|cc)V#=d=9nCp_VFGAV!gjxjVF`}gH<&(UO#{PK5~FsLBs zU-Q|&=aA=KssVg}>=MobOr}W&^K9)S=wpYLw|s^|hGE4xzlM-ZD@Z!>;ha^BBb>85 zt@_m$8s4I5Wq*g4^Ke{2=*Rm2g>Hy%s_5~kLw(3AUVrs22n@>KU0mOX6>mHkURTjG zt(uxo;vvCgS}{m(PFz&c<2T4rI75DJ>HX^WPH?cjyDR;-x{wEW0+Tn15%1CUw*7+@M~D4I0(UvvY&W zdFkAsYEF_isF@S`jcVrPL4&#lf!UyLR^~OSn34MpD(19FgPK{r*q~xYL^r9I68cT5 zrSU|AdTHI>q*_*2G^v?Z!cFR>Rd9oPMa9)Fn|KCImRw^}2?mV}$TEzXx@W~C$-v?Z zPc}JG_kYf)F1y(W#Lppd>5L%8j`0*R{ywBLwLRY2`m1iT!R_Eh530=195-!ZF;){& z<2KE9)5DLBs^ut?~ zKxI8L#;mKb-l@y@RUs8Fv2%@hdtY5mn`C?bEf!-X(F3|*y={B8#~aAdkZpiWkqdwc8q}qvu4`yfvuc! z`+ug5evAlz39>!xVRgqrKD_6*PoKsPA7*LTHWb%hKQbvsi|Rsc20)n1IuFI;Nc zB6dFs-p`1lW`o)=ne(PDzmDJ>eJ8*YQhz6Ep-S$&(gi+4UcPxC@pd77!1o`fH#4V+ zs1-}CZ)VO7)9@T^hAyAdYX-*9xt0fJBS{5)Ke}Lnfm_Ty0KrU56ed%Fu4$;RZjJ;r z<1`3lT05RfJ>bchj_$B_=9?MD8DG*QRd>H9tcBL8yH(|;L5$6>9}F~`fXh@AE{6qhw{mik zr+0yrT)!{Brb2MLF5ie^-*Ycih|lJQU3}}}m{2oU z!Is5TOV!yT;BMNS!TDdxj{NQSjDVx` zmTj#-<0}(yE5uFDR+u?$){H`o$%w`?mH!G3X~MOkQ)be7SRvhuJ%2w)yYhUg#ICC> z<{}9B_U^&n!Jc?7xxk7=@BqJuU|6F7p{@$aLAW zGdM(%>Xn3bQ~tp;Ar%Sp5A;mFjB$W2QLJA|$#1A1(60`a1n-j&8#fmxUOT(U*P9PhVOT@R;{EAM2K!%h?2$E{-kaR(L%+c}^ zb4RW89vN%Zx|A<0>9z1CpRMBes_Blq+QKej%yEF{khHxIQh%n?N)2ptjJF$g(+4{_ z)))Hfq!{K{wGF1tXM3eD&a=wB+V~XJ#^!@_LqSi~vGzFKoj&tON9|`TgAbZ+t*hyv z*K+%0*d;RUQ($`^#;sPn0}8I{kh2NZ=BWN8E`+EFhzsS3yiZEqZvcLoXc~+K{uYAX zEb#bd0Y9sBe}DAvkN*A9|EE6sKNBVMbrbx948DFBaD0c<2WorJFVR`gasSu1-(_^q zmZJ72Q5fiCL|3bxB~}{a-Rs(EVF0Ka0~gJ-%&@JRYMqqnS26_NBxh1l@j?@n)uW|K z*F?sBwx(W1T^+7pH}@;z_8W>ijj*byjxHOAZ^eEfdw)kq8;5VyFBEpF)v8mLbs&;U zET8Ga&a$o_iE3Xp6t~nj?QJ#p;uFCf!{{r}uLda1@@v_6F>i|0RLMWkveN;(#^QVZ=bg?~A*RxIj~f?xCBYtSr<_^lYdtKi zc>eo(>wn1QuiKVHVIs63gMIRH6y~aLa}^V@EeUIuyQz(-m~btg$`QX4MsZQKscqz& zTUNH*ax3fW)uLzpaHVH<6Y5P9e2dbpqKGQC*U)VZjrH`}--nowFp9#hBh256KOFU0 z(|m_^)MB@sRn?T26fFUmZpop6m`EgqDAHQ1mPFSK%wRl4A%GHKK@-77jqMisrPo`Z ztKM2(LuCtVRS|~~-F_g5g(oUH-!`GpsI`6vaRi4ES}&r%iqv|7R6RMu<4=?8YDowC zMO}^d%54seHXdE+Ro6@%pfHGi_(mDn}B~>8gM2g0$bb#I63hAo=*vuQZ4%&9`26hdkN@VQjlqV*G!+xOHb=%+OhUT2q}M#n zg{=b^WO$nlP~6+!d-eA9-kZIHH@ONh=JM;ANUOvBUD;KJ2uqk$ZB8RNXX5Lm9U>tn zV>ymyp;_Z}ga{hp0ITm%_4o$GG7j!P3FT0S4}5=SD71f#_xah?12xUl?PW>Y3W)}PdslG8ho+mh-o z9cU8vp7pcc#i?S;*<7)edc;gWlhet5BcPd5d93g$>t?_@2bM~TK4%y^BJ(mv$89P&_h)1 zjB`8=6k~oXLV`OE0v05%VDZ{nDKxl3PyI}oVh4v^vE!-5{;-f(-)*`@Os4e>en=Rn zPatODOZzm}L86*+&XwL&(FZL27{%vRBlw>X_Nf}XjwdT4;-lUqnDB%B8eQhEZz+?2 zZX#R@RYuhOcrX-&{Vp&Rdf~oa+(o)7DgrO;cTQvYE{f8_xDL9I2CrrD=@km-9TGcy z@y(faPu4uk-=0-Z*St4{ETe(ndEV}$Z{5ORc!T_`!*|7y_c14h-TI)D{%$&d4*%V_ zf{UXiNBXz)wEZW65$4Nx;s48?%EYT2MlI@ngzOxX+%;e?!$q!sm1`m2ArHzWhQ0Th z+#sy)WylZl&)bvdX3~G%h^!~4pRr$_ASt)s)AhH{8j?@Ts9(qB!&>zl#-?ktzL<}) zDG;i*dUJkn&hO3ny*a-(=Rb8-y}38%ucP$5S&8&^scyv8UT5;rb#j!}G#W@6Tkg@< zh1R<^AC&s$Y)B~Z6~HJ+BAHfS=pV*n4H5 zjFSy;Dg#J}?vpxj9~`eTG)^{>U8Ru4=dg^b9fT)54e{{fe7bA5HyY%C5}U%rh~Z(e@^x7S$u3%HLiMqh8QMEcUW zoE<|xCp0eTpIesitb`d;YeND4tSiSQ zl@6d4bX=E@*p^MN0$I>>Tk693KDsKyHhZ>-P77-~O4VLWESN?u(i!41rK2(Uu?}-I z{#IaPnF7*K^f=4IS6M4W9&OSgZrXO2{#ncd^{ z?n;2M_4D<#$kbDXUtV)TW4#1EkC3{joV3SXhp$Z8Q!sd>I{@1PpOiUdgd>h(%Z|d7 z*D8ZfX8^_sU=l=0_;MBgr-tX#O$ZKT}Y(g&+7;-ERpd9-0od%bLb?s@;J2{=iQ(H9i6stde6 zQ(x1lJE)dVpKy+IA4(H&T^71{!^)^>p!M>|dMJ9ddX*Rsa|?e(FOEC?4%#PBj^|z4 z8T&(y`yr=hu9T1DwdEehxwX5~+Pn2c<)jr_-SG)thwM zWOwn+b}t;f9T^9C+%$6^8j8;R!c^+Mmuj5qWuZq5ayI?TM!wuT7axX6N~cT`$23G8 znj$10hyQwG4;z1;d{3u_ea}OmX0xU-^=+Q_W#8AYn}9Lop?}#{=8L+HYNr(V0S>p0 zaVP}+Cvr!FE4ct1B)w>;OEIq*carh4?O6UJbOr6QK#ajL8UV;xGQ(sHFb50BQeTAf zZ4VFHehs|^WaJl3PcubmEmxu@oQriGW3l<^ za+raL(kTi-GFPnQkzpxq28CRiULJ?1C`n*b9*Nv3aPNC(l1 zuAvZE6KMkLoRc_oCRRNRc(l|_{hc5t0Zy!rpnDV~9EEDwm*D*K^^FQqQxq!r!VI9l z6Bvoc(hO{3t{mfV>y~`Qe4-pH!%Fqlh#V0{929VtnleBao zXg1j#kx z2a`N?8-Hk1l^Kdj5oj7(Ar?Y6rM3k=Ns%<7@eGAvxC9WSb`A)HIuU?h)j}{DyPVod z#Bm_rZq8vKq?u_&4AyU2Bun)D31pM4{GqX%&)?P%R;f~2a;U6R=3hFY?MPA9og#V8 z#)6nR&C4*G8*1mxcpuYQE{_J43Zy9bMTi%z-+z99>0HeU|Aa-VQcS@5DN| zqJNZkhS4A!IHpWeJXcb^yKkE^FNgdHGV~syBh^>&XIEL#88$nL#h`FqUls_d6<%$7^=gDo@T|ll%Hw#baI>^>YbD(YD#9)Q2e?= zF#MB5X$BWjuuF`MR&z?dOL^9lU;^W@UVq~kN^~gMqxNudxEjk@7^r`k`iJw4!-MVg zKOusylcCV8QgP9b`;Q)Xl0?yWv1ObJt-nn1Br%@p0tp|ymc+-qtr@9E?^0f>9!%Kd z=bBk3PeBcN1z*9~t!K=!9Ct0}bYHg$Y^@kap_iV|73^%4_?cPM^7b|9WJ}g%V1JBY zaJv1hB}dDANIBu+(q1NRs)7WBu=5=oEfUv<;LGHcSDG#((%gElWM0eB&WXi#Q$G`Z znG`6kh^mT~_Ty#5v^1F(v;MPAAm&%mQqTNWXI`7~ZZ=iCymNt7sCWKBNlMT2t!Jr( zovb0x8PZxHnp4Ze%2N9{6CsjXIc?JFE&Mj}G7B8yEg4)c@pJ}Yz7K@1Bf-tt z_>9tNGGFP@NxA6GsbhD{zM&#GZ1C@7oJ5pP85qJ~3X(bC6huOxDiE?Xzki7GR47QY z%m-v)kztvCKR|e{t}%*A+Cj3IpcolHk+I6(l3Q}|=gsLMke;AQgL}cxqZ|ZfKhG_J zApHa>s%x3zrhJ~3+&VA#T`YtCEjj*l0{8?H?W(by7J5W}32^v}GQkflqE~thBvCQX zpelb$l!?;BEFyFMGY?AqZht+P%Vw4^Zo6#CLsILpk-Z)OeP31f>wjSs(S?bk{@=`v zAu3DZvIWX69yNQU2c$sYmPpbRNb%LXf_hg_?+WT&L0#Oz%WvTi7C|ZRNOb@avj0d3 z7uBgN%pOsZxx#wo-=g>2r{!Q$jh{&4jyR}EA==sc=t?{eHh(_q>pN|*D?g@J ze_ZUCEzLOA*X>V$6^5d0n)yWgWixX9ds{#Ane%NEI<~qyXI*J*dGyRvc>w6M+$HF& zC5Q89zCxGB(o&}#@e@isnIoox#fDt#?kXTrqvy!u77}${YU0Zt{p_*#(jONtU%lGP znptf*7d7oqa)W2tm4E+J7)Q%?YJ#rng!HT%eR0q}Z?>BtjnyaofOsVchQ}_XNj&rx zD9K+7ioWRr07UaHZ>#B#HngSqQh@vLqR72cRo^Xd2-y z3T#>X;0!KhboUSe7z9ZSITCbb$_PQ64M4(Bwax)J1!Kh1ihs8RW$)z1+Hafvw)uj# z%_dNxwIGFhM4_J*QOF z_?V(nzPdgL*d6vd3S=COFbP?jaP7b5=?m$+%^wC{bOza8r+%3_wOQ-U3bj?rMVn5u zQpyW1neg)mqkqmQIR<8$mR_DQYPTtwKy_;9_FIun=%Kfxv@w4RRgTZjx2M7&_-#=+ z&TN}i`o_^{bxTsK6^>+}2ca560grOVD`~e%bE>PXGq>bI%*hmHA)l;f2A9%wmFBfs zOmJke_(|ErM9W*?Muqx8*$>D8!ZI!@t86w{MVx^JijzxwC4b%$gTHN{r)4Z$vB#nr zdu&vUS3V2N|=^N(b=-Nx7meZ0Td0Pfyj#46>g#_G1iUzNVxW78&a+{}3aNj~S*g zmwcM5iZ?1xB7a{)S#iF-Jned~DT~XO^J5&V4DMtsw8&^_6vlR1b^}3o=-d*Cl}d9% zvkeHkr8@rDxy}7u0i@f+b(-OpC>XGNeZ$jei9uEqFj-Z+F<-X|cz5fTNJSSbZCzd! z05MYi1VeqNBOx5m5Ws?u5e$$}QlZj90~&S+u-Pj#?pF#;X_{2T?w3orC@k-B^hMrt z(fjjz9Gzog|2#@!!n2=eG??12t%kFQSBRnb4xL~&Okx90Hj6}FXW6XHGyrPpreKvpp7%4kSo6S?-jGm}Wdfk+fLr?p-11&IqRQ)f0Ak8ms zq4UMPw%2QWPgu0}+Fm!3^-WXKi?0y#)&NSna-A&Appte$f(bv^?+!IdH{G2e&HCbj zm}IzUi+vxKa0<|bR4ygW zGt2z{cDoKt%`CGy#iX2$%~{~c>dyW|b#J9f;7EGaBBzD0G2A(b8`ZE7EzAfTCPYk- zzC__b-hWB+mI{eO$uAtBI~0qRI0bM4mtYjr8Nj@c0(=a!^+kUYm7{X?LrYAjN2MtG z$yfMJ9ZJ=b1m`ertxxE>E7gg{HLZzsv7j@4npd-Fvb>a~w$QMGhfBbgB#^hiJ~M6W zLiapI63$7QFMCzu*{TvRPIBzkT`69YpgQxvi`N_p1&cvQRhPC5xqc zp`qHdUGYH@E5m=a^3rRsg&bHZB>-D8j%I%HpwiM+Kis)jE|x9{frLaY_4_N0rzrk( zqHgLRK_*QM$2iof83!9jQaYMn#=f#Gj_WWUtK+&``D-q%EjtAZk9-l!*!b=3olW`w z&Gz=8{QrM81{aoMA2(Z98F})vr?oe^;jyS>~LLS15!Q!7h}- zJb%rKq1|)<2^b=f2u+Anz~n0c0YQss34$0&FTOH4DWCAxEg^_6#37GQVw#L6%DYQw z*d4xgVJsb`{zn8ub@xv!XEjK)GmIsA9yM#|Nu zk1nR<3^5LWXLGHTh`D}^$F9}i(^wQIFp|y-jX;D5*QroV;`O75W&Q1Lc3h)iKJA{c zr~Z=bTMK?bOz_xYts>8=cKw z_&>w&mv%@GrnCLCCF9v{+>ZHz)O0xtv^ae*f7iDm)>ym|EAk@0UG<8M){prLMW79V zw%EX_^7F!XfK18#ag)n|ArxNpbZu*W=q=V~dv9OWAr>r2@R^c=LJ)VDCM;U!Lu}SI zalg2E`nr=+f-is1MsmEVyNA6b!56&(ZX{A!EAf#h;f@0_q%>OPv(3}47A$I@J>^S@ z>1H8Q;3HceiwTmqjdC}k&e?^lg*JxPtOj#lhQ}%fnw`6d`^D zBS-@OFpXSoM<|Bhz^~dlg~y)=ZxRMM@(s{0Ha#!gmm+`v_3|LkiXGoE)X#KaM-FJg z07IG>kO_ie3Mo11RO5JZ_z6`D)BaF35-xq&0|4aL@c#C8&5aK=H&4(ACK0a#uyI?; zc_P)pR~}GKRYV^M!l{P;rqx{Fs|v0uJHCdhu(`#)kQCMr+UjwKI$9h%HTM(Dr;bpI zFhsku^Y(vMdtSDwt$SQ9aJFjW(v61l9|d!)XSlp$&~`@u^c&I(I~MM5@74tQt7&q2 zFD72gWuhv(Yk@jO=?}DAm8r+3-$^WQf#FrFN4IQm5c3${L5{!_Nx%wgL9MYt{PfEy z|4Hkj(z4esL1{NSwPeI(LJK+U;s9I|$mQenvWS1J8wXJ1-FhaQ>t0RjO0_&b!nW$> zN9YRR=U_TYNp@s0vRPauAw;Xy_M!ZF5Wj5s&>Ln-OKZR8?u?pOpJr=p$g1*+aBD4$ z+nnnZ{RchIrCnIH05vZ$3XlX>gCNx_jB_K1l2E>}_HKRYUsh&7=F-#1U0tuwe(&p1 zc^`jI%Dk$%+MyQD8D?!|jHp^|Ci?4}w?GlZ8pKJ7Vhe$y`E3#Z@O%Mav~{ffmjF z&p*)eMmo*?x7Z7`c+mY-@xE$v6*6bBiBt}MnG#cr&|ISyB?eXDTk`7bXJ-Lb98+eCl zoO8N$ogoCT+FnJ`4h_nh_2$$KR?7^JiM^miM;J($f|V&JZFsH=su8hQeP1^wOQ+&4 zH{jCzDxdKyO1K~MS6p#^vRB)lhgyHIv)vdWB|fQv#%M3sGzA~=rtL<$X67~%%lhOh_Y5CJ@n@jndjVKwIm~9Ci%8Ki-s)ca4Yi>h-p6!i|GuCkK&s#u z35uhz3O+z~hG$seHhh5WJwnHDp1r(`(F`Xu{oq_?myoDEm--V_fmc^1;U9kv=OG&3 z#d~-^pbRbeWXZ;_?x*+jzei+uF$(@UnBDD8W^~FI!|;9z@Auipci#lJvH|P>6aUw~ zHzTcnx2USe&k>6`9Z=tv%-FlMqd&IO9Y6gY+wLROzbAVBc~>)&{o!`425)yx64$NX zVj)ks`4_O92OF8%Sa(%8D!sVw&(tnRrQ}KnEw9GPGe}bxd^mg zY;}Q3-624Io;J>cLIV$zA%`LpoBA%J?nGy&f*%g`-dp(}a7FKvR);|<)-AcQE?|Td zF_~C#0`JTP?w1ll_w>x7jY-OS>t`Po*_HI(tGlLvhI^C2ha4xB4KglkfIC%X?XaXi d8BX)`+&|d({{7qc{~rJV|NlO<+R;w&1^~*i&GP^N delta 33541 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 diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 2a3e5c939acae4a30127e564ae3f3c9baa2c2339..64765a403bcc1ddc6b5e19235a2d8f88ff13e0c8 100644 GIT binary patch delta 9385 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 R{{a91|Nr`Ma)jeQ0|0m4W<&r0 delta 13660 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 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 2e6e690e5b18e273b6e90e5d303fd222f318b945..ad518528c220e5ed049d7917ed2e6100042f3f5f 100644 GIT binary patch delta 3303 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 delta 3303 zcmVfpHFQYH8{sIH^t|5~F13iDuZh`A|AE@IZJCa3gW|h2nrh%$c$+7D?;k43>Z?|83b}b|btm^(VjhPQmXy7i@utP>Uj^@i`-ODs=1*$)qcFJm^AXmnq#RbWVgp|=KxdS*Tt`kA7!gR9PC<61ee=Lo!uz)dk8 zi7V%WkceXyFvo_JgTY0f-N%1H>Qy3_q^i{K<*U*!m|L@oiWJtVik^!ic8I7qFV7L5 z#gCKQFh5x#-usds`rL+#lC>bV* ziqT)Kn&qkBG1SJCDV3Xnm zB7bO@@B4qn6f?wQhxZS>_=UOiJ$B^_+o`&|Xc4=0O6-c!p|Ja=0>!TJ?oPx~apSGV zjh%~!v0gvFRu~!y<>1W5l#>a`SvNc-HejNAA5$(Iw2z(1aa3kZ=rl4o$^o)%hJ7E~ zfUH|Is0|SKB1+AWKWn9zGM`{u=sB7!jPW;QVbp!_?OA`(McqChcl|p&_x^Gp z|Mr4~JNNz?&nI{>>6#PL4Ho?%z@~9;!lhc}QxRQ7^f01#^wI8!{wJZf`*7}F@_#); z`KEzg8PgYdN(7DA79~SJ8^&?*?kAxQB5-?MaGl8LId^>?smkdLIS!`NXq%8w(QYrS zD_Xli)OP0-`+f=zYzVsujk*jl*wiV72)4V}3mc>uxV^I|2HGe z(XGLldbyq;9TduK4}X04@BvD50CG1H-3~iDFlkQFGU#+22SU@^LNGf6x6@BvWbe?+BjIKw<(6uhVS zA=BcK27YGjH88A=5r);6G9Do zh@pAJpn!#bdU5Qze&`HVuYGuOy_SR5$#6Y~Y1`fS)(p>)&?Nkb=AMJ2HqSoAu@N&7 zrF30`zeQ$oGFoczf1J7Q|U@oO9Xe{9AspT)ejxYq0D$F+0B zXMV+q7S_p$Wk=xM^=-n;qj(@n?}|=gYdhjnL6eoj(~9DQ15%!AC?GJy)Z%i_JBm1J z!9jo084ZWyV?62V$EH2N$Kx)xjz_3(3?}9n_0SM%@J~#pGY(HoLxZ1P3prs&tC|f8m02q|M?dcg66<@8#{SwsH>F)n-hqX7i?Dn@;lHMlLBcZ%T|I=k02= z`vtZ{l!!dj_igBXv%t`qYhmBN#J(TtbR~;VRn9m4ARu<@>S{L>O*gc|>esDRv-52_ z^9??#C?Xp})OP1UbOhW9cnC)g{HVSLrkG+TBperXe-_|jhG|^xhI&zdz~_i@|Arpu zN!EkTh$s2xd2dk;Eu_qQAFP!DSGQ&2|JyLLL9fuv?(s#G$aEDZGG%8j&)V8{3svWh z7O`8W#MXeBnX_kHnzaKhZ(VEfKZ!=A&Nfcfy0R<-X43%y2JLm7alJ4AZh~yzKBvY)I_KVB?&IHHuyE(zU*q`%FD6}cLb}1C z9|YJm?oF7)KryVUESav7jHHq=m1Ja+j9Oh%t4nWfb!pg>U=e2m(IAt_5mbMT1z1BL z76sV3dtWslIjU3?PSKdeA>r)PQ4}8YqoZgfKPXlSelaPc>->1P%3E%OfASe-l~OEr z1;FGuOImw@jaM_v`@4q6osa(^d)M496X_A@@hN*!k*OydGl*EQ* zh>1VIx{_LHQTt{Js3@RP4^ZhBT>O;^x%-4AlZoiQx9;qDUipJ}KKmF;F#u?R4ZUDw%h=wQ>pp$89Ar0h6+ zu<3A)*qsmf46m#L`2a`n+AHg5f!|yX_za1Eh!1?sIib@VI!6n@(H#Z|Oz;EnvE@?R z2iyh1y`w4OSo}-i$iD+Z-R;1s@u-8~YAK@<8k#^2t7}=+S%T6wGb*?T=W-Ts+kL1U zY2s?Rp{CeO;#vnA$)@*w^Z1>S=@c{I#|00L4nLZ{boGbd2Jyw+=q0~wNEWZNmlf^t!z(;bZv(#>O|Z}g5$bKE%|BilS4+xlSK8;uRaGWU)a zJNI1Fvc`+qXulxY?RVtgeTo*pDq3cuW+4c}$l=Jp^TTeU&mI=qVxql6Eig@5^ALY5 zGt8233?rv~ueYsmx3O&~NOp*Z4+^p*giN9(;5`&Ps#u$TN6pot-fO~?cK;CCJuKM& zT*;*B2LRXgc1$%gf)_A4u=vw**OX)3@^kZz;^r&OJCY+QSmcgNfa9A$*Si=*UzIFGOu`O2wn{loDiQ3vd6hpnZ$PSnnm#Bp9HdHmT(^JH%&GUxhXty&o^}Qph zqzc(7NK*O}5&o}$U|vxr*Y&C;aIC8xx&oH$KVSVeU5y>ry7NImIdK4=VTJ)>7| Date: Wed, 29 Nov 2023 17:56:20 +0100 Subject: [PATCH 03/68] mod tidy --- go.mod | 13 +------------ go.sum | 41 ----------------------------------------- 2 files changed, 1 insertion(+), 53 deletions(-) diff --git a/go.mod b/go.mod index 25dc88655..fa5e9370f 100644 --- a/go.mod +++ b/go.mod @@ -70,12 +70,9 @@ require ( github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487 github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e - github.com/hashicorp/go-hclog v1.3.0 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/golang-lru/arc/v2 v2.0.5 github.com/hashicorp/golang-lru/v2 v2.0.5 - github.com/hashicorp/raft v1.3.10 - github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea github.com/icza/backscanner v0.0.0-20210726202459-ac2ffc679f94 github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/ipfs/bbloom v0.0.4 @@ -108,11 +105,8 @@ require ( github.com/koalacxr/quantile v0.0.1 github.com/libp2p/go-buffer-pool v0.1.0 github.com/libp2p/go-libp2p v0.31.0 - github.com/libp2p/go-libp2p-consensus v0.0.1 - github.com/libp2p/go-libp2p-gorpc v0.5.0 github.com/libp2p/go-libp2p-kad-dht v0.24.0 github.com/libp2p/go-libp2p-pubsub v0.9.3 - github.com/libp2p/go-libp2p-raft v0.4.0 github.com/libp2p/go-libp2p-record v0.2.0 github.com/libp2p/go-libp2p-routing-helpers v0.7.0 github.com/libp2p/go-maddr-filter v0.1.0 @@ -154,7 +148,6 @@ require ( go.uber.org/multierr v1.11.0 go.uber.org/zap v1.25.0 golang.org/x/crypto v0.12.0 - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 golang.org/x/net v0.14.0 golang.org/x/sync v0.3.0 golang.org/x/sys v0.11.0 @@ -173,11 +166,9 @@ require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/akavel/rsrc v0.8.0 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect - github.com/armon/go-metrics v0.3.9 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bep/debounce v1.2.1 // indirect - github.com/boltdb/bolt v1.3.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cilium/ebpf v0.9.1 // indirect @@ -224,8 +215,6 @@ require ( github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect github.com/hannahhoward/cbor-gen-for v0.0.0-20230214144701-5d17c9d5243c // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/huin/goupnp v1.2.0 // indirect github.com/iancoleman/orderedmap v0.1.0 // indirect @@ -307,7 +296,6 @@ require ( github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/twmb/murmur3 v1.1.6 // indirect - github.com/ugorji/go/codec v1.2.6 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.0.1 // indirect github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 // indirect @@ -323,6 +311,7 @@ require ( go.opentelemetry.io/otel/trace v1.16.0 // indirect go.uber.org/dig v1.17.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/text v0.12.0 // indirect gonum.org/v1/gonum v0.13.0 // indirect diff --git a/go.sum b/go.sum index a96b193a3..797f30619 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= @@ -99,9 +97,6 @@ github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= -github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= @@ -118,8 +113,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= -github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= @@ -164,8 +157,6 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38 github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= -github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= -github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -588,26 +579,16 @@ github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyN github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.3.0 h1:G0ACM8Z2WilWgPv3Vdzwm3V0BQu/kSmrkVtpe1fy9do= -github.com/hashicorp/go-hclog v1.3.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= -github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -624,10 +605,6 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/raft v1.3.10 h1:LR5QZX1VQd0DFWZfeCwWawyeKfpS/Tm1yjnJIY5X4Tw= -github.com/hashicorp/raft v1.3.10/go.mod h1:J8naEwc6XaaCfts7+28whSeRvCqTd6e20BlCU3LtEO4= -github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea h1:xykPFhrBAS2J0VBzVa5e80b5ZtYuNQtgXjN40qBZlD4= -github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= @@ -888,7 +865,6 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -984,8 +960,6 @@ github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFk github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= github.com/libp2p/go-libp2p-circuit v0.4.0/go.mod h1:t/ktoFIUzM6uLQ+o1G6NuBl2ANhBKN9Bc8jRIk31MoA= -github.com/libp2p/go-libp2p-consensus v0.0.1 h1:jcVbHRZLwTXU9iT/mPi+Lx4/OrIzq3bU1TbZNhYFCV8= -github.com/libp2p/go-libp2p-consensus v0.0.1/go.mod h1:+9Wrfhc5QOqWB0gXI0m6ARlkHfdJpcFXmRU0WoHz4Mo= github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi9LuoTNdPrbUco= github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE= @@ -1014,8 +988,6 @@ github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFT github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= -github.com/libp2p/go-libp2p-gorpc v0.5.0 h1:mmxxAPdP3JzpYH4KcDf4csXnqtd1HazLPfdyB2MBRb8= -github.com/libp2p/go-libp2p-gorpc v0.5.0/go.mod h1:GpHuvY3m0YFkd0+inOGo4HDtc4up9OS/mBPXvEpNuRY= github.com/libp2p/go-libp2p-gostream v0.6.0 h1:QfAiWeQRce6pqnYfmIVWJFXNdDyfiR/qkCnjyaZUPYU= github.com/libp2p/go-libp2p-gostream v0.6.0/go.mod h1:Nywu0gYZwfj7Jc91PQvbGU8dIpqbQQkjWgDuOrFaRdA= github.com/libp2p/go-libp2p-kad-dht v0.24.0 h1:nZnFDQEFU4N8GzclnR+IGxIgR7k4PPCDk/GK9A28onk= @@ -1046,8 +1018,6 @@ github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYc github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc= github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= -github.com/libp2p/go-libp2p-raft v0.4.0 h1:2atEs7/FWH35bRiLh8gTejGh5NA9u4eG7BXjpf/B+Z4= -github.com/libp2p/go-libp2p-raft v0.4.0/go.mod h1:qJCYtFBTbip2wngLxFeAb9o52XmAPi2vSIQ4hV7IpSA= github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q= github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk= @@ -1179,7 +1149,6 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -1372,8 +1341,6 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= -github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= @@ -1404,7 +1371,6 @@ github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4 github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= @@ -1426,7 +1392,6 @@ github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7q github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= @@ -1587,15 +1552,11 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= -github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= -github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -2017,11 +1978,9 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From d7ea5561dcf4b189537c77d80f1b01eb896721b1 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 4 Dec 2023 22:30:40 -0600 Subject: [PATCH 04/68] maint: break out lp deps for easy testing --- cmd/lotus-provider/config.go | 47 +--- cmd/lotus-provider/deps/deps.go | 270 +++++++++++++++++++++++ cmd/lotus-provider/main.go | 9 +- cmd/lotus-provider/proving.go | 23 +- cmd/lotus-provider/rpc/rpc.go | 91 +++++++- cmd/lotus-provider/run.go | 343 +----------------------------- cmd/lotus-provider/tasks/tasks.go | 58 +++++ 7 files changed, 450 insertions(+), 391 deletions(-) create mode 100644 cmd/lotus-provider/deps/deps.go create mode 100644 cmd/lotus-provider/tasks/tasks.go diff --git a/cmd/lotus-provider/config.go b/cmd/lotus-provider/config.go index 5bd681429..49eed327a 100644 --- a/cmd/lotus-provider/config.go +++ b/cmd/lotus-provider/config.go @@ -2,7 +2,6 @@ package main import ( "context" - "database/sql" "errors" "fmt" "io" @@ -14,7 +13,7 @@ import ( "github.com/urfave/cli/v2" "golang.org/x/xerrors" - "github.com/filecoin-project/lotus/lib/harmony/harmonydb" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" "github.com/filecoin-project/lotus/node/config" ) @@ -77,7 +76,7 @@ var configSetCmd = &cli.Command{ Action: func(cctx *cli.Context) error { args := cctx.Args() - db, err := makeDB(cctx) + db, err := deps.MakeDB(cctx) if err != nil { return err } @@ -131,7 +130,7 @@ var configGetCmd = &cli.Command{ if args.Len() != 1 { return fmt.Errorf("want 1 layer arg, got %d", args.Len()) } - db, err := makeDB(cctx) + db, err := deps.MakeDB(cctx) if err != nil { return err } @@ -153,7 +152,7 @@ var configListCmd = &cli.Command{ Usage: "List config layers you can get.", Flags: []cli.Flag{}, Action: func(cctx *cli.Context) error { - db, err := makeDB(cctx) + db, err := deps.MakeDB(cctx) if err != nil { return err } @@ -180,7 +179,7 @@ var configRmCmd = &cli.Command{ if args.Len() != 1 { return errors.New("must have exactly 1 arg for the layer name") } - db, err := makeDB(cctx) + db, err := deps.MakeDB(cctx) if err != nil { return err } @@ -209,11 +208,11 @@ var configViewCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { - db, err := makeDB(cctx) + db, err := deps.MakeDB(cctx) if err != nil { return err } - lp, err := getConfig(cctx, db) + lp, err := deps.GetConfig(cctx, db) if err != nil { return err } @@ -225,35 +224,3 @@ var configViewCmd = &cli.Command{ return nil }, } - -func getConfig(cctx *cli.Context, db *harmonydb.DB) (*config.LotusProviderConfig, error) { - lp := config.DefaultLotusProvider() - have := []string{} - layers := cctx.StringSlice("layers") - for _, layer := range layers { - text := "" - err := db.QueryRow(cctx.Context, `SELECT config FROM harmony_config WHERE title=$1`, layer).Scan(&text) - if err != nil { - if strings.Contains(err.Error(), sql.ErrNoRows.Error()) { - return nil, fmt.Errorf("missing layer '%s' ", layer) - } - if layer == "base" { - return nil, errors.New(`lotus-provider defaults to a layer named 'base'. - Either use 'migrate' command or edit a base.toml and upload it with: lotus-provider config set base.toml`) - } - return nil, fmt.Errorf("could not read layer '%s': %w", layer, err) - } - meta, err := toml.Decode(text, &lp) - if err != nil { - return nil, fmt.Errorf("could not read layer, bad toml %s: %w", layer, err) - } - for _, k := range meta.Keys() { - have = append(have, strings.Join(k, " ")) - } - } - _ = have // FUTURE: verify that required fields are here. - // If config includes 3rd-party config, consider JSONSchema as a way that - // 3rd-parties can dynamically include config requirements and we can - // validate the config. Because of layering, we must validate @ startup. - return lp, nil -} diff --git a/cmd/lotus-provider/deps/deps.go b/cmd/lotus-provider/deps/deps.go new file mode 100644 index 000000000..f82a1ecd6 --- /dev/null +++ b/cmd/lotus-provider/deps/deps.go @@ -0,0 +1,270 @@ +// Package deps provides the dependencies for the lotus provider node. +package deps + +import ( + "context" + "database/sql" + "encoding/base64" + "errors" + "fmt" + "net" + "net/http" + "strings" + + ds "github.com/ipfs/go-datastore" + dssync "github.com/ipfs/go-datastore/sync" + logging "github.com/ipfs/go-log/v2" + + "github.com/BurntSushi/toml" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-jsonrpc/auth" + "github.com/filecoin-project/go-statestore" + "github.com/filecoin-project/lotus/api" + cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/journal" + "github.com/filecoin-project/lotus/journal/alerting" + "github.com/filecoin-project/lotus/journal/fsjournal" + "github.com/filecoin-project/lotus/lib/harmony/harmonydb" + "github.com/filecoin-project/lotus/node/config" + "github.com/filecoin-project/lotus/node/modules/dtypes" + "github.com/filecoin-project/lotus/node/repo" + "github.com/filecoin-project/lotus/provider" + "github.com/filecoin-project/lotus/storage/ctladdr" + "github.com/filecoin-project/lotus/storage/paths" + "github.com/filecoin-project/lotus/storage/sealer" + "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" + "github.com/filecoin-project/lotus/storage/sealer/storiface" + "github.com/gbrlsnchs/jwt/v3" + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" +) + +var log = logging.Logger("lotus-provider/deps") + +func MakeDB(cctx *cli.Context) (*harmonydb.DB, error) { + dbConfig := config.HarmonyDB{ + Username: cctx.String("db-user"), + Password: cctx.String("db-password"), + Hosts: strings.Split(cctx.String("db-host"), ","), + Database: cctx.String("db-name"), + Port: cctx.String("db-port"), + } + return harmonydb.NewFromConfig(dbConfig) +} + +type JwtPayload struct { + Allow []auth.Permission +} + +func StorageAuth(apiKey string) (sealer.StorageAuth, error) { + if apiKey == "" { + return nil, xerrors.Errorf("no api key provided") + } + + rawKey, err := base64.StdEncoding.DecodeString(apiKey) + if err != nil { + return nil, xerrors.Errorf("decoding api key: %w", err) + } + + key := jwt.NewHS256(rawKey) + + p := JwtPayload{ + Allow: []auth.Permission{"admin"}, + } + + token, err := jwt.Sign(&p, key) + if err != nil { + return nil, err + } + + headers := http.Header{} + headers.Add("Authorization", "Bearer "+string(token)) + return sealer.StorageAuth(headers), nil +} + +type Deps struct { + Cfg *config.LotusProviderConfig + DB *harmonydb.DB + Full api.FullNode + Verif storiface.Verifier + LW *sealer.LocalWorker + As *ctladdr.AddressSelector + Maddrs []dtypes.MinerAddress + Stor *paths.Remote + Si *paths.DBIndex + LocalStore *paths.Local + ListenAddr string +} + +const ( + FlagRepoPath = "repo-path" +) + +func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context, makeRepo bool) error { + + var err error + if makeRepo { + // Open repo + repoPath := cctx.String(FlagRepoPath) + fmt.Println("repopath", repoPath) + r, err := repo.NewFS(repoPath) + if err != nil { + return err + } + + ok, err := r.Exists() + if err != nil { + return err + } + if !ok { + if err := r.Init(repo.Provider); err != nil { + return err + } + } + } + + if deps.Cfg == nil { + deps.DB, err = MakeDB(cctx) + if err != nil { + return err + } + } + + if deps.Cfg == nil { + // The config feeds into task runners & their helpers + deps.Cfg, err = GetConfig(cctx, deps.DB) + if err != nil { + return err + } + } + + log.Debugw("config", "config", deps.Cfg) + + if deps.Verif == nil { + deps.Verif = ffiwrapper.ProofVerifier + } + + if deps.As == nil { + deps.As, err = provider.AddressSelector(&deps.Cfg.Addresses)() + if err != nil { + return err + } + } + + if deps.Si == nil { + de, err := journal.ParseDisabledEvents(deps.Cfg.Journal.DisabledEvents) + if err != nil { + return err + } + j, err := fsjournal.OpenFSJournalPath(cctx.String("journal"), de) + if err != nil { + return err + } + defer func() { + <-ctx.Done() + _ = j.Close() + }() + + al := alerting.NewAlertingSystem(j) + deps.Si = paths.NewDBIndex(al, deps.DB) + } + + if deps.Full == nil { + var fullCloser func() + deps.Full, fullCloser, err = cliutil.GetFullNodeAPIV1LotusProvider(cctx, deps.Cfg.Apis.ChainApiInfo) + if err != nil { + return err + } + + go func() { + <-ctx.Done() + fullCloser() + }() + } + + bls := &paths.BasicLocalStorage{ + PathToJSON: cctx.String("storage-json"), + } + + if deps.ListenAddr == "" { + listenAddr := cctx.String("listen") + const unspecifiedAddress = "0.0.0.0" + addressSlice := strings.Split(listenAddr, ":") + if ip := net.ParseIP(addressSlice[0]); ip != nil { + if ip.String() == unspecifiedAddress { + rip, err := deps.DB.GetRoutableIP() + if err != nil { + return err + } + deps.ListenAddr = rip + ":" + addressSlice[1] + } + } + } + if deps.LocalStore == nil { + deps.LocalStore, err = paths.NewLocal(ctx, bls, deps.Si, []string{"http://" + deps.ListenAddr + "/remote"}) + if err != nil { + return err + } + } + + sa, err := StorageAuth(deps.Cfg.Apis.StorageRPCSecret) + if err != nil { + return xerrors.Errorf(`'%w' while parsing the config toml's + [Apis] + StorageRPCSecret=%v +Get it with: jq .PrivateKey ~/.lotus-miner/keystore/MF2XI2BNNJ3XILLQOJUXMYLUMU`, err, deps.Cfg.Apis.StorageRPCSecret) + } + if deps.Stor == nil { + deps.Stor = paths.NewRemote(deps.LocalStore, deps.Si, http.Header(sa), 10, &paths.DefaultPartialFileHandler{}) + } + if deps.LW == nil { + wstates := statestore.New(dssync.MutexWrap(ds.NewMapDatastore())) + + // todo localWorker isn't the abstraction layer we want to use here, we probably want to go straight to ffiwrapper + // maybe with a lotus-provider specific abstraction. LocalWorker does persistent call tracking which we probably + // don't need (ehh.. maybe we do, the async callback system may actually work decently well with harmonytask) + deps.LW = sealer.NewLocalWorker(sealer.WorkerConfig{}, deps.Stor, deps.LocalStore, deps.Si, nil, wstates) + } + if len(deps.Maddrs) == 0 { + for _, s := range deps.Cfg.Addresses.MinerAddresses { + addr, err := address.NewFromString(s) + if err != nil { + return err + } + deps.Maddrs = append(deps.Maddrs, dtypes.MinerAddress(addr)) + } + } + return nil +} + +func GetConfig(cctx *cli.Context, db *harmonydb.DB) (*config.LotusProviderConfig, error) { + lp := config.DefaultLotusProvider() + have := []string{} + layers := cctx.StringSlice("layers") + for _, layer := range layers { + text := "" + err := db.QueryRow(cctx.Context, `SELECT config FROM harmony_config WHERE title=$1`, layer).Scan(&text) + if err != nil { + if strings.Contains(err.Error(), sql.ErrNoRows.Error()) { + return nil, fmt.Errorf("missing layer '%s' ", layer) + } + if layer == "base" { + return nil, errors.New(`lotus-provider defaults to a layer named 'base'. + Either use 'migrate' command or edit a base.toml and upload it with: lotus-provider config set base.toml`) + } + return nil, fmt.Errorf("could not read layer '%s': %w", layer, err) + } + meta, err := toml.Decode(text, &lp) + if err != nil { + return nil, fmt.Errorf("could not read layer, bad toml %s: %w", layer, err) + } + for _, k := range meta.Keys() { + have = append(have, strings.Join(k, " ")) + } + } + _ = have // FUTURE: verify that required fields are here. + // If config includes 3rd-party config, consider JSONSchema as a way that + // 3rd-parties can dynamically include config requirements and we can + // validate the config. Because of layering, we must validate @ startup. + return lp, nil +} diff --git a/cmd/lotus-provider/main.go b/cmd/lotus-provider/main.go index 19cc6f5f9..48ff70122 100644 --- a/cmd/lotus-provider/main.go +++ b/cmd/lotus-provider/main.go @@ -15,6 +15,7 @@ import ( "github.com/filecoin-project/lotus/build" lcli "github.com/filecoin-project/lotus/cli" cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" "github.com/filecoin-project/lotus/lib/lotuslog" "github.com/filecoin-project/lotus/lib/tracing" "github.com/filecoin-project/lotus/node/repo" @@ -131,7 +132,7 @@ func main() { Value: "base", }, &cli.StringFlag{ - Name: FlagRepoPath, + Name: deps.FlagRepoPath, EnvVars: []string{"LOTUS_REPO_PATH"}, Value: "~/.lotusprovider", }, @@ -144,7 +145,7 @@ func main() { After: func(c *cli.Context) error { if r := recover(); r != nil { // Generate report in LOTUS_PATH and re-raise panic - build.GeneratePanicReport(c.String("panic-reports"), c.String(FlagRepoPath), c.App.Name) + build.GeneratePanicReport(c.String("panic-reports"), c.String(deps.FlagRepoPath), c.App.Name) panic(r) } return nil @@ -154,7 +155,3 @@ func main() { app.Metadata["repoType"] = repo.Provider lcli.RunApp(app) } - -const ( - FlagRepoPath = "repo-path" -) diff --git a/cmd/lotus-provider/proving.go b/cmd/lotus-provider/proving.go index 577b5b5f9..001108712 100644 --- a/cmd/lotus-provider/proving.go +++ b/cmd/lotus-provider/proving.go @@ -15,6 +15,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" "github.com/filecoin-project/lotus/lib/harmony/harmonydb" "github.com/filecoin-project/lotus/provider" ) @@ -62,18 +63,18 @@ var wdPostTaskCmd = &cli.Command{ Action: func(cctx *cli.Context) error { ctx := context.Background() - deps, err := getDeps(ctx, cctx) + deps, err := deps.GetDeps(ctx, cctx) if err != nil { return err } - ts, err := deps.full.ChainHead(ctx) + ts, err := deps.Full.ChainHead(ctx) if err != nil { return xerrors.Errorf("cannot get chainhead %w", err) } ht := ts.Height() - addr, err := address.NewFromString(deps.cfg.Addresses.MinerAddresses[0]) + addr, err := address.NewFromString(deps.Cfg.Addresses.MinerAddresses[0]) if err != nil { return xerrors.Errorf("cannot get miner address %w", err) } @@ -82,7 +83,7 @@ var wdPostTaskCmd = &cli.Command{ return xerrors.Errorf("cannot get miner id %w", err) } var id int64 - _, err = deps.db.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { + _, err = deps.DB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { err = tx.QueryRow(`INSERT INTO harmony_task (name, posted_time, added_by) VALUES ('WdPost', CURRENT_TIMESTAMP, 123) RETURNING id`).Scan(&id) if err != nil { log.Error("inserting harmony_task: ", err) @@ -108,7 +109,7 @@ var wdPostTaskCmd = &cli.Command{ var result sql.NullString for { time.Sleep(time.Second) - err = deps.db.QueryRow(ctx, `SELECT result FROM harmony_test WHERE task_id=$1`, id).Scan(&result) + err = deps.DB.QueryRow(ctx, `SELECT result FROM harmony_test WHERE task_id=$1`, id).Scan(&result) if err != nil { return xerrors.Errorf("reading result from harmony_test: %w", err) } @@ -157,29 +158,29 @@ It will not send any messages to the chain. Since it can compute any deadline, o Action: func(cctx *cli.Context) error { ctx := context.Background() - deps, err := getDeps(ctx, cctx) + deps, err := deps.GetDeps(ctx, cctx) if err != nil { return err } - wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := provider.WindowPostScheduler(ctx, deps.cfg.Fees, deps.cfg.Proving, deps.full, deps.verif, deps.lw, nil, - deps.as, deps.maddrs, deps.db, deps.stor, deps.si, deps.cfg.Subsystems.WindowPostMaxTasks) + wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := provider.WindowPostScheduler(ctx, deps.Cfg.Fees, deps.Cfg.Proving, deps.Full, deps.Verif, deps.LW, nil, + deps.As, deps.Maddrs, deps.DB, deps.Stor, deps.Si, deps.Cfg.Subsystems.WindowPostMaxTasks) if err != nil { return err } _, _ = wdPoStSubmitTask, derlareRecoverTask - if len(deps.maddrs) == 0 { + if len(deps.Maddrs) == 0 { return errors.New("no miners to compute WindowPoSt for") } - head, err := deps.full.ChainHead(ctx) + head, err := deps.Full.ChainHead(ctx) if err != nil { return xerrors.Errorf("failed to get chain head: %w", err) } di := dline.NewInfo(head.Height(), cctx.Uint64("deadline"), 0, 0, 0, 10 /*challenge window*/, 0, 0) - for _, maddr := range deps.maddrs { + for _, maddr := range deps.Maddrs { out, err := wdPostTask.DoPartition(ctx, head, address.Address(maddr), di, cctx.Uint64("partition")) if err != nil { fmt.Println("Error computing WindowPoSt for miner", maddr, err) diff --git a/cmd/lotus-provider/rpc/rpc.go b/cmd/lotus-provider/rpc/rpc.go index 3ae3e2a1f..0fe1039d9 100644 --- a/cmd/lotus-provider/rpc/rpc.go +++ b/cmd/lotus-provider/rpc/rpc.go @@ -1,21 +1,32 @@ +// Package rpc provides all direct access to this node. package rpc import ( "context" + "encoding/base64" + "encoding/json" + "net" "net/http" + "time" + "github.com/gbrlsnchs/jwt/v3" "github.com/gorilla/mux" + logging "github.com/ipfs/go-log/v2" + "go.opencensus.io/tag" + "golang.org/x/xerrors" - // logging "github.com/ipfs/go-log/v2" "github.com/filecoin-project/go-jsonrpc" "github.com/filecoin-project/go-jsonrpc/auth" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" "github.com/filecoin-project/lotus/lib/rpcenc" + "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/metrics/proxy" + "github.com/filecoin-project/lotus/storage/paths" ) -//var log = logging.Logger("lp/rpc") +var log = logging.Logger("lp/rpc") func LotusProviderHandler( authv func(ctx context.Context, token string) ([]auth.Permission, error), @@ -49,3 +60,79 @@ func LotusProviderHandler( } return ah } + +type ProviderAPI struct { + *deps.Deps + ShutdownChan chan struct{} +} + +func (p *ProviderAPI) Version(context.Context) (api.Version, error) { + return api.ProviderAPIVersion0, nil +} + +// Trigger shutdown +func (p *ProviderAPI) Shutdown(context.Context) error { + close(p.ShutdownChan) + return nil +} + +func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan chan struct{}) error { + + fh := &paths.FetchHandler{Local: dependencies.LocalStore, PfHandler: &paths.DefaultPartialFileHandler{}} + remoteHandler := func(w http.ResponseWriter, r *http.Request) { + if !auth.HasPerm(r.Context(), nil, api.PermAdmin) { + w.WriteHeader(401) + _ = json.NewEncoder(w).Encode(struct{ Error string }{"unauthorized: missing admin permission"}) + return + } + + fh.ServeHTTP(w, r) + } + // local APIs + { + // debugging + mux := mux.NewRouter() + mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof + mux.PathPrefix("/remote").HandlerFunc(remoteHandler) + } + + var authVerify func(context.Context, string) ([]auth.Permission, error) + { + privateKey, err := base64.StdEncoding.DecodeString(dependencies.Cfg.Apis.StorageRPCSecret) + if err != nil { + return xerrors.Errorf("decoding storage rpc secret: %w", err) + } + authVerify = func(ctx context.Context, token string) ([]auth.Permission, error) { + var payload deps.JwtPayload + if _, err := jwt.Verify([]byte(token), jwt.NewHS256(privateKey), &payload); err != nil { + return nil, xerrors.Errorf("JWT Verification failed: %w", err) + } + + return payload.Allow, nil + } + } + // Serve the RPC. + srv := &http.Server{ + Handler: LotusProviderHandler( + authVerify, + remoteHandler, + &ProviderAPI{dependencies, shutdownChan}, + true), + ReadHeaderTimeout: time.Minute * 3, + BaseContext: func(listener net.Listener) context.Context { + ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-worker")) + return ctx + }, + } + + go func() { + <-ctx.Done() + log.Warn("Shutting down...") + if err := srv.Shutdown(context.TODO()); err != nil { + log.Errorf("shutting down RPC server failed: %s", err) + } + log.Warn("Graceful shutdown successful") + }() + + return nil +} diff --git a/cmd/lotus-provider/run.go b/cmd/lotus-provider/run.go index bf19ee537..87d073963 100644 --- a/cmd/lotus-provider/run.go +++ b/cmd/lotus-provider/run.go @@ -2,54 +2,23 @@ package main import ( "context" - "encoding/base64" - "encoding/json" "fmt" - "net" - "net/http" "os" - "strings" "time" - "github.com/gbrlsnchs/jwt/v3" - "github.com/gorilla/mux" - ds "github.com/ipfs/go-datastore" - dssync "github.com/ipfs/go-datastore/sync" "github.com/pkg/errors" - "github.com/samber/lo" "github.com/urfave/cli/v2" "go.opencensus.io/stats" "go.opencensus.io/tag" - "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-jsonrpc/auth" - "github.com/filecoin-project/go-statestore" - - "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" lcli "github.com/filecoin-project/lotus/cli" - cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" "github.com/filecoin-project/lotus/cmd/lotus-provider/rpc" - "github.com/filecoin-project/lotus/journal" - "github.com/filecoin-project/lotus/journal/alerting" - "github.com/filecoin-project/lotus/journal/fsjournal" - "github.com/filecoin-project/lotus/lib/harmony/harmonydb" - "github.com/filecoin-project/lotus/lib/harmony/harmonytask" + "github.com/filecoin-project/lotus/cmd/lotus-provider/tasks" "github.com/filecoin-project/lotus/lib/ulimit" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node" - "github.com/filecoin-project/lotus/node/config" - "github.com/filecoin-project/lotus/node/modules/dtypes" - "github.com/filecoin-project/lotus/node/repo" - "github.com/filecoin-project/lotus/provider" - "github.com/filecoin-project/lotus/provider/lpmessage" - "github.com/filecoin-project/lotus/provider/lpwinning" - "github.com/filecoin-project/lotus/storage/ctladdr" - "github.com/filecoin-project/lotus/storage/paths" - "github.com/filecoin-project/lotus/storage/sealer" - "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" - "github.com/filecoin-project/lotus/storage/sealer/storiface" ) type stackTracer interface { @@ -144,112 +113,22 @@ var runCmd = &cli.Command{ } } - deps, err := getDeps(ctx, cctx) - - if err != nil { - return err - } - cfg, db, full, verif, lw, as, maddrs, stor, si, localStore := deps.cfg, deps.db, deps.full, deps.verif, deps.lw, deps.as, deps.maddrs, deps.stor, deps.si, deps.localStore - - var activeTasks []harmonytask.TaskInterface - - sender, sendTask := lpmessage.NewSender(full, full, db) - activeTasks = append(activeTasks, sendTask) - - /////////////////////////////////////////////////////////////////////// - ///// Task Selection - /////////////////////////////////////////////////////////////////////// - { - - if cfg.Subsystems.EnableWindowPost { - wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := provider.WindowPostScheduler(ctx, cfg.Fees, cfg.Proving, full, verif, lw, sender, - as, maddrs, db, stor, si, cfg.Subsystems.WindowPostMaxTasks) - if err != nil { - return err - } - activeTasks = append(activeTasks, wdPostTask, wdPoStSubmitTask, derlareRecoverTask) - } - - if cfg.Subsystems.EnableWinningPost { - winPoStTask := lpwinning.NewWinPostTask(cfg.Subsystems.WinningPostMaxTasks, db, lw, verif, full, maddrs) - activeTasks = append(activeTasks, winPoStTask) - } - } - log.Infow("This lotus_provider instance handles", - "miner_addresses", maddrs, - "tasks", lo.Map(activeTasks, func(t harmonytask.TaskInterface, _ int) string { return t.TypeDetails().Name })) - - taskEngine, err := harmonytask.New(db, activeTasks, deps.listenAddr) + var dependencies *deps.Deps + err = dependencies.PopulateRemainingDeps(ctx, cctx, true) if err != nil { return err } + taskEngine, err := tasks.StartTasks(ctx, dependencies) + if err != nil { + return nil + } defer taskEngine.GracefullyTerminate(time.Hour) - fh := &paths.FetchHandler{Local: localStore, PfHandler: &paths.DefaultPartialFileHandler{}} - remoteHandler := func(w http.ResponseWriter, r *http.Request) { - if !auth.HasPerm(r.Context(), nil, api.PermAdmin) { - w.WriteHeader(401) - _ = json.NewEncoder(w).Encode(struct{ Error string }{"unauthorized: missing admin permission"}) - return - } - - fh.ServeHTTP(w, r) + err = rpc.ListenAndServe(ctx, dependencies, shutdownChan) // Monitor for shutdown. + if err != nil { + return err } - // local APIs - { - // debugging - mux := mux.NewRouter() - mux.PathPrefix("/").Handler(http.DefaultServeMux) // pprof - mux.PathPrefix("/remote").HandlerFunc(remoteHandler) - - /*ah := &auth.Handler{ - Verify: authv, - Next: mux.ServeHTTP, - }*/ // todo - - } - - var authVerify func(context.Context, string) ([]auth.Permission, error) - { - privateKey, err := base64.StdEncoding.DecodeString(deps.cfg.Apis.StorageRPCSecret) - if err != nil { - return xerrors.Errorf("decoding storage rpc secret: %w", err) - } - authVerify = func(ctx context.Context, token string) ([]auth.Permission, error) { - var payload jwtPayload - if _, err := jwt.Verify([]byte(token), jwt.NewHS256(privateKey), &payload); err != nil { - return nil, xerrors.Errorf("JWT Verification failed: %w", err) - } - - return payload.Allow, nil - } - } - // Serve the RPC. - srv := &http.Server{ - Handler: rpc.LotusProviderHandler( - authVerify, - remoteHandler, - &ProviderAPI{deps, shutdownChan}, - true), - ReadHeaderTimeout: time.Minute * 3, - BaseContext: func(listener net.Listener) context.Context { - ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-worker")) - return ctx - }, - } - - go func() { - <-ctx.Done() - log.Warn("Shutting down...") - if err := srv.Shutdown(context.TODO()); err != nil { - log.Errorf("shutting down RPC server failed: %s", err) - } - log.Warn("Graceful shutdown successful") - }() - - // Monitor for shutdown. - // TODO provide a graceful shutdown API on shutdownChan finishCh := node.MonitorShutdown(shutdownChan) //node.ShutdownHandler{Component: "rpc server", StopFunc: rpcStopper}, //node.ShutdownHandler{Component: "provider", StopFunc: stop}, @@ -257,203 +136,3 @@ var runCmd = &cli.Command{ return nil }, } - -func makeDB(cctx *cli.Context) (*harmonydb.DB, error) { - dbConfig := config.HarmonyDB{ - Username: cctx.String("db-user"), - Password: cctx.String("db-password"), - Hosts: strings.Split(cctx.String("db-host"), ","), - Database: cctx.String("db-name"), - Port: cctx.String("db-port"), - } - return harmonydb.NewFromConfig(dbConfig) -} - -type jwtPayload struct { - Allow []auth.Permission -} - -func StorageAuth(apiKey string) (sealer.StorageAuth, error) { - if apiKey == "" { - return nil, xerrors.Errorf("no api key provided") - } - - rawKey, err := base64.StdEncoding.DecodeString(apiKey) - if err != nil { - return nil, xerrors.Errorf("decoding api key: %w", err) - } - - key := jwt.NewHS256(rawKey) - - p := jwtPayload{ - Allow: []auth.Permission{"admin"}, - } - - token, err := jwt.Sign(&p, key) - if err != nil { - return nil, err - } - - headers := http.Header{} - headers.Add("Authorization", "Bearer "+string(token)) - return sealer.StorageAuth(headers), nil -} - -type Deps struct { - cfg *config.LotusProviderConfig - db *harmonydb.DB - full api.FullNode - verif storiface.Verifier - lw *sealer.LocalWorker - as *ctladdr.AddressSelector - maddrs []dtypes.MinerAddress - stor *paths.Remote - si *paths.DBIndex - localStore *paths.Local - listenAddr string -} - -func getDeps(ctx context.Context, cctx *cli.Context) (*Deps, error) { - // Open repo - - repoPath := cctx.String(FlagRepoPath) - fmt.Println("repopath", repoPath) - r, err := repo.NewFS(repoPath) - if err != nil { - return nil, err - } - - ok, err := r.Exists() - if err != nil { - return nil, err - } - if !ok { - if err := r.Init(repo.Provider); err != nil { - return nil, err - } - } - - db, err := makeDB(cctx) - if err != nil { - return nil, err - } - - /////////////////////////////////////////////////////////////////////// - ///// Dependency Setup - /////////////////////////////////////////////////////////////////////// - - // The config feeds into task runners & their helpers - cfg, err := getConfig(cctx, db) - if err != nil { - return nil, err - } - - log.Debugw("config", "config", cfg) - - var verif storiface.Verifier = ffiwrapper.ProofVerifier - - as, err := provider.AddressSelector(&cfg.Addresses)() - if err != nil { - return nil, err - } - - de, err := journal.ParseDisabledEvents(cfg.Journal.DisabledEvents) - if err != nil { - return nil, err - } - j, err := fsjournal.OpenFSJournalPath(cctx.String("journal"), de) - if err != nil { - return nil, err - } - - full, fullCloser, err := cliutil.GetFullNodeAPIV1LotusProvider(cctx, cfg.Apis.ChainApiInfo) - if err != nil { - return nil, err - } - - go func() { - select { - case <-ctx.Done(): - fullCloser() - _ = j.Close() - } - }() - sa, err := StorageAuth(cfg.Apis.StorageRPCSecret) - if err != nil { - return nil, xerrors.Errorf(`'%w' while parsing the config toml's - [Apis] - StorageRPCSecret=%v -Get it with: jq .PrivateKey ~/.lotus-miner/keystore/MF2XI2BNNJ3XILLQOJUXMYLUMU`, err, cfg.Apis.StorageRPCSecret) - } - - al := alerting.NewAlertingSystem(j) - si := paths.NewDBIndex(al, db) - bls := &paths.BasicLocalStorage{ - PathToJSON: cctx.String("storage-json"), - } - - listenAddr := cctx.String("listen") - const unspecifiedAddress = "0.0.0.0" - addressSlice := strings.Split(listenAddr, ":") - if ip := net.ParseIP(addressSlice[0]); ip != nil { - if ip.String() == unspecifiedAddress { - rip, err := db.GetRoutableIP() - if err != nil { - return nil, err - } - listenAddr = rip + ":" + addressSlice[1] - } - } - localStore, err := paths.NewLocal(ctx, bls, si, []string{"http://" + listenAddr + "/remote"}) - if err != nil { - return nil, err - } - - stor := paths.NewRemote(localStore, si, http.Header(sa), 10, &paths.DefaultPartialFileHandler{}) - - wstates := statestore.New(dssync.MutexWrap(ds.NewMapDatastore())) - - // todo localWorker isn't the abstraction layer we want to use here, we probably want to go straight to ffiwrapper - // maybe with a lotus-provider specific abstraction. LocalWorker does persistent call tracking which we probably - // don't need (ehh.. maybe we do, the async callback system may actually work decently well with harmonytask) - lw := sealer.NewLocalWorker(sealer.WorkerConfig{}, stor, localStore, si, nil, wstates) - - var maddrs []dtypes.MinerAddress - for _, s := range cfg.Addresses.MinerAddresses { - addr, err := address.NewFromString(s) - if err != nil { - return nil, err - } - maddrs = append(maddrs, dtypes.MinerAddress(addr)) - } - - return &Deps{ // lint: intentionally not-named so it will fail if one is forgotten - cfg, - db, - full, - verif, - lw, - as, - maddrs, - stor, - si, - localStore, - listenAddr, - }, nil - -} - -type ProviderAPI struct { - *Deps - ShutdownChan chan struct{} -} - -func (p *ProviderAPI) Version(context.Context) (api.Version, error) { - return api.ProviderAPIVersion0, nil -} - -// Trigger shutdown -func (p *ProviderAPI) Shutdown(context.Context) error { - close(p.ShutdownChan) - return nil -} diff --git a/cmd/lotus-provider/tasks/tasks.go b/cmd/lotus-provider/tasks/tasks.go new file mode 100644 index 000000000..18c56a744 --- /dev/null +++ b/cmd/lotus-provider/tasks/tasks.go @@ -0,0 +1,58 @@ +// Package tasks contains tasks that can be run by the lotus-provider command. +package tasks + +import ( + "context" + + logging "github.com/ipfs/go-log/v2" + + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" + "github.com/filecoin-project/lotus/lib/harmony/harmonytask" + "github.com/filecoin-project/lotus/provider" + "github.com/filecoin-project/lotus/provider/lpmessage" + "github.com/filecoin-project/lotus/provider/lpwinning" + "github.com/samber/lo" +) + +var log = logging.Logger("lotus-provider/deps") + +func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.TaskEngine, error) { + cfg := dependencies.Cfg + db := dependencies.DB + full := dependencies.Full + verif := dependencies.Verif + lw := dependencies.LW + as := dependencies.As + maddrs := dependencies.Maddrs + stor := dependencies.Stor + si := dependencies.Si + var activeTasks []harmonytask.TaskInterface + + sender, sendTask := lpmessage.NewSender(full, full, db) + activeTasks = append(activeTasks, sendTask) + + /////////////////////////////////////////////////////////////////////// + ///// Task Selection + /////////////////////////////////////////////////////////////////////// + { + + if cfg.Subsystems.EnableWindowPost { + wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := provider.WindowPostScheduler(ctx, cfg.Fees, cfg.Proving, full, verif, lw, sender, + as, maddrs, db, stor, si, cfg.Subsystems.WindowPostMaxTasks) + if err != nil { + return nil, err + } + activeTasks = append(activeTasks, wdPostTask, wdPoStSubmitTask, derlareRecoverTask) + } + + if cfg.Subsystems.EnableWinningPost { + winPoStTask := lpwinning.NewWinPostTask(cfg.Subsystems.WinningPostMaxTasks, db, lw, verif, full, maddrs) + activeTasks = append(activeTasks, winPoStTask) + } + } + log.Infow("This lotus_provider instance handles", + "miner_addresses", maddrs, + "tasks", lo.Map(activeTasks, func(t harmonytask.TaskInterface, _ int) string { return t.TypeDetails().Name })) + + return harmonytask.New(db, activeTasks, dependencies.ListenAddr) +} From 8db6e73c9074ad41af0940a7ad68e0e5134ff6cc Mon Sep 17 00:00:00 2001 From: Phi Date: Mon, 4 Dec 2023 10:55:26 +0100 Subject: [PATCH 05/68] Bump version in master Bump version in master --- build/openrpc/full.json.gz | Bin 34818 -> 34820 bytes build/openrpc/gateway.json.gz | Bin 11875 -> 11872 bytes build/openrpc/miner.json.gz | Bin 16370 -> 16371 bytes build/openrpc/worker.json.gz | Bin 6052 -> 6051 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 8 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 4e3f31fbac65da324b9d4afcfa0df76515c27435..45489699a662d670aa38c7821e2bd49ceb88fb6d 100644 GIT binary patch delta 29452 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 Do?x+@ diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index fe52522fdc80bd103c059f6980f4e7d8ed94f483..52715057145366a37930c2c9c54ad529f7c593a2 100644 GIT binary patch delta 8869 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 delta 8845 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 literal 6052 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 diff --git a/build/version.go b/build/version.go index 0758686f6..215940e7a 100644 --- a/build/version.go +++ b/build/version.go @@ -37,7 +37,7 @@ func BuildTypeString() string { } // BuildVersion is the local build version -const BuildVersion = "1.25.1-dev" +const BuildVersion = "1.25.2-dev" func UserVersion() string { if os.Getenv("LOTUS_VERSION_IGNORE_COMMIT") == "1" { diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index f3fb8a9e1..82b6b300a 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -7,7 +7,7 @@ USAGE: lotus-miner [global options] command [command options] [arguments...] VERSION: - 1.25.1-dev + 1.25.2-dev COMMANDS: init Initialize a lotus miner repo diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index cf0b9fd36..73774503c 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -7,7 +7,7 @@ USAGE: lotus-worker [global options] command [command options] [arguments...] VERSION: - 1.25.1-dev + 1.25.2-dev COMMANDS: run Start lotus worker diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index a6a6ea30a..959aaefac 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -7,7 +7,7 @@ USAGE: lotus [global options] command [command options] [arguments...] VERSION: - 1.25.1-dev + 1.25.2-dev COMMANDS: daemon Start a lotus daemon process From c9f13253fd1952db0469fd1369c19299b9b477d9 Mon Sep 17 00:00:00 2001 From: Phi Date: Tue, 5 Dec 2023 08:13:25 +0100 Subject: [PATCH 06/68] Make gen Make gen --- build/openrpc/full.json.gz | Bin 34820 -> 34817 bytes build/openrpc/gateway.json.gz | Bin 11872 -> 11875 bytes build/openrpc/miner.json.gz | Bin 16371 -> 16370 bytes build/openrpc/worker.json.gz | Bin 6051 -> 6052 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 45489699a662d670aa38c7821e2bd49ceb88fb6d..ad2116cb9187f20cea37fef3a37566fd3a2730cf 100644 GIT binary patch delta 30260 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 diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 52715057145366a37930c2c9c54ad529f7c593a2..48ad91135e370665117694d7515928b8773c1ad8 100644 GIT binary patch delta 8840 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 CGd(c? delta 8864 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 iK;e{Bd|_osyX`#_^YQWf?_`$% diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 120a1c457ff1b645d72a48626162ac17610296df..a16ed4f260fa20727e54ba0b3e2a51c8aa09f1ec 100644 GIT binary patch delta 15993 zcmV-Bc9JrTZy1}Z{eyv-2^%Ki z0Va8#9jJ}mE!$e!Qm0!6JX3u4waJq?ou)sDVt3^NmHN7^}M8wXrooPgttGp(oHBiq4$l*lg*_J?~0y4Rk1+8VJH zH5~2e%Qua{HUIPjHjz#-*+149wT}(MMvkNPGy^%hjV&g@{PovgOL{{V8=`|Z4*2&DhDPic5?Vrg1{si7Y`EuWF)C0)2sr?i9c0+C$UI1tR zj4)&qXhyJq0ss6bAlQ`6ZkUbO#wOrrf*#@!f9iqvw*4DrR~yTsHbVygvyrng z8DAN9c4PP@<~8{~(zTC`h=n<|h6Y+kuMSn1V9F4Wx9{*gR0nH1WTF7RYw^%^a zK|PIaEySDC`G1klwA&|+-`^W-BSSl4_6BieEF0;N@h9S|r<7+s4L!;!JEgkAk%^As zBWA139N1`083HCIcUn)|*rs-*tr)YMqqlFDqRGBa*KZdtz3o{x<#@d{Iqklkn{@tm z4IPGm?6=UuZ!McXZvV4HWPeHj-}%A8@KAet>g7}I2_*}>Y)rcnOgaTenv|tq**b@c zBkgL_u#fjnC^>(Q<8O71b6#B|dyNTXDD~|rg673$ZenMZ z{vJDUZld2G2(mvw)0{*7&f^F7-JjIHi@$t-Dq=S)^yph0{cjp(Xf589;8~AlpZo{V zw&9llP8(f&z*DE@o7Zkmsfi#7wTw?xTGQk*w}x+$5LyEL^va~?XqqEEuaNjR{)+00 z&HzS=-0T5s0OFb&yn%DPAADCROoOI*_CN$?bx|4_2gkdyEcGYd8gyU#rsNgujw5k$7{MF+~m=*v44V%LjH_(ki(=d#OmCc978sX#?gVM zNgo`*D0pz+fVul>Vbe8O^BDt>cf%Wh(FgHUGUg4rvXG7!TL8tZ0O)`lt$(9Mz%4eW z>A~Cw*DLG*x!(eEIGnWC$Z_Bjfs?b-8v=;|42m2;C<6}=Gq9kx-vm7(eZyDzhO{Ma zqH9}D-1MJM(ztYyz&m(eAX@|>69&!OM+6ghK(`Epn`au8vBMI2-<_GFuXIVMZV z6nu&0(jx<4AKE@RV_ZZnsJ%u8m~R0Df5@$N4?u824WxrN4=b#%044_JBNnT^F&WnR z+dT{FcgXO2;dA#B;Di9dC*EoWoz;F+^nKIb^7V#`?Qs4T>IjY=9Ah=vj^Jp*<|F40 zt*!sk$G@%3maeV;&esdHU5v(m3q0CvCz}l#5AVm?Q%Gt$%*JH-olDJ0KV53RLj*0b zj-kD6Lw06^YgK|~chj;Q%^gp+G|j=!6Rax)=0Ph!7o6~gP%R^Km55a$R*BediP*zI zx`;hlA^q;cruT4e)|09c2zi3^5-l;u4;dHqie1>0E_%Qkf-koYqc&cDKpnZek4v=p z3A|ZD>r1dBk(-KJxfprkH-b-&#LWR;Neaiu&&SKhwcFih`h4ze%T|A*7K~z;=rwia zOUcXi0*|2&v6>K%5ANB2q_cJ|*tGDHkyNX;jOo;4H_lN)fC zkQj7LL@b3h5|2-RRuGf-7S&fhV2$}Bg4hGK@Alno)KB0|yqAz|T_{mSyBv9%3A>JL z_2$ZxtbCMwSUZ)l#cNR3+`K}9L+L_0n)bA?^`afkya&IcZCkRTCwfFitKz1v85|mX z8Ot_;c|}PTp2s?$*08FZ8^yWmG0EWNTuJX9{`pTWvSM|A41k2XZ$89P>JS5AwL=SL z&>ys5!i>`f5EHFC8^o~o2+|CmOc7lu3QIT*q7pFpfJ;E}*Sjs_Z?*p;X8+$;?^Zhb z*9!g5KmV!K7d4??%7~gU8sD@vGO)mWjtR84?}<(gE*-e+bkJlRiVn%!0oG-aZdyT; z{y5hP`V$j>gFf(iZ(<4sP_pcy4JK?d7B&x`U1$FqTUUtvinhXx5eEqSSDX17GYQOf zYzaMI!kP&%$Tey5`>A8uM27w>8%H^nI}=gk;ZF96u~jcCcUrNg;$Y_1$XPL)j7N8e z%h86|$oP7=cqHTHe-B0@V?@Uz_BRwa{l{&_2;YqygNSm_4CDl-W^}P|Ifwo^)CRC zdu&s(=KJV-Xk&3Y>L3Of1rA*!U_rL(iL-Uy*A3yF@n<05a4wne% z)HIRK=Lk^ABd5n7#gQ1=uf!zjwqnZ2QVhiOR;8>$;gHkja0w>}jvWO5M*5n4J;d;C zG%}opv%-_%A)J35qlxwCZ`TKB*b5oANg;Xnc~xAdi+ zw~)=d@;VT2ZV01b0d;I*206(=hHPLXW@B^@O-FqBR>sv^GIx#t=}|Fo=*HHOBSt1- zIyqy?kzog5B9CAACpzWwMc5;MvUf2JV2ziuy=Mq{zk%(>JBctvF~bXL19Xqs90Sb6YKD=vk%^%D(uI#5uyN30V~QYLXs^M>k_Mv=^%VlqW#{CB{@(D# ziLE_v=u#94$OburaD0kbp|wvF<~EHQ77&{bz>9#kIf`;6fMB32j>&K60XY1R{Tp(| zz}%$zodY(6VKY8K3rw(ovl6tYtj_OP9UWxkP_??(r0Pi6-#TJqh zv9}F&qMV=C(7r>=3A9k_Ms8|+PkNhYHgLJH(vGx1gdKZxrFF)C+?6<%iiUh;w(em@ zs*%qol-_MD5oy&>yo3N{S-D=)Pkmt%>f|}ZO>|7fCUFG6Y_a2t9O2{Q^8{T#(h}bz z!p*t%RJuxzdBNluCD)Z)-;rFOX5=?{gmZ~>dXMbp4va9M#@>rCu(n(mF$9Z+bOZ^= z7+PCQB-h*W1%P6Ivlek$)Z5Gniso=KHgs->+h8jP&K9Ak0*fBs@OrvL7^h;I)voXR zX5d*y=1M@N()-f}2ZtcFz``MD?eTCF#WGABMkDDeTSKyern!~=D#QIs{*q>vd=&+xW@^Ffv>6}pFU<28|FBT>y=+blTiI?@5st{~{x_4zxshPXODTJHOYjPo~ zuw0n|?4$}GpMu1kyAO+5hSOz;QM~i2@0)lB8Ih`Ki{w&cyQCWi+8*JCq3)1uW5_F_ zeIBA6W`saRmx$~{;HE%rgKSg4?u2gB(N~1~JcK*S3hzm-QOm+M0kbut-MOeuLtPQ< z^APMfD^MkWyh5MJJ+ei-V!K3}4z~ruO$WRS;>{d_BH-sC;De0Xy^&S=V<+UB2DJs^ zO#{0N(#=3$5$^L4?j$QFgRjHcny;l>`=chA1~3W^OWj&BMc%n6%*KAX1d7j+=BExT zU$T;4e#sl<+kAd0G|dX$;Ou#hoq7q({?}P?U_XC<65&j|U7=p&aB?FtLcprUV1%&T ziPnptmU09ieOs<#fK4sxKr>#vsGa&KLB%Y$Jddu~yL zpPj=wGUZsV7_?(asPBmpec)2jg^hJ|fo%7s)(=5Hp{59(=9q{V5|P;B@R_|^ct6?w zIds^6XUpKs7(>H^&MNxIn}QP);;eyTzUmZ?nor@Q1; zJE>oTD@3j((^FkCt&Cy{308#>Cc{!m!KoZkwbv*E=j7rxyC}Bs_>b3 z@5pM%DnlNA^K5lKZd2=Jy`t?=V)O927<<~!3IpO)eTCSLA{dGwXE`OfYASL=6v1xA zIZ_CwzV|9psb04;Ozu>@m!XBMMVOt5F#RfZJk_(!m)GI3yi?#UihV zMMim1O9@hFUxAbf0jbX(J5?WPs4LcZJ*+X#i;D^oLferhg`itvktzWv_1PqI2#Qr+ z533yHMP!ADq1~940>CY?N%_#0`b?66zG9Kr!y=Qsn6E3uTJ%<@LCe0K#IJuoP{ibUZNXqvL58v+Jz-@HoE4@ar9jF7C@iloLA)u2)ir?8q% zS!(6LTBcMNzib_rhJr_>Q3`(*)o>sn=s^%Ccz_PDk&f^^GI}?}5tX^NK!*ev^nsWZ z8UQoLE90m_P{02WR3%}~4`%(0P!Ac7cmj!z%u~qVwGD~0NFlp2VkQe%maH)#gUoHS z?=?O<6~XBiLiWD+dsMXL%<8tORLU7n`1-wc5tWIQE*^2F5;bVO@%w+Z=iNdQ{`0d_ z!CjQCkS%7VHK~*_{X4r5XS9?1a9lzu7ezi8o{oN{^v{o9AHV+k@Bh0;zx*$=K2DAu z`}4ov>3=@{^6tac@E7Mj{doOoe>%Va^?%u-cC>l!WpB!N@NBYgkP!{zhGK`9^Ay7+ zp$@}(z1=`A#4IW367YXd;LXn|U**NZ<#v}Y{RlRzguxXJDBDEK$IYvK>;MDJH_N3c zvYe=BsBdhW+ZYi+=>SnqYiUDk+&mO@*AOGv^A)amn9*(2c$l!;DS% zC*(MAnX(eUbL-&(HJKW33IwH!yUQ3{x)GtXN>8YoM*(H&C#@UgthvE&z z8;UpLyixHs{xmgH@8Y@$$5gqr@3dS>Nr>`NipGZcE4y%PI8iIcL=_MYaaFb4sR;KZ z^Mb;>l=jwVpp@Z7=}N}3$|4N9U9AyA zdN=ALW!Oobk>03`qVQ_myxTHQDSRdl;!GB(i3_-0Bf`WC+(T2kR$~v(h;Ae3AR+Us zN$`IJ_)-;xvbrx4a`9!*W*!a!6cv;+>Dy&qEfl7 z>=Es#-c}02sTXFZwJMeFq)x?upi}YM>7r^dk90QS*CO+liw?PJ|bb@%7&qQgh95d%JMh z+8PW;!XL(<0U6A1m10JIfKG5Q>k)LOcTKF^C328`&$Wagx=XasLg_TuVQa|$@RCy2 zGFP@sKw&-~j(gfAd=Pc1YVly;&Dywn%2jZzJ*sNGX4SU##$ci~zH zLibCbS451Ejwe3-0B(;#Zs9Awm2ctViY#E+P7nUwx2JMmjxx7Y_)ZQ9xTaSlfqhLTObV2m{1hScO_O!=WJOQ3 z$M6~@*ZFm2fK2+M+*D$Jp4zcnlF+Ju6?o4C(@y3`I(|DbQGT#^{z-qFaS5WF`Ag(* zCTyv4atgF(DV?0sZ##sUKA^J2lhe?GjPc#10~iIie6K1gt4hkMlJc_%!-L$+>`TP# zt*eV_UsaI~s{U;i>G0YTZwV}Se(#dXw^Ub2ysQwIWL)eidE%;R5udB9B0hqD;rTo| z`|t4bj4)yB#2$i$@pGFp%Nzb$h@%NPAu=Nv?9r09BPA{!qgf z5yzNgw^Jz+p0#rNzONN|rs{1k^9+(MVwto*q6D`yn@{*UTd@1asRM|y!45|;8n!Tq zgYR|_N`;(H`iHsYJFZ%*@N-pvSm8$~m9#oGWfVbiiJux8A%^hI4N6tS=d~B{Q6lGj z(w}D4<-i1!k6^l<7^*LJH^7ncxn2X-CD!qp#|WW0sNBEi4@8BVs3Kr>TJgWhggg4y4e<^5$nt ze8Q-W_T7*2C_3IjD|DTLwQ{-qXfBr&LQD#v)HbEWQ0qZ4LYSRXU8ERzcLkZhFBT4B z(jJPW$n;td&Z&GYOZ`BC_*mcdkUWW!643oVXH4Ir#^TeWz zBdxNwg5Jp(J3 zcSDeJ_%;l#8tX}(EtQrhMZ(Rk( zP|tRWM6l2y0doX4T*5O745XXTM!=SBFmk{ek_|M?t&sW-B8CIjvX+T+Ll_ki-=b0z zfI>uwFmMAgh)oC3g$D|M8Nd-!<_J0OS4NAa;_5ll8AJvsr{5Cqb!+S zi{wd0jQXWu^kYNDht(9yVGvnj*&&2| zXx~kvjS?d%&dF&>mc?hMq)Fpiphua;jV!gM^$+F$_fr1l{a>qS2}wVl@4GA`FAGhk zHGDji00)zvw#Fp%EAA}}#@-q8t@*`bd2zoHW+_V`p~3_0AD>nWNvnMtS@y)Ug;`I= zF{cTnvPb6BK-y7%KeOOv)zfDIuGAH#nZ@i>uv`NjdYF;oA=SnyWH8NME3ZOb2rr>Q z-LBhFpusqb^=E+WpVYqNn+Fb|wLOB;t4gmby{h!8(yJZTtJ93U7gw9m2VzoaH1M{k z0ji{B>*>@;e=Vuj_!yq$He01dl@=}1qDr1CdG5;dSw>QSkrZJc5EJ>pb;Y>&e)rN_ zbkmN|_ApkmTFGi9tCg(okgOi|Gm`0C$%P3t@mF+-EEDTcUUk<*cBjF623elgZA-E} zV?;{UD_O5(y^{4^lJ&!kw6&-tYwTx<0(w5_-lm@=F$N{il{{DST*>n;$@5W0o|qJ2 z9}z(|WUdH*`xR|J*mNzfC#WylGhyyt%4c@nj=;|wnUeiV_AA-1WPg`r|2QMHP)f5; z^d7lVyn(b2LD{{04|Ud#M2}*xWVn*yN`@;L-X$4+kda*~<=2Hx@1t(zq`)aJ%Tu6L zlIg)i7swxwVAF&bHl+)ve&A^eUhRng^Z~1c4y6izI-?5md8%A`U-H_;SgKxId2K3| zQ|Yu4I&G4f`kgM6lU&h6rwyCwGzmnoUz-|jxGRk|R2ofbv`%ZZ5J#1}s^r}RS7BYr z%vV}ZX}vO9?=UyJ{u05)>GeL0N*ZoXsaao>`F*ydzrsUMT1#oI&S}C-q4i{otRxGyi%{bJ#l?L#50#{r-_XOAH0oNr(&9Jt;9H6>Q=KF- zsA}a&V#q(sjSy;&ru2ESJ|FdSGu%1BpV0Mx8nY%58zCq)b-DX>BP|}nq8%L`9hTDI zN`rS$g9n_WPOX#{d#ze*kemA-2+P`c|? z>#k95Edws2FKpD#CM*C{TZ5stwqgOO_LNy9yCd*T%Uu9U|g? zy6Lto08~@2NqKaFjRyH&QABp2)YK+TDYcF&wSa$0(n;HAd3^R?@NBT|!Js-7RJyy1 zy89rvCWoZjrg;D%D7%l?40YCyW{zU7A~lst?u1HKGF-`USB6irYI1A{!)tW4nLArY zuud%*9*2^C_q+VYZO#nmx?u+^@wPQg6m{^|rq;mf3*;4xc42B3`qB5-c< z-Z24eg&ly2!ywVoe&ajjV?$0XTJn9FnhT#W;hZMTXYVgAGlQC2pP+q*m=mwY@RA;= zj&j^#M#TVkZja~Gu6J2{7(iKDDaRxVgKKIH#Zb$>3|<*Q$_Q%D2vQpUd@`DUX5?zS zJb8)MqRhtM8{{;SI}t!x@@KQb#{TEeWdu(IUP}Tfj$^hUazD7zSICfGiDkMM_wCy* zQVW}|fg@W23tPy<1hsaTt3Oxe&VNb?rJZQ!Vlh)qb1SwzpNwW1X|Z9#JjHO?gk^mo zS?oHe)cgs&!JLh_I{o&PXPd`=p{6q}!DbahJO$NqTq`gzHfxL9*Ake|tDIttjfrgF zFv!|t+2_fuPvei!5+$&TzAIq}Wt%P%rFtHTZZg`qpOLF54I*K(ezul2H0rrAlVGx# z4bHLKsg%6ADl!hVxq?hVGmp^{2>d0{bU4S{_ z+_;et48SOWV!MG^Yb+U`)oc!^qYgt{GrLXEj!NB?O^?a82^)st zSU8B~>&gT^Ii9RA)Jkrw z^kEmr2OJv)u*5kC=Sc#8sD(U+-Unw3K&a2&516e0B6PD{0mp(m61>ho=-m*6*$Ua5 zW6*>91$e-wDI|rBI2HB)wWS-3iw^g#N%cFhAq<;fO>J~Tyxu%1BfqWYFe?%hiACR; ztQho%(|3a%aEbqnJA?ZL+FD2zr0UNt(EV2FTGB$Wa~Z5 zNXT>p1w}mT2Xo`pyFNbwCH?UE%dPMVh4P@^L8h-RQSLc(0(g$~p4~$YTRu9Tyxn;i zIlNvY14D+)EpQMqxM3>agS8B-kaoOhX2a#uMoUgFU_ouS>HZD5bdR?AjuYTT@G*4A zKNtsHZRehU#?jf+l^}!MrX^0cJ$4s1`Eb-52($bH#3nNQH{Z0uaHJh+I^;uyy5Kfo zBWM7=O%cH<&ayqbQHJ9r;%XwU`zneR&ojMLghP9aDj*+<2Ra#Qx{HumOu@BZfB=ug{TWMSB!??))t)s z?#05>L&}TjfxyHL19Sl__l+w=eP1U9b0ox|=j|lukp<$^6PPUs$?#;P2*%j!Qo=AJ z>Y=vi*==~h>t*GGjHD>Jo*xl=|7andaoG*c(~S*XimA)g84%Oio8dLu_nH)QcLwYn zK96(^P=n30N0Z0!S$HlHle{Dwe{NiplfM7I+8)Y|vehIbU%@8;vGB-*O^z7CVA^6J zAK-4eCX9Chs{|PN{2|yvp7jBO9?b2Y>!f$N59Xk$Q5@dfu;%vJv9mXJ~TWPUI#dcckgB(*W*0P4NmK;Hzy%xvJ^Jcia z7b(L5ben)RV$gsLf<0g(e+Sw3$ao7)lL~riY?c)*WAc5OQ=3Z{QSIoMSvxEF!zoADad>fUHbwW_99v8aZSN%-lS;m7BOhL6iUfH42K|eEa+U120Hfmy# zx)8E6tZYn{g^J6C(vE@(P%4Vp^tv@{YB_-eL-M)U3$+$e<@)$bf8{Pjjygidoqvn7 zvh7Mz{~$M-`M1sbGFa*+wpx*2%+c{DOr8})^=ydOoW|NTZ{&&9EofXu&kFrH>J57X;dIYAF#M5K&@eZc*(aEW zTF3>GuZW~4B*}c%f2f>)B?f1`xr01gnY(LT6B3@oTEgP=JL^8eC%WZT$4z<~?Iwm@GY{m$9H zA%8#<8$e${8|sY1S-60X0Nnf91IK&+?t%W^tOx$n1AE`Ef11tr;?$BW!X_`W#M>`r zrCd(WCJ{%ukzN6RpU@4dn}wVLsf29YV8SNjpTL_Y7K-dG$3khjbCs;KOb(fP)C>ei!m>XSp ziFAY;dAwW*SzEeGF*x_Y9x+(x*>d5v`E zdK-@4ls{{6fjGF!7T4QD+9Q8rc})kU3&By5P`#s>cQrw)B*#Hs!ZKVP0Ff&GG@fo!RVens1418*v0eLcy}uAZ-}6R5Ay&U=!!fGZo{6T_ld zXpb0xaI;}iGq;A`DJ6d>t7+vT@2;G#w&(WcarMt4yin(Jm)E{&!Y{=Cm}3I%?R%nA zu`lK9<)Fzpw1*F1Lf3Rc5R2YPVYR<87YmjV`On>RcGx?N=7nJ3m~CZuHAlrt&=&Wt)fG4P`&^ zogQ_LFrRr3)ve0sNRKF>YEx()MGKxFT zCzF0|*@3He%0gY`mxZdwhXr+^YA|0I#}XVDAmDVN43y%@*TR#7+$4VCn+xuut<94m zFs)g`VW594v1Js^LbePeka;N+CgAjkzQ_EV34O>PL>FuH~eb3Wesn_kQ!n_Yj!oIe(Gj&iFE__WwGXDkXRJ&WRJ z9UJ>6xJ1fq6k1C+gr=fdicz!EzXESjVft5yd!H!*%$x7TvW8w1ux#oHMHJWxHh|4Z zpW`g61(}OI*=8=R3l|173>!HPG643W3D+AIcK#X}V7>(q{DEvo)Vzh@gc?W(Z=~}L z69a$iZdUSoV=}Dsw|f@U?~vj5!ddqx;e3PO6K}PG&T2m@QQC=otex50QAsh*&A#`U zp?S_#98^0wS8=Gj%(+S#K`B8}oO9**ngU^=vaVFtRa4fUXW^RAsIoPY;GmH2 z)q*y|`o@H|?{jTQ1w|&Y9IyB}!7*-$Z-Hu3zT*6Da{eqg%E-Ayi$)yJzb`Bc%c&Kb z$hbs{5`VnSL6$268-iPhuU*`CQr15m%e-Q((Pm|m{b$pDzaP5J_Uu$_)xuZWj;9BQ zlYY<7;upW4imJNSNnojd7jD_SmHIL0WeV?n$Gm;m&y6^8xN_Ju;%*6{#(g|*+$AOp zT7u(cH#s~XK&!*&{wVS*DSkvu9^*)C=mJ2n#DDk5J5B}jEjT;H9#Ia1dY9k16mW?w6YKD^Wk817FVz7Z_TEkuP~3S9k7!YwW1ZpqXeF7H z;s`RF)c!4Tk-KBbpXi_qB1&FgKgbkv5IAHX3kFe+W$Wy;Ibd7jbx1 z3>M;OBzXRrSkN$#@ovk|88OhKxT+7%vH!-m!+XFQyC*HO?haiO5xt_PNkZ;SIBayY~lA;W^D+!blUhu@vpn_!3sDp{se z$ucSu`FwIX%1y9!IED(dAmMEPl3|`fl&50Y z`V2eHO1hOScx)K58g?y~jl#&kyf%+Dqi`BCX9BIA-*NQpe|NGf+CHBg9%QA7x&*)& z)N5vvhar^M9Lwf1M$j69g|lJU-2Wir^-2)F=%y{Q_i)bFNfu-)$IGJRdzTjPCr+7` z3OicuaIzT8rqlTzT8#R8W8)C*%|}Szo59KOa50|4131-0ss2=c@*J<@VNd%6A6+Em z?-NL_!a+`ufAH6S$je8YZmd+G$EHaiu4(qGt(DH*r-*DbURI6%@K6Z3y%V1I_%Tix zxhmiJ6P4!X4yG;bZD_<*di3VL$~W!-Od>)dwCbhmEDK7i(sAJ2e-Rf%M81?{trKWL z9kZ>74?Xs7Iv2k_Tt$DoHnbr}!%X}clQl?=r z1EuK4Dc4ff7;d2K53>@-UA4DiD{=f*^Drq6rO23l^W_$9*lPa**=y`b$4Ab=QXG7K zre73rwUeckf&3WeZ(`okGV~HH%A^}U*qEUmB^!2?-KJS7=aRnOA%}6>LT|!tK9I7< zPaF$we_9A5J8*}%hfAYS`wPfc*TSXv=F4q{pw3Mnp&Z zH{?PB#%v`EqCN;?Nce8W@BfeYu&@#D0_q4re;c^~Y-H@;kl!dnN8oye9k51hMGe2= z`2w2^*)HaD=*SX~feriCw=LT%NuEVxyE_5diFYl^4Ld`AG#(wy4oB0`WV(~Xs3ZrM z)GBUq)piw1)>byIR_bqgf4n_!-GWPM`}Y4tOQSyw+bFoCvjoirCDrZvxrezPO;+@nvqKeE}M%^Qk@Ho^XlpSMWY|er8g6tX!U7(v;TEc2fEdI;hMkYQd@Lg^eY?^5=`4hgLsme+(v| z+XtcuL!vwe#E6lFmIhP@j@jM+y#57>G|P` z*G~`fb1YL0q6#vTe_zIH8x^3Hya~KnIpNvNf8Y+~8BQ`f<*6-@^EqUqlIc`3or)%W zrFFihll%nc`uF+;-{;+E6v)Wi@c#T1>1GL?QE<&)VHb7uNA9hEt=w~ze}izwl}Gts zlo8aWWOSyhQQVUh^TizvcXBh*vzf53+g_aJr!qEQw9pe>oNVeukl9V$LVCetzoFB{F1IO=F893MosH{+x&*ESFCd zh2D~kOrZQMVeLOx_dE?ovl)c_@!oJUJlGqL=YzdDG{$>#qklL*n9YYneY~3(L6u?h zY@9mC&oH?}oUDIA&}5DBOu}#~WSe*o2k*Z!pT9kNd-A)Eo~NZbg7+Ue^N zC`~u=ag?$R!)Uh*nWiI>wFos3V3dzVzM zW-~b4n@lGMd*i`$wl`fY;NEP37X8JvKS2nEuDL6URqyxR7&h&2(w`3Iu)jAM%#FSA z0X*27>;35-T=WkX1ARC_2SzlCI|t%5bndvcK+t@9-+#+_N?eQlmfIhf8}cW_Ogrkk z*Hvpr+OR+DfA0+jdxPP1e|9t+9`z6Zt@X5DsKeZ8Ur~o?JBiN;I!SSW|28sU&*Z*^*EjT_T5WY&|3wLQlSFpV0bZwRNx#P3>rSIG!FJ&ia$tc--T!q^D~* z7$1(Oqse$G9$q~_OFJ42r_=GQKbTIZegAQ?{mI2=M?0E~d)i0w*B1?by!Z?TqtT&u z8^gt-e-7h{@&OZrK3LwB`h8b?eL`!>CvDglh``6_gO3-VKQnCNuTZYVK(x7lHZ)CS zVrQN5=;Os_p@82(2c`9JLW#byZA7@9e(Gt17%J1zbUNurvGJd^h)}qn1WsL=pH5ED zFox8ie>gfE52nL$1h2tl(4P#3hoecWs0F?Cf78($#n2lKhlAnpV0<|2NAc^A`iHaO z;9$@nm%?x_9mPok#ZaYzbQH%i6er{HaD338jmI$*BSN7~6erWe!EAgu5v!AeVz<}0 z`%B#Y6+Y;Wn45G^${lu^0j8a2fLX^G;Hek3j|e79Wgsa7X*UMa?kA|SQIsXlLXTh6 zesW8@yUb~;7wPd)$41R92gk&YUeIsLAg zISmlng_*OH`RU{YmGu$i5PbvGV!ahwJmcYPJewR2XOjqa;m6O2U0gp-52mx(XnZgm zM%Og-`1!Ew^ul&}T|2$3HI1HK2((5X5BN z$c1bvak*`pB{k@erw50Vm{ZJsf7YT$EW;_#Eo?eAIUSpwr0?NH(McYugC!TjR%?xhUx(;}%(Egb82gBLHcsLkGUC|MLXZy&NHAja1;lZpwe;p5}v8fv! zjz`nk!DxKgcKlxsew|&`POoam7gYr^S30`t49&+4n@-Vu!p`Xu&8HeZO`>^H(9Aek zdqK;mG)B*4`m``Z-JGHpqCJ}6RymwGIMvR;ujQlUs%KDH$MKQp&xl~R*SG7-+x69L z&m3wl;M%r_T9I!p#PaNrfBX~fo{o`!+%W1E`9~}xdXH>mnOKJ#%YY22WUuEnkebg= zCnu=WIYBDftG)1?P9fLnb?x-Bs$?&f?6ni*zK>+D6gx;Ie(lZ78|2?l{|UP|xIf{e`1#S=$lK`qJ?%vNE&k*HPw0j) z7wXf~ZBMfxW5^~KHnot=u)K|a|7ZShXc(9e6Pn?-?oIkuxpV0bZwRNyAt>NM>KB4v11Cs?mGyPeYG<0-$+HbtgIOkC?4Cb6}%2WeAv< z+-W^+W1HHMwqne3j^4gqiYEIyUB6vm6X_I_J(hY zcG5o2#-1%iLK4;#z><({CFAe@4glWoH`$DX-A-$f;K2cKZa6sS;G0G*L~Kjfj{l+kCDJ%DVR+CPDB*W{YvC2$VU z2tzi3W&|65@Xvn&f=$`%n%RhLZ32EK=sphdryh7`+rLqEwY4m2Gi2~j9{IoAuQIxL zW%Yl$CXd(TufP7%dYZG{Y@ofr^0ndlfk zV7A^afQ>ekAz)&1tM#<4ZEDBbnlZ~ce*JnSnjGqM^Lpvh+ks_Mj@N6G)9&kqNf)m- z&|%1behn@B+Op}x?msI;4p;R5olnN|q4xOL%ct5CN|t!ln06(YbPA3%DNDbybq*Cr z+SR6EAMd?Ta{e60-xgExH|@ekCv>yHj8Csk%_wQ-y!wRf4JMGG)VHSynit!JiJf)& zd+fl4iGIH)$bJt^a{={Rk00E3e^UE4{_?SZh~2Evqi=EaziF7Ejd)XnXFZmE^dCUm zhCBW{ZFKDcPo0`?Ub_XQCW0i?GComhO_R&q8oo(FXbJS=%aWdx{wPO!ULo;s{1w#~ zodJv#x!D8O0K_#lcm)^uF!-)emY_9<4vu$YS?W)^HR!(fPc>m8Q<@xq zL;Q8d5Ij?rY&Q#JC&2tB9s}$E2>d3YVUNb6$^2+E8%<|7!QkAM-#2p(#yQOSCuVEI zhWBrw35ni-Lt}t4*>r&qKhax6-fZZWaFa*J#^DJz3i&hEK@O9;5UX=%atzrl8b=43 zCcSq6qu}0s0~YS9rA;?r!)FXY-VJYmMDN8<$(YyV%0fC`?f?|C0-yt~wf?mh0k_4g2%MaqUK207?a*Q70R z6J6VK;->#}lE$Tr1m3~(0@)%6nJ{o>Aj0qxr^uNT%$LKmk%I{1E8-w?c_7<=EHGI~ zrr=8~mmV1a`_K--8RH^qN$m|Xz+wj=_(N{BdjNtHY9JlFx?f{`4KOh{zeR@M3!l5604D?pKJr#;=&TQ;qVJpbny)up?uLu6P)Bfd?-=XpZUjeDwir3L zXk-1CKKyNMcXVU@cd=Qb-EuU4UgFVqH{EX0cz8F~9z#;oVKyeK?_6pQC+Sl2Eh1=% zbqwuY8?rMST&of^yPKBfXzqBjrD+a+o?u-gun1ZKy5xi}glZX?t3<34u}Z{tOT><* z=_2-Ijr7|Ko8G~NSx>4)AmjGQd_EnEGKS}=-XqSw@w zFC}NceACWO`7=R^+VP;@@AuqMXvcHms-krHNuWG?yt(Ol&ZI8|-lVAOPj*t_0~eo^ z33t6x?(fF{+v2v5DNe3`(D*6<2&tXWib_veeNB|ZN{KbkZ(GLKJQ$9+mV@LU3_xAr z3v2`pU{d{7NNx)<&YTyKl{x%5UkSE5IHF7O!o5UUCC_~4#@Oo}HaYi}}q&>xQX zBF3XDTaJsfk6^?BO%n&FPXVd(9e!Iz+K44N9`r}Uo+iFMkvgFbBeUW;RJi+G8$KrF zdhQ_V>51=I98PAr;?T31Y70XFAWIZ}xmj$n$uJR{V(0MP14G0>hSYpg=vhM{F}VSE z35h{BM8r~9Bk}luWDPNSXHk9K1J;;7B8c5n`}WY?M*Rd{#d`_a)`b#Pw9ApFnXv1~ zR&TC6$;wB`hqYG;Tf7Ek&CM$$IFv56<5^D&TQA!2+}9+M1S&Xx4`{-6KUA}dyZ#{fvE`{qL&r4BI=R(rHy z2K_+`Cd@c(05Q?Jw?PbRk08z9$rRCrqOgS1ASwZa54Z#rf4$u?{#N@xV)p-i^>(e3 zf34B~{PUk$eNhwYrHrTvqw!7KAOj1`7nneM_m1e);L?H1P6tiLq3Dpj9bjD+>8KSn zo#$FXe_~>P(0e}bO-!KxN|rse#e_}A!sg+#>l}W<))ivEqMa~f!~w$L)poJLOagNq zTSCv5ux0`ba!s22e(G2@k)c1y#!*h?-bB=RxR-rmY}L!komQ-=IGBYsa@Ncyc*wSA|5ukVnQYEN^xQ$(jJ;=S;LQnP)E zpkZQywBs?~@j{!4(MpOuBL;eqZ?0~!W$`h5ne+xiWC~I2hJ#j86+KPZ4l=S(S`f!V z)kj`%^GQ3FR#AQRlI*FBmPw!yicKtIgB5m=5*q5RLMbH}TBWj4lQBQHT-Z{^y|?hy z!ZOo;eAw|(dlXb}49{jcR0=(PVYbDrpJ7|r2r~2*>bF~~o>>tBkY!Q0r*+aaNVNIy6n*V`P}v5g1@1 zV@IGPzillRqrw4^+ZNnGbBnaP=lE$l`M0fUrr1*AVaWFK?IzRw&Y62YNN4U-xN;bO zwb6%@TC5#>o}QTV<;H7qwT8BFDb^ux0}uerwfs|{Rx-KM^4{-5JzI@uo9D`+lnb8OED1BTa~g3g+oqTz!jV#ICc>H8|fSN^$5e; z(a3O?&KggLM{x0VjK|aI#8_^>+M~aJm(F;xfyUH$7-76J{?>Zh)mGP$6R7Zad{MPy z?Rwkqk94ub;!o7T#&cmN4tsl==T}U)4n3@rNiQ#7hfn(%`FI|^oDs}0H1StSIgNNe z2CKGa&w$rd$!DXPt?#o?!TxUtKmxWTcwhjBH#xi}*Tnw}3h|&*;$Vk4fG)v*5;1+v zb(ydg_!s|hfB_ik#i56?ZVkP3~hQ~g$S}C<8UAWm|OZ% z&s)gmU3nddH`jzwu!K4`F@v1sAVW5=5wkJ6gQg?Cd@bYZEt$K<|MaLBICN|4$PptG zF`b+-<;buDFp6aTH*_fq1!RL9K{!4|tkK4&33Hc54NHhk2jFEu+Z;u?5_vi49yXth8e-5Mgh;xzaj+W9~{EOGQJzFk5$& zk!s|#38lANOGH{V6fYq_Syrx>^iyBhggSW&aT6U=u}K`kFI()mB1ibR_&h<^kF>&f zh;VbRJ(aGKW1cZNM#*(0*Y_mX#~Jxe9^qUfo!%k4xdS5%sIm7V46H5JMGV1WAss;i zGKMx56Up_qd;y?;*sMjI7WFoBf}%N`j18UJ;V#(9fwN`kslcMgH@u!M5yq*QX0_}4 zz8QFuk+~93sr3G|!NDO&EwFG1T6;VkMX?MMhtWv7$~KT}p=s`KYUb{63gM>nnp}t~ zELUa#d#S?5ryw!s?!#i1;dB{d6z{z1`zGF_j7ZhAMRKXJUD6E$ZI5unQ1?i-G2|7| zJ`K^%GeV%EOGNe}a8sbRLAEJi_d>Vn=qti~62d*|XNC79*QjM-n}FFG(e7Q;rlGC~ z_Gt)qkQJzZ5?-Ot8g7w&82(*8ZqTrU8tC!&0}FOp$jk3bV0aE`j2cr1`1C z%IB=)mtXQm`8JDM&EzjiH2m(cyxKB)s2-A+eQu`wB?~Yp( z;b-S?flN7;D+cXY66!l*L?5_RbYWv1T_D?isr5t9PpBzEr#U9#g+wIwIDBUB7T!;G ze-0gg_SrHxGse&`p|g%Y@}}U#gm|MJ_Z!rF2`^ri1Y38)t6tiXoS&)?f@La`{^>4x z)lTZy;0lpz$@Em0Oe>?9LV{Icgvqc}QgA9qRP8m&z&W`%QA{QORG`r$N0qB;6lc&< zUxk>oO#2uI*C`JA^22?OCRyP=TuVwG#l~A+lj^r-BeNg@D$7PFQ5QZPV6L%Hrz(6V z-g~kdvdWN$-#l5JkDJtbSubdNl-NAHFvgx{g#mG@zCvtI5e!9;vz!uKH5IubieR_m zoG3AXy@mxWBMMVOt5F#RfZJk_(!m)GI3yi?#Ud|; zMP~iHsHFrcw68$Qgn-m%kG-moG}IMqyd2gT*oFXrnCu@=46Y0$E7C-Hx)4-|4l zNvCynHb}#E@3gNR(_MBXg}TwIWe?1e&HS>4t#8+c&RL^utl=BqJm%wj!x9MK!3D!zrw$ zQ+aX_S9LMKv4<2)Y-<3GSf-Y@{Q6hm77eaYSXV9nc{G2E8XH zg$BUP@ya-=5Y+EK1XW3x^T}+Q5$Yks5l##&@cbXtPj&S zj{W&xZ}mSPetG-;YWR!uj(+&`V1GQn`}Kd>vUaq2?qzSvckpDg?|G3P0U zD?%NH^?JL3T!>jx&?SH1pTMi1Q@+ZJh0E0mXDiP``7^nT5MM< zQDiw$(NN#oHn%Y%g3Xy^ZbHVH6PgM+QD@E-lH-!U|DaoaEruDJ z@Q=uG;3{P$e&^Q11!^)i-V_K*6?d00xNi_=Lrm z{eFLNApZH(?;n4QfBvoYG&j&ZztK5eNi5FkD%np75RW&HH;<1!EzB;7+%wLOd_5Fz zDBe)K5$BDHxACW`nR*x3ML4F)rG2O6Qc6OUmr^t~#9!HkW5bDBF(#^jaEPm_ay%DSEmhjv@@CBvd19WnD8;l9(HC0&#H7Y&KU3MK@mbi6s7Sa` zlcUs_;;1Gq8zqjFI9B3ViDM;>pIjWL?0D7n^=cU1N0-hLoW<{F^&n$yiodgh98f zHDXBbM}4FWJE=3$8=?BN;FZ3G=8 zWPX1&37!C7s-jR<_vOkFg-2agf<`8&rj&ajB4U)0F(Y}ztucw9S-YHO8lYBcYNi2h zCr~MYtg5d0(nA|nb_lQ>nuHl8U}fLH95ix09>o?+0(!yCsEIBr zmD|c5(VpsUr68PoVP;yZQt3|WRQv}z6|a9?9#kD3sKWzwc<^M02QRji=X{cp>ljk3 zwR0R}Fd7#4jzQZ?neQaVs@S(G_N|J2$04X<->TTRD)#+D6#Je}GjhxWU3o@y%2g3- zP+2GwT9(xiJ$4qb%3BbzK5}h|jE-vB70J=<$->A$JH^__ZmBGfmMjnXykcBI&!2zV z6Ku3Mqi+o3{gxO`t3WTd3llr*R$+QU95ua2K2g;C-qm*E=#UfP1!R2v4~5j+aNJ%m z9k#Is!;$cZF=#*r^IN5uk?)}s9L#zIo#|Z@D|d+;WZ!WuA&Bl0EwxZO&8M(6WL+h|4y4a|f{r7bbd7?ZlLEdB6qFWXz?6aQ$FP^1XO5 z7wwrCPq&h$q$MOX#^q7P(0=J`GRv)zbRm;Mn=(ik zOn*9Sgj$@DB`xNUFvuLvh{3JF9x>ea;_ZuJnV9M1`!b={a@CHNi*J7}J}wPh^X~%L zm>L4>Y==dpt#&-^`~RyL!tSnZ&A6KHbFZ%Ul4>v6`MqSBIIfr!C^h*hLgt$$>*mRd zp6Gz#4N9)_OUnS6=cW?-^VE*rl7v>Rz<+xtn07Kh((&7iiSmQR^H2Nzj7t#Z%wHmh zGhs`WlT)BQN$KR2e%m3;^Z}JEo}7jjWQ^}79l$8C<$G00SyfV2m6V@E7!GqYvo8^| zcdjm~eN{y|sQR~6q{C}Vyd|*Q`@Ksl-%?#A@w`G{lyR}Ak%l3eAK0jerL{Go;| zB91Y~Zm&`#JZt6jeP1i`Ox4?7<{2bi#4>4rLq@P8weN?IM8GK!$M#7_;45JPzH2Bj+E^U{m>D3NnM z?N74ma$thV>MdXWT5`t!JfnP=v|&DB>k6^l<7^*LJH^7ncx12X~)IKqc7-;W7?l)By|f5$N7NR$=PXYpgc{}=TsLd2Hssk=I_g; zgP633A}KPx)`N2@U&~TIkRU$RdZ8&5BaZ6_KZMqyUNlNZk(3vrfsT{B88r-fPxHj0 zjO9E>WX0B#{TUhrOH(hilN%Z*f2X<muRXG`kE>!}#lT%>;6Xnloch8<#tKRMrylc$0HiZ6T;M~` zz{=&_5TqQw4TG!3x=~Ei+4d9KSO8j>(;Q&PVVJBMCpCsqPCeKTy)3h1e{icb4Ep_k zPxEVzR5aRyQV)gZarq4F7iPc?1{u-emq@2~$bJv`Lf2uNFn}zd$d{XdHslhNRfA#Z zt*gKo>e()l2o^ddV1dAvOL#_sfpinv2-va>Mh@6OvW2F(6H?zn#Bjhy)-rLf38Nz7 zTU2TSP>2W-25uk*vFQN1fAl~h12|&J93khu9A*CX$=NAy=s^`7ttsJ6*&1Dw4ScwO zHWM7=Tp-&Wz|JkH0+u%22tYa|OI%GZG5;VKs$v7(|v>b{Mts66)yi1e&IslOw{@e*$l{H3C0J+r5** zIy2}f+IQ1vqr^yxb8=deW%1c5Y0|hB=y9fTBTKDm{UiDRgOq=H|JN#7Lefv?`!37K z%R-ZB10T*Lz`?YqZ7>P_ihB!#v3JINYksjdbPuPb&`?y;%XCmPfQAp z2Hy5GK$Wy?J)IiquO-zQAH$Q}W~;QQ(xOFLRLOHC&s}*wf6YiLk|OLqVj>^7t{4~J z?_YY0ZrTyr9>z*mD_N~%wUX6clGR5U$#kyd!UUT5E4oCMiFGKix@#i4)8IXUEKlpU zCE1=aA|>mUtXHyL$@(tI`dLQWT2zuX_OnC*J)LxK)6bF^gOcY;o-28-} zOp34%h#(s>e^-S4igxd9x)IkC)EDiUF!wLzGrMj_;OC7@$$lmKmF!otzeBQr*w08U zl+x@Yy+f`PZy@bMQ1&n1L!GrF(WBTa8LniwlHp2*cS(j1GO|mh{JOB|UDU0d6gcH& zc?z^jGCg?c0{H_HY?|=GrgZ7l4?Io5s~z#5K46v5f1y-CXH-ExPnApWOJ2JeOVw*D zuT8~rDxFqBrwubxzte?sk}I0%v|%%yCV>d{Yg3~Q_odN>N~0-_)@h9v;;3?0mAt*@ zDy%D+`AX|4tyf0tjdQc>FA;2b`*Ki|Z1WhT{h#o}I&4d+#7Ch{dX!q}gj!KDUCDG;rcZM- zoZHH-sGn7lv2Xu<%bM&ST2HpfO0rP92qo^HUEF8$P)Ta}4c%W!qpr0pEq+7yzNPp) z)kz|Qs#cyPhWwM<2%+|9N}rd|=SR62?wsIHf9Pg|S(Av35R{s_-2J+d77t<3jt-9w zOKEVW!8@qI1I|&WR!WP#R4q2k&HWDqb(0v45R{r)tYJ7t2!Xa0me$i$}BQIrO%W;>!dzIYEP#0+Kbm~qke8p ze}{;;Zn`ZC0M*oMQXZXPqe1>x6p=kBHML1oO0A&x17$iD6Y9nMBeZW3bK=z) zp3?)>QH~pBR19$E_RWIY^)8DK11M`N<(Ncaa80eD7;4#o9 zu&fUxi(MC#nm>V8n6nXAr{5m)e{AzO)O4mL*sNlRr=VJnYXt_zc4Kk-S_1QVl~atd zHIWS*23dP7`!t#LY5Wmdq6AjacO?v=Y|}-eRL>*PQARt;$W@dEkuX_5TPqtH_1u_A zFj>q77ufAoO5R)*83)>2L8hRY$7l%zbV$I0|Hm|u0Vn~EXcOA^itR1}f0j*kH-N39hmWnr>f#XSiwb3>4dh?`={I;6ItVm2G z7JYBBV$dIs>xzq#hwbjoCyljz^AqC;inn73ACJWKJFtaAM1&VIp1F?UqjWL1R_%vqTs zy6a!HlQ2zJ3pokVZW;Unnyrjt3O!bZ5hlqp*ru~b)n23A?4L?{Te%cBW|EmIkZLu8 zsWv5Ps76^hIlNv>Mn6ShQktb4HjNUhC-$<+8Nj@!x!(!te_c_2d7qYAE8p{8dYxX# z)_b0jkm&{rig?!d=GLiqeSQK;`r-4J8{riSgf!&JTp8yQ$3?Rd}3hO3p0R-9hIlG<+5!)tQs9&Pg-C&0_# zW9X27Fb=xff6hIPqqC@IBb;ixwdX8C)FO=S3QzG;KuNITYa$cG4Z z!EL}s&;Wd!B7#$#ReN@$497{t)kIwPRTPH=mk66l8K(sqr?rd7_lG~{#oUB6hC2z> z42@9l?Vf!`&o|Q~=gW#K822+W1jEAM0ue*TZ!{C9e=eLXfg1SS&Q8k;Q5R&c7!AX% zEjk0-i-o6$lo!zhfr%Xk=n`1&8&`<>zD^1jNQgnt+ey#^3&g1>Fk29k;mJr5jIr0H zgkeV1Lv7Ks-|&E!%gTd{q$s(b9}s)@U?H7x*$vIptqom@sms(E5YyS4;SDr^& zpt}Q?QmC``^XYh;8G$aTm+5PF<0Fm%oKKT+B_4mr)67U^SE{{n9K0gP{)oicc3nD* zK}xsMVvUOJwAcqZrdq6J4Pz}if;@XIj+y7paCa|Kh6Cs}0UN}i0T~1bz(x+T?~w5t znkE(W(%393TE^u2GN(3|E~47;mq~AM)6?E~2>VaY$Y%%nzkWjxO!zh`9qWXkRy{6s zyRU!xnZ&b<2PK$-YJI%0L#6RiX5h5T3-4{z#3FSeWM^2}n5+sFmkXsG1r?xF6tU@b zYuMCs0tbfVbFmj{EuzZx@t4Y7h#YlDUsq;ws+ zfz}tfgf|P!mKd4F;akk!^FK-{)NmI$3N?SPpL*IgHnswmilCW1D~RgZ5U)9nwQ1hS z6RTU$xQw0^`g7D9_6EY~o^xRMBdef!ZZNY?Fb%bk3nX6=Nl!?U`K(bn|47hJYpN>1 zyEqOxfrRuaI?;&YBxfChKe1_oCB!030g@e{A`&^&2CSh2bZVN|5dKC9#Q_{3+@OC$ zaD^CHQd0ubhr!NdYRP*IzpSue6gS>=sa*%}2nVFORO;3CG zU|}~9)@$RfR*M`Lo|01}q@I6Igzn=|jpvrv;1jm45EJsN707Wg3v1-8nN7x{+oRQJ zOKfC(Jz74H@#?>m(a0Fl@reCRhSm^U4-aemPG8^2TG>|!88HsvkD@E)nst(PwErV! z|KC?{*E;#v8vT#Y3455nbGi~!_A4evd~3!zb%PuRH|PHq?JnvQVYKue0iP(_6vdrvZWsS744D@ys3=!^(Z^Ldb+MopuR?X?@8JMu55fq42xo+ zJz@aD&4xwI+!}hPl%TApm5aQ)a=O}{+n2}HKa21}ozGof`=$xM5dUL=3AA_bh)%`6 zl(UzErsL2aK7bJ+fC_&TNka zdek|REAN6&I5iscTZ-GFqK=5WC#q6i#{MtG+{xGiX0}Y-1*Wv_^0grmS4uf*^qn#L zW<}Q>pK6$f9H6C4)36(L-+0Rtf&G=LQ_+&=)5$nDw_aXH(&!|O18A)by?Z@MOXp}V zYDI}mu{&ABRcn7T$WUI&A_sp6&KNK#5}`K?*&9qC6U8PdIndV-lODKVV|@*DNUq5O z0fQ1Z&`0+3$@}O~oG{*DvI3A8fY1OSe`ex46e@{rnm~tJ2Z2B;0t*pnauL{W)#`5N z{40JwpH3#Z3HMj6*K^8%n8oqY(lJHso&mfa{?Ep|NFaY?q2=tUep4P>emBKs6nCCa zCr7zu2d>&F3w4!W7OEZ}7Sx5R!F*vHOK@C(fYXICP>LsC3Qx{*llX;iF1U-fHcy7Y zv}O&5fwsh!Q8WwLGK@gxrA(NBcN>fC0JXuN5VKRkh2l0e=bDIoN4#1g+rKgmLEGFZ z!}Z5v!+C#hH35Hb)PM(l7_Bj&53wEY3nN&>dO_FzUNf>a^){X072g(;6<2qR0vPNh zDRD!tm)LgLPd)xMxh8PS=ms*(`FQ7VdNGS^b`^8}P|P{)=T;f;X|ZX}SQJot7RApx zHV#j4iImwWw3coNO+~X5qh_an1>T~<^sf;2K2d)Hm^a^vWevS3VA<3YiYTxXYyg{+ zKF3*B3o@4nvduzR7cLBF7&dYoWB}|#6RtNb?EDQfz+wj=_ygIFsCf&)2{n)oUP6v+hsA`3Av9-f9h<^MH{IOodqH3h;#WnHPPtEQ|y%uO7ZC*BPhS^{XzHkaVq zG0c6`imY##8Y7nH?^@701f!}`{f&n+B(Bsa>) zxkSrG9M8WmEDOu26`IJnM9UJq%|Vtc0~>-{hp%1S_fpnB9m~98tlKtnie!m~O z&i3q7Y}LY7+Ky+FqiMhAXYq^Qk405o>m;yLzYDi)-b(!#^fHBazGvQ^=0+SjTsdqT zakqp}<365O?h=zFEy3}!n;f2h51`fIbAJ^1l@vc9CXaC>HgpLfSm8V59jAiD4xF9- zK)c9}-sBSyL&i3Z#n%u)g3pg*YnpbERF!Y+F%?82eMN?XJ} zzd|xIF27ZfXVYfA!99SyM9da8k0^&hz02=h3b;g;iFNqdG9W|km+F9j4tr-O3MlTq zhDWrh%^RKJyJ#hul;Sd+)c!)2}I*p(o%Pi{iTi#M3CGEQ6xvf$(<2Dg?w*T+5EkL&&dm@H{< zIbS5Pf zjK~XP-A-IyY#zdQ{BevqdV8&po-)TJnM~RrnZ?kBJ>ynHujpx#kUJ9&8{KSqgW6wF zm)zr`9NOR8!PlTa?vG}F;}(v;lD7(`^6DN(GHhcQhvNtkH1cXX)8j&E(Li0huZ_9G2BdU5jO-F!C?2&120doW{(VKx^-J96kAeovezs&!`3BniMv_#|t=tGfkB0Pvs}i@j4#%w2$z? zMMC~Qf#fP28gZ2#y}7UQje7u-h)@WvdZ{|gf|9Cq960x%#RUj>UuJ`iIm z(=eEUQuO1LYpH4sH&FJYti*9w?QPjw9KY2(Oo~G(GG4x_WFJxCAzg%ujg&OH8@4O32pcO`zF>> z1W>U`#dLNWvy#MvQJzgTc2k~<{FM<*T5?;)M;8ynd7==Uk_F|;$?Mu>8Otg9lDKBq zzN_TPd9s3cE!q&@kwupbXnDT0^dHW*G|iK}Ga-K-WtD^plWXJPg%Fsg@e3hPt+J$w zVtCPXKF>;#acRJ&RtuX4A4>Z>hZ3CO_udv`gojh?EByg=mf9w~oNa;`|6?(u9JG>^>76 zxQY`oWCW*SMaN>%UgF64xFrFn!UJbZnY4dlndq7TfvGqzbi}cqzf?Vd_)b)uBzj%w zlsH%(A!1_SJ8W$E_$=)3%zFFo&P%)GB+S(<`Ddglt)J|q^euEynN!q)Q_~9@OMKV#%XP$MglJmA81|s%n8K-` z>zKfy5$vVhdMcuYTG(q<#$b_cgPOrwRuO^0aKu?eL_Z#X>G%4*L9gHI-}JOg1P$%@ z%dj`%4|@HZ$Ew*3E)w-B^2zSoF8_bCfe&XA;H0N*FbRIdrA9DsoiXu3B@)~Pd#>sE z;fmMKhWR;`sRmI6naRH|geu{Lngw80q=C81eI{G8`*1uNnIm&-QIOEEr z{4dG~>QXW~)72>MNs9U6j)!}>8R^MP*q3cDj`LF)8^^R{MYE(az7)%4*gZS0C7s{h zu$eks?&AM6Z0<+B6fk#%=$NuBt-UrNgRd>f)>;9(#6CUL&o=vH@0$ABToC(qx4q)KkP-sW zMJHVb%5|wO^@1@fADn;k!6_eHpafl?!gDwpx+-!98JTN;Qu`L!CzKG*0Cgm81VZif z^$3)v8~Hd&*@j`XTZT;25y@JF8VE4T$0FZQa4(uV;PT?6#kzkg+5PExVVDtOE{Wk^ zbWtz5Jor5O*n7Lh#^LABu`mt)%REye0AFwbUeHIS4OV1Kdpmy$FTgnUSiJa~GS&%N z&W!mS4iBcY>EvKMn9UDn%OyORFVV8Uob{&&q0lvVMX~Drz8k})9ZmbQ!2uz!Cr7#s|SpZfFT;qbVB^lz=F{X!k)PWzfVOxsI*PS8n;ORe&qe)5BT z1(6S?;V5$c>wAi_PYYV|siFK0(%l@KPt4!6CABw@leGaEI$(H%(yrQ;Op+a>@}op{ z%|{uT08%zyG02+eH}QQL1s4~};=^JECz_SkaH*Zt&~Sg=sGdN@rJ`J*;AyJR42NGx6~19$MP*U^ttN=l#KKHtYM3lkHC~K0Dg+bllTEh`+vQ@WaJtFc^)F zw3`?%7Il9ZSCsdd81&xquGH_l;_D;YP(EqHzCZ*%L?3*(`23k+6MuzrEe4{^1+<}Q zA`?5Clt&*fJ_`l>7CI=chZ9Qlt!*R1_4H#;8^lnVjb^iHKZ=e2tVM*v{UmVe()@IC zf`&1q2K}Sa(ReT$jw5&tri1=;FgzMfTSYDCt)G96-YACNXgC}Uhm-Nquph;*Kk6UN zhl9zWKQ4vgK{|@l1d5?b1L-J^V<=9?c8`Gr+v#4Di?s+eZYGl`@c&fwUh3Y5x;c*(k~qXQ9W> zY7u`uF@9Ceq32)GjxT7(*Halkm5iU~C-=C)(=l?7TRWX1_s5=pW&#bv!bnFA%$$DL z%$x=Y?ZeF3%lve5g39^`a)`bGYO&r5EuQgkKAumHhVy9zyYS;D#4fHMXOr1{J{nKv z!|0lZ9zPv+onF{ZuWP55wWiUt4}sRm=-GdhJS*$*c^0aV+drM6`ndJeA*v7AK5nqc zpk3Q1@#wj2pRx!&k?qrbemXfp`%#f)QLAeEbPKx{d;|N#uG0(K>2>Y&vbJaYG!|%W z+dgf`v;EjUEv;P(zMuUe*MjF~U&tkGpP@S5+MDh3;~sBy>u9`u{Ev@czvYwX*5ZGE zhW&AW(4UW|lc|dTsT2S6Y)jnz6;?-JKSKP^voS!~_@C!ufRJ%yKn8Veq}fKDat!?Wybb+{LwRx3KHJ)aJUf52rYp0hrZaZ}fxwtjeDdgg2Ri}{qt`6Bc zgj~p$5|`ViSyF@kcs4nj#++jAvlf3nVi`_>Zei20$?4eaBz+Ihica#-pI}6Li=Od9}MS{@o+GXx}qcg&i0WjYmN;2!^ylq8xMbHv8fv! zjYqTjWHdf%JN_>Rzs@der&qP(i>d;dD;-^RhUVjjO{Zu+Vdr#-=2H!yCeb`8Xl5L& zJ)`AQ8lxvNeOj2IZcb4P(H>23s~pZ8oN8y_*YZ(v)ibE9)Z9^?fUAr zXAU(NaBbT|t;n|)VtMvR{t16~PshkVZWwio{3DhTy+by#OsvDLWk7~hve(lZNX_S` zlM~eGoFJ9#)n0f`r;zLPx^{Y5RkD{#_Sy?_-$$}niXEg9zxHPbsl=~tMLT68DHEv+uA)|?M>z|rMh<^LY3!PxqSYuP zwmDsJ?%vNE&k*HPw18~ z7wY5VO;58RW5^~KHnot=u)K}_@Mr#SXc(9e6Pn?-?oIku2bur96P;x0a-&DA}V1V1zaUHp?eKQe!L>}fXodyDNr zIT*;Ykq#MuBDmr)OYB#(>{4vww86ZEx<`?a4`+cFsvM zXJwFW8W2>7B;Jg_`yBzc!GHrcB-*T|Gus&S^5}W}NqQunpyy*keG{I*UPtQ;paN|& z_29`9WHxg!Jb|A*76#zr{1p6jeg+kIk7;0gB(Bl#XvY@5hf4*zn9V&afG5{akRX>= z{l#{$>Di?7lVzRT*u+qQ77k2m`z&ta>({R{?}ki6VuE)8c>kwI?=Zb&G&I=}SXF!H ztHAUK!;h?U8vkDbeh&o9qxKY;xO0h3=Ftm0Re-O7>svIjJ6FU*8_2?0Jx*<2ro`RrrMi{09IqMOE4<7)row&#iqnL%1 zfcFGHF*04!;{hSR)NT}BEpb!PCXw}X7hHY$O*6l z{nVpX%QY$_L~L}L#Dpl2MFgyVFE=DUUv{~E;!Xa-CWF~Q)o9>))xzykffWB8+7w&x zgwYUlarhLQi18=U;FiipURq9GC8}RZX4gGcGj4AcXfvEBMs5t*-ePV6I{*l54fA?c z=ax%%^$byp7WK!e=X$O=%6-O>;!MPtf|1o6hOxuExX-C(S>@KkNvK5AEiV*=4&!Yn z)NQ+`9ki|sRPh6`-`MF3xIsg882@)%@XzW$xR<9$)cL8B@;>V!T=aMrH`p5}(6veG zS5i3E@}-g*yLjGeZ}*db#%(2zQ=dGufYZO)Y#vSk#jeLNaBOl16&O+np1?U{esI$5 z&Y~h6({sDi1T`G{)Z=t@9gaY{6UUo$T@)}(yU4e@KJ^|K|D9pdnR);7d8iJCd`x-l z!42!wwrWC;q*fX7C_@q2VJIT$wJi{_8Pp0x6k~@?CoxlaSHTTw2vU5Pt~(!TrR$ci zTe|K>T=#HP;<~*D;&{l4Ws#U!EiayHpzc(1;(1OqZ*-A=yW6~2#IjI!H)`*pq8_y39s zridjD?;m*a3-#PRcI8Xksk^*r+E(Y(wrWO)((c;|6uZW|I}uC9jkg*%b}k+!dj0%b zVPqtPfinveW>4*cb;DEJ0+e?jV8XbA4zM#lj>}AJGK&q4Fn}zJ;vm2lu-C11z!~Fi zedcPB|4;w|r=EpP@a|!5n{!|j%jQGmeYl~+Y?Hq|_K|sqt#vP)Sw{d7 z3n1`?mztws-pMXyKEW>6b2MFOlW)kxNPh^d`Cy?VeZVGqaED$0FYobhKU{dO|JTHw z;>A=qrnVj~24RQ|?cRV(xymOax{T;?L^q7x5&ch_Sl+|Acggk)<(md}WlUe-nayd$ z7B3n3*(i?lcRz7$;DOuM!F4L5=iCcetSYB-XZB~t1$;eKrQH$y1s@lp<+cP>} z?En{#D3KTSrtoC6^0Di1qC~H;bsGErCZenYHzb~18``Y`lf8mCr9FF`tcIsgHQRKQ z%15F#&#DBL3=elAv0R#6RvuM4TQM`AT~`#N4nJv^-)*%CYtNcAy#ZtD7kYwhP^h*& z{PE$#2Pn(|$lXYEJM8Shqy@+|K|8# zA3j8?erNkWAIo(qxV^23ShMu(Q?Z)OrN{OJU2NGAZzeWDbn!DWJ&T(&_niSA7%7jk zD{FSmkNpyNUu^c9b&hWh2>1KX0%2m4*S48JD_i_ z>3tDzicv3`Oef*4gu4>%O1N7Dci%2_%(?9Xqs*76WQMh{;odg#YA~(=l@k;X4F<({ z=!{IgngEDbDL!VheVqU=xeJZ(_tjS3*3H#IAPJ?doI)ugZr98#U8u^O?0>z0t-IoC z3htw$dkQ?85s%^v9C#r$S62!sF!kUGe!=efd=c2ufjvW0_=Br}t7P)y@&WmoADg$Q z=T|}e*RRoE*I5E?x4QDZfOYTH?n5;9^jBu9CX<;j*!B2OHPsj?@C$m(KKS+g>WbNp z{VhJndD4r@oFmGkq+g@vMLnE)#0)9LguxSasleVADIy zW2mWF`cz#VjdVPrsE>OYcDZx)I@bmiWz72Q;Q}=DOBb2%? zmFO}64t0=a`Oz)#`@`?jxNZab|S;S*#V`DrRYU4qM zy7c20q;5Mtj{2kVSU37(Ei2R1$mZb zP+Gr@egx9`6!tMa*R@%<*DUtQJ$h~IQ!aj%dM@R;>6C$gURu}t-MO_1H1MN{K zv|xpntI%R?4*MMJ(3-|RP585Ruuns>YhdlCJ>nWz`Du%|JoeG#_Eu}y=f~aN5^HO` zdj8LvKDFVU=f?7XG}Tah>ev|c2QvR>pZuR!6S4RbmRn#yLjKRI89>$ipVu;g6gaXF zL#AyNVI!fI*|x!eSj36VIo#^0inwhwB@}Vn zuu3T6zN<|(frv|CscH0GqXHz=Q;ku7IM`YgOP)2jB37~}AQm-(F-I`&SCASfUb3Qrnp2b*b3~DX&XSezE5@smbqmy(TsJ4X)RtCIvKnirY!( zk;%+5nVA<>`?@+&CF@{J$Oa2`g5ir7E~kWg>H}tt(-4ejC^brSmzQBa+S+0-r;&c?!rZ z*;so;3I9u;AZrcz$P;9*e(XY?AUlLUVZ|!6R0S8RJV7Q;kTtGUVxJ&eE|<3oM3xnO zL?1cl)blZAHV)v)6gdG_pr3k_{?7dqWD9@uy?eMU_|*Nn%*68?j0i83d0nID_&fJc zklD=PO_I=^U<#F07s>Bs#Ji}Z&9EC35}G_fl%fUyo%#NLl`htwf7-Q^A0qOR7sahTOY?RTP z{Dn<+@RRG+quZqdDgHaODc2-ML##jx`xKjq@h6dZmj%xhh#$G8Am@{3Mnbo6U{c$U z#Rq@2**u&8id~Ok;Mn92DlnuDJb`n@{NSY9okc}DrssC2wu4R2CdWSYI9*-GV`0#p zINqe|qJUxAMZVqjsrR_}?+la9%=@3u!`^Vn$MghaUju(hTIqc8?(rq_D4JoYY!UYL z>(`lgL#81y!Mgyw|I?#)m|ij(n(PRqYQFPTV0wh%N7gxw|E~bQ2Lk3%dx}ilxs3Mz zFYr_WzLtB=srh~3<0J5H^Xe2i&e$P4~h@q=!PtB$k(r5p#p=@ zbrIK12o>lfirkn%A&va>;@J0s$Qi6&2k_*2EeF4s<9Y$pwz~<;Id&1(B>ae6-@$R4 zXP=VTh$)X!s;a=>VzW3IFBN!BJ#YGZq|~FDQ7Ue^MumikD(1Z+aUa{x45~&0b&Yx> zFYQ@*t(3W3XgM;o4aN)sb^s7q7fA`ace@!z^1j+IZh4^~bfSom3~1Xrb_{P_po%WW zyx6IaT&bWsjQ=|>_-FMW+)G>6Xr%&opVv|sJ)Xr4_67=cZIb%6jea&`7tdneT3j2A zisRZjV)LM8M2qSa#Ihss?)o-m=5ajWrFTWAsI?t&sietT;b}$j!2zkrHIxvTV`_Q1 z=N&~7wcv0t?TtsH$uXYl>ak%B@$p2*=J6N}wBgj4pgtNw1^$Wc*_^=>LsQ^q&qPkt z(P}0F?vWF6zk7dwF}StenGjy&2Q0*`jIKrjw$#u}jL$n^I#a zc)J?yet|6&C1TI?eH;3CTw>_dGjR}H;vk51x|YRfDi@o67}{3n>S{L>%{H{d>esE+ zv-52_iw!=m$Ris?#PVFgI|AMmJVc`gL0n$}GfXh$5>5&_3-B<p|zllYaBOx2T2|GUmMx*2;ma+bZ$@O_-V1Q%lY49$&p7Y(w8=MQVx&I=)_kzgkv?D(J-EZJ|Cjgpw;wJ%*Z*tcPVr)@8&g{k z7lSawhIVhjGzLmwRc*=WQZj-{#*mT`NiuSENvs3X=`2b!Q4QmafVFmd8 zRNbVnKM=7U2SxZMI2bT%F9(>l0>I3NC_%Fzwl6{R4-Nn%X#Nf)BSEvMlIib=K1IR1 z+WrdsH*wVeTz;IJOHp&B>I==|E-~aT`NZa7udllz*o_!7Hri- z{#&){qW<)5>jfgSx=B-8-M0nc^P`l>Q-YbR2!K7O%~i7o{yCinm~lyIh5|3`Z#e#Y z|K0sni&fYj_xGav@-o260Q=Sgtf7|$Sl7F+n~xk>fInQlu;xjV!YU9>a*X^O!?D!;R6~q1o!>k!S zu8LS!7**F47*#%vncT$k)BdP8P07xMzFc;y#J~~*OALH)m>%?t!}KLa&S~@s%DRb` zshV{|bc`O6a}i|)6C4E5?lONI#Yki_`yS^?7~8RZYwtPk0-9hJDguTsQsnOuSIUSdBi>t!c%zbgqPSZ>r+EJrsZHgE7Nri`PRf$hW-!bQ zJiWdoW1=87EJ95D0oIk|N{ie#lR!lRm1cm-xa8umOvv45cD|{+{{(##^Y@#hZ)kWC zWFlwk0vfCcsH8-rzei{yW1x(IZ!8AtYRR2=`(1{2_$_#CU4Qr7y?3AOJG^z5p8_T! z1M3U%NRslMy5){rfn^71;_$xZ4R=4t4R^X$a>LyvWxO+!4#4!KCP;dvhx?7>s;86$8)k;RiH8h19R@bu1vjmlGMlZPs z=W-r0%X_FDX_9J%p{CqSl3E8F$)@*W^Z1?Gvl*r!ND3Yt9ey}{F-lHOC#Rl%vaIOl zMG6 zqb#uw9H84}T73lGxyZlXEYqERx{c+wbD1L5=#I6Dl9ubOTx98Q#gmrMnd5YMxhiX# zmA=q%0=pJssOuv(j}|U>d?c@-v|~|?VN{kn8f(M_wy^0SdWcnI+bDDT@6$4m_Nks* zjwouqp*WBu`9-#!GAyVT6?*!3jF4&^YXhx+Y#5W?@dR1M@x)Sxlm2+3X{NDvwAi`l zB9}E@%tps0$!@=+;O zV;DKzd$nsuyNz8$1(a)ReDIyBkSa@Uk&-STtujq>Je%{$T~DOu!BN`T{=P*rsd;;+peyw?59 zD2it#JIhy@oviGNYw60gPM(&}OhI;LD7@|50Yfj@291x6M(M3JttVA;|IE27;v>t# z*2e|IXT-vf>kBAWZ=wz^?Qb}`c%txdK!49Kf~7{#R^DBfN%Fc0nSfU@0WW75&tKSH zCnF^NeQDKD^^vjfSEir6TOw!3EsjKMVi@^LBi`I;jr;`+^0NT)TUs(%RVJ%81~`q9 z9HPXQYl6+BR`En_?H8aQzh5+>LqZjs~x%mmhQh;{We`q9M8N9KuDPF05-=I14J<(ak6FrXh=wu e;wiH{>M7Mghs)*d^8W(>0RR6PcGz5TSOEZTdgbK+ literal 6051 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 From 538039fc8d19b173b1b775f2477ea51dfe94da67 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 5 Dec 2023 10:34:17 -0600 Subject: [PATCH 07/68] fix sender --- provider/lpmessage/sender.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/lpmessage/sender.go b/provider/lpmessage/sender.go index 8d6cd4027..cb43b7401 100644 --- a/provider/lpmessage/sender.go +++ b/provider/lpmessage/sender.go @@ -76,7 +76,7 @@ func (s *SendTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done b SignedData []byte `db:"signed_data"` } - err = s.db.QueryRow(ctx, `select from_key, nonce, to_addr, unsigned_data, unsigned_cid from message_sends where id = $1`, taskID).Scan(&dbMsg) + err = s.db.QueryRow(ctx, `select from_key, nonce, to_addr, unsigned_data, unsigned_cid from message_sends where send_task_id = $1`, taskID).Scan(&dbMsg) if err != nil { return false, xerrors.Errorf("getting message from db: %w", err) } From 2618b963e744babd4debbaae3486f7a68392e19c Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 5 Dec 2023 10:41:32 -0600 Subject: [PATCH 08/68] getdeps --- cmd/lotus-provider/deps/deps.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/lotus-provider/deps/deps.go b/cmd/lotus-provider/deps/deps.go index f82a1ecd6..54305f6a1 100644 --- a/cmd/lotus-provider/deps/deps.go +++ b/cmd/lotus-provider/deps/deps.go @@ -82,6 +82,11 @@ func StorageAuth(apiKey string) (sealer.StorageAuth, error) { return sealer.StorageAuth(headers), nil } +func GetDeps(ctx context.Context, cctx *cli.Context) (*Deps, error) { + var deps *Deps + return deps, deps.PopulateRemainingDeps(ctx, cctx, true) +} + type Deps struct { Cfg *config.LotusProviderConfig DB *harmonydb.DB From 943c223dad598a253636dcc1a2934ed315058366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 5 Dec 2023 17:51:42 +0100 Subject: [PATCH 09/68] fix: lotus-provider: Fix winning PoSt --- provider/lpwinning/winning_task.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/provider/lpwinning/winning_task.go b/provider/lpwinning/winning_task.go index f02ffa1ae..907b594fd 100644 --- a/provider/lpwinning/winning_task.go +++ b/provider/lpwinning/winning_task.go @@ -4,10 +4,8 @@ import ( "bytes" "context" "crypto/rand" - "database/sql" "encoding/binary" "encoding/json" - "errors" "time" "github.com/ipfs/go-cid" @@ -579,12 +577,13 @@ func (t *WinPostTask) mineBasic(ctx context.Context) { taskFn(func(id harmonytask.TaskID, tx *harmonydb.Tx) (shouldCommit bool, seriousError error) { // First we check if the mining base includes blocks we may have mined previously to avoid getting slashed // select mining_tasks where epoch==base_epoch if win=true to maybe get base block cid which has to be included in our tipset - var baseBlockCid string - err := tx.QueryRow(`SELECT mined_cid FROM mining_tasks WHERE epoch = $1 AND sp_id = $2 AND won = true`, baseEpoch, spID).Scan(&baseBlockCid) - if err != nil && !errors.Is(err, sql.ErrNoRows) { + var baseBlockCids []string + err := tx.Select(&baseBlockCids, `SELECT mined_cid FROM mining_tasks WHERE epoch = $1 AND sp_id = $2 AND won = true`, baseEpoch, spID) + if err != nil { return false, xerrors.Errorf("querying mining_tasks: %w", err) } - if baseBlockCid != "" { + if len(baseBlockCids) >= 1 { + baseBlockCid := baseBlockCids[0] c, err := cid.Parse(baseBlockCid) if err != nil { return false, xerrors.Errorf("parsing mined_cid: %w", err) From 0490359ac6b3ab7692b50ef71f5f9cbce497c177 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 5 Dec 2023 13:36:47 -0600 Subject: [PATCH 10/68] in progress --- itests/kit/ensemble_presets.go | 15 +++++++++++++++ itests/kit/node_full.go | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/itests/kit/ensemble_presets.go b/itests/kit/ensemble_presets.go index 3ec39cf90..88f07b684 100644 --- a/itests/kit/ensemble_presets.go +++ b/itests/kit/ensemble_presets.go @@ -101,6 +101,21 @@ func EnsembleOneTwo(t *testing.T, opts ...interface{}) (*TestFullNode, *TestMine return &full, &one, &two, ens } +// EnsembleProvider creates and starts an Ensemble with a single full node and a single provider. +// It does not interconnect nodes nor does it begin mining. +func EnsembleProvider(t *testing.T, opts ...interface{}) (*TestFullNode, *TestProviderNode, *Ensemble) { + opts = append(opts, WithAllSubsystems()) + + eopts, nopts := siftOptions(t, opts) + + var ( + full TestFullNode + provider TestProviderNode + ) + ens := NewEnsemble(t, eopts...).FullNode(&full, nopts...).Provider(&provider, &full, nopts...).Start() + return &full, &provider, ens +} + func siftOptions(t *testing.T, opts []interface{}) (eopts []EnsembleOpt, nopts []NodeOpt) { for _, v := range opts { switch o := v.(type) { diff --git a/itests/kit/node_full.go b/itests/kit/node_full.go index 3e80ed688..697c59aed 100644 --- a/itests/kit/node_full.go +++ b/itests/kit/node_full.go @@ -22,6 +22,7 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet/key" cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" "github.com/filecoin-project/lotus/gateway" "github.com/filecoin-project/lotus/node" ) @@ -54,6 +55,17 @@ type TestFullNode struct { options nodeOpts } +// TestProviderNode represents a Provider node enrolled in an Ensemble. +type TestProviderNode struct { + v1api.LotusProviderStruct + + t *testing.T + + *deps.Deps + + options nodeOpts +} + func MergeFullNodes(fullNodes []*TestFullNode) *TestFullNode { var wrappedFullNode TestFullNode var fns api.FullNodeStruct From 685934a644a0f6ad16d7ed959bf2c285a1718a32 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 5 Dec 2023 13:45:08 -0600 Subject: [PATCH 11/68] fix: sql Scan cannot write to an object --- provider/lpmessage/sender.go | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/provider/lpmessage/sender.go b/provider/lpmessage/sender.go index cb43b7401..bee22ff69 100644 --- a/provider/lpmessage/sender.go +++ b/provider/lpmessage/sender.go @@ -76,7 +76,11 @@ func (s *SendTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done b SignedData []byte `db:"signed_data"` } - err = s.db.QueryRow(ctx, `select from_key, nonce, to_addr, unsigned_data, unsigned_cid from message_sends where send_task_id = $1`, taskID).Scan(&dbMsg) + err = s.db.QueryRow(ctx, ` + SELECT from_key, nonce, to_addr, unsigned_data, unsigned_cid + FROM message_sends + WHERE send_task_id = $1`, taskID).Scan( + &dbMsg.FromKey, &dbMsg.Nonce, &dbMsg.ToAddr, &dbMsg.UnsignedData, &dbMsg.UnsignedCid) if err != nil { return false, xerrors.Errorf("getting message from db: %w", err) } @@ -96,8 +100,11 @@ func (s *SendTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done b } // try to acquire lock - cn, err := s.db.Exec(ctx, `INSERT INTO message_send_locks (from_key, task_id, claimed_at) VALUES ($1, $2, CURRENT_TIMESTAMP) - ON CONFLICT (from_key) DO UPDATE SET task_id = EXCLUDED.task_id, claimed_at = CURRENT_TIMESTAMP WHERE message_send_locks.task_id = $2;`, dbMsg.FromKey, taskID) + cn, err := s.db.Exec(ctx, ` + INSERT INTO message_send_locks (from_key, task_id, claimed_at) + VALUES ($1, $2, CURRENT_TIMESTAMP) ON CONFLICT (from_key) DO UPDATE + SET task_id = EXCLUDED.task_id, claimed_at = CURRENT_TIMESTAMP + WHERE message_send_locks.task_id = $2;`, dbMsg.FromKey, taskID) if err != nil { return false, xerrors.Errorf("acquiring send lock: %w", err) } @@ -114,7 +121,8 @@ func (s *SendTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done b // defer release db send lock defer func() { - _, err2 := s.db.Exec(ctx, `delete from message_send_locks where from_key = $1 and task_id = $2`, dbMsg.FromKey, taskID) + _, err2 := s.db.Exec(ctx, ` + DELETE from message_send_locks WHERE from_key = $1 AND task_id = $2`, dbMsg.FromKey, taskID) if err2 != nil { log.Errorw("releasing send lock", "task_id", taskID, "from", dbMsg.FromKey, "error", err2) @@ -135,7 +143,8 @@ func (s *SendTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done b // get nonce from db var dbNonce *uint64 - r := s.db.QueryRow(ctx, `select max(nonce) from message_sends where from_key = $1 and send_success = true`, msg.From.String()) + r := s.db.QueryRow(ctx, ` + SELECT MAX(nonce) FROM message_sends WHERE from_key = $1 AND send_success = true`, msg.From.String()) if err := r.Scan(&dbNonce); err != nil { return false, xerrors.Errorf("getting nonce from db: %w", err) } @@ -164,7 +173,9 @@ func (s *SendTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done b // write to db - n, err := s.db.Exec(ctx, `update message_sends set nonce = $1, signed_data = $2, signed_json = $3, signed_cid = $4 where send_task_id = $5`, + n, err := s.db.Exec(ctx, ` + UPDATE message_sends SET nonce = $1, signed_data = $2, signed_json = $3, signed_cid = $4 + WHERE send_task_id = $5`, msg.Nonce, data, string(jsonBytes), sigMsg.Cid().String(), taskID) if err != nil { return false, xerrors.Errorf("updating db record: %w", err) @@ -198,7 +209,9 @@ func (s *SendTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done b sendError = err.Error() } - _, err = s.db.Exec(ctx, `update message_sends set send_success = $1, send_error = $2, send_time = CURRENT_TIMESTAMP where send_task_id = $3`, sendSuccess, sendError, taskID) + _, err = s.db.Exec(ctx, ` + UPDATE message_sends SET send_success = $1, send_error = $2, send_time = CURRENT_TIMESTAMP + WHERE send_task_id = $3`, sendSuccess, sendError, taskID) if err != nil { return false, xerrors.Errorf("updating db record: %w", err) } From 91b0032ee4f0b79c7f4e51ed568239b5f15b14a8 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 5 Dec 2023 13:58:15 -0600 Subject: [PATCH 12/68] do not suggest the default layer --- cmd/lotus-provider/migrate.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/lotus-provider/migrate.go b/cmd/lotus-provider/migrate.go index 819499402..3869c7dfb 100644 --- a/cmd/lotus-provider/migrate.go +++ b/cmd/lotus-provider/migrate.go @@ -231,12 +231,17 @@ func fromMiner(cctx *cli.Context) (err error) { dbSettings += ` --db-name="` + smCfg.HarmonyDB.Database + `"` } + var layerMaybe string + if name != "base" { + layerMaybe = "--layer=" + name + } + msg += ` To work with the config: ` + cliCommandColor(`lotus-provider `+dbSettings+` config help `) msg += ` To run Lotus Provider: in its own machine or cgroup without other files, use the command: -` + cliCommandColor(`lotus-provider `+dbSettings+` run --layers="`+name+`"`) +` + cliCommandColor(`lotus-provider `+dbSettings+` run `+layerMaybe) fmt.Println(msg) return nil } From e570693b3ef93c78c031e539d86bcf33ad0b982e Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 5 Dec 2023 17:38:07 -0600 Subject: [PATCH 13/68] lp docsgen --- Makefile | 4 +++- api/docgen/docgen.go | 4 ++++ documentation/en/api-v0-methods-provider.md | 25 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 documentation/en/api-v0-methods-provider.md diff --git a/Makefile b/Makefile index 68d97227b..c3c46f71e 100644 --- a/Makefile +++ b/Makefile @@ -356,7 +356,7 @@ docsgen-md-bin: api-gen actors-gen docsgen-openrpc-bin: api-gen actors-gen $(GOCC) build $(GOFLAGS) -o docgen-openrpc ./api/docgen-openrpc/cmd -docsgen-md: docsgen-md-full docsgen-md-storage docsgen-md-worker +docsgen-md: docsgen-md-full docsgen-md-storage docsgen-md-worker docsgen-md-provider docsgen-md-full: docsgen-md-bin ./docgen-md "api/api_full.go" "FullNode" "api" "./api" > documentation/en/api-v1-unstable-methods.md @@ -365,6 +365,8 @@ docsgen-md-storage: docsgen-md-bin ./docgen-md "api/api_storage.go" "StorageMiner" "api" "./api" > documentation/en/api-v0-methods-miner.md docsgen-md-worker: docsgen-md-bin ./docgen-md "api/api_worker.go" "Worker" "api" "./api" > documentation/en/api-v0-methods-worker.md +docsgen-md-provider: docsgen-md-bin + ./docgen-md "api/api_lp.go" "Provider" "api" "./api" > documentation/en/api-v0-methods-provider.md docsgen-openrpc: docsgen-openrpc-full docsgen-openrpc-storage docsgen-openrpc-worker docsgen-openrpc-gateway diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 018629600..5a05c8d0e 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -432,6 +432,10 @@ func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []r i = &api.GatewayStruct{} t = reflect.TypeOf(new(struct{ api.Gateway })).Elem() permStruct = append(permStruct, reflect.TypeOf(api.GatewayStruct{}.Internal)) + case "Provider": + i = &api.LotusProviderStruct{} + t = reflect.TypeOf(new(struct{ api.LotusProvider })).Elem() + permStruct = append(permStruct, reflect.TypeOf(api.LotusProviderStruct{}.Internal)) default: panic("unknown type") } diff --git a/documentation/en/api-v0-methods-provider.md b/documentation/en/api-v0-methods-provider.md new file mode 100644 index 000000000..fc4a2daf7 --- /dev/null +++ b/documentation/en/api-v0-methods-provider.md @@ -0,0 +1,25 @@ +# Groups +* [](#) + * [Shutdown](#Shutdown) + * [Version](#Version) +## + + +### Shutdown + + +Perms: admin + +Inputs: `null` + +Response: `{}` + +### Version + + +Perms: admin + +Inputs: `null` + +Response: `131840` + From 3d30dedc39867adc3bfa01e7c95ff07d38c29e8b Mon Sep 17 00:00:00 2001 From: Phi Date: Wed, 6 Dec 2023 12:52:26 +0100 Subject: [PATCH 14/68] Actually show miner-addrs in info-log Actually show miner-addrs in lotus-provider info-log --- cmd/lotus-provider/run.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cmd/lotus-provider/run.go b/cmd/lotus-provider/run.go index bf19ee537..de97aa766 100644 --- a/cmd/lotus-provider/run.go +++ b/cmd/lotus-provider/run.go @@ -176,7 +176,7 @@ var runCmd = &cli.Command{ } } log.Infow("This lotus_provider instance handles", - "miner_addresses", maddrs, + "miner_addresses", minerAddressesToStrings(maddrs), "tasks", lo.Map(activeTasks, func(t harmonytask.TaskInterface, _ int) string { return t.TypeDetails().Name })) taskEngine, err := harmonytask.New(db, activeTasks, deps.listenAddr) @@ -457,3 +457,11 @@ func (p *ProviderAPI) Shutdown(context.Context) error { close(p.ShutdownChan) return nil } + +func minerAddressesToStrings(maddrs []dtypes.MinerAddress) []string { + strs := make([]string, len(maddrs)) + for i, addr := range maddrs { + strs[i] = address.Address(addr).String() + } + return strs +} From 4b1445e3b2ad863a5f10342a7c55c611ee258c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 6 Dec 2023 20:53:50 +0100 Subject: [PATCH 15/68] fix: lotus-provider: Wait for the correct taskID --- provider/lpmessage/sender.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/provider/lpmessage/sender.go b/provider/lpmessage/sender.go index bee22ff69..5d03cfd02 100644 --- a/provider/lpmessage/sender.go +++ b/provider/lpmessage/sender.go @@ -324,6 +324,7 @@ func (s *Sender) Send(ctx context.Context, msg *types.Message, mss *api.MessageS return cid.Undef, xerrors.Errorf("marshaling message: %w", err) } + var sendTaskID *harmonytask.TaskID taskAdder(func(id harmonytask.TaskID, tx *harmonydb.Tx) (shouldCommit bool, seriousError error) { _, err := tx.Exec(`insert into message_sends (from_key, to_addr, send_reason, unsigned_data, unsigned_cid, send_task_id) values ($1, $2, $3, $4, $5, $6)`, msg.From.String(), msg.To.String(), reason, unsBytes.Bytes(), msg.Cid().String(), id) @@ -331,9 +332,15 @@ func (s *Sender) Send(ctx context.Context, msg *types.Message, mss *api.MessageS return false, xerrors.Errorf("inserting message into db: %w", err) } + sendTaskID = &id + return true, nil }) + if sendTaskID == nil { + return cid.Undef, xerrors.Errorf("failed to add task") + } + // wait for exec var ( pollInterval = 50 * time.Millisecond @@ -350,7 +357,7 @@ func (s *Sender) Send(ctx context.Context, msg *types.Message, mss *api.MessageS var sigCidStr, sendError string var sendSuccess *bool - err = s.db.QueryRow(ctx, `select signed_cid, send_success, send_error from message_sends where send_task_id = $1`, taskAdder).Scan(&sigCidStr, &sendSuccess, &sendError) + err = s.db.QueryRow(ctx, `select signed_cid, send_success, send_error from message_sends where send_task_id = $1`, &sendTaskID).Scan(&sigCidStr, &sendSuccess, &sendError) if err != nil { return cid.Undef, xerrors.Errorf("getting cid for task: %w", err) } From 93fd40826740b7caa122144f6d0e535345c8e2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 6 Dec 2023 22:54:46 +0100 Subject: [PATCH 16/68] lotus-provider: additional fixes to make recover work --- lib/harmony/harmonytask/harmonytask.go | 5 +++++ provider/lpmessage/sender.go | 7 ++++++- provider/lpwindow/recover_task.go | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/harmony/harmonytask/harmonytask.go b/lib/harmony/harmonytask/harmonytask.go index 595e5b63a..31b632975 100644 --- a/lib/harmony/harmonytask/harmonytask.go +++ b/lib/harmony/harmonytask/harmonytask.go @@ -146,6 +146,11 @@ func New( TaskTypeDetails: c.TypeDetails(), TaskEngine: e, } + + if len(h.Name) > 16 { + return nil, fmt.Errorf("task name too long: %s, max 16 characters", h.Name) + } + e.handlers = append(e.handlers, &h) e.taskMap[h.TaskTypeDetails.Name] = &h } diff --git a/provider/lpmessage/sender.go b/provider/lpmessage/sender.go index 5d03cfd02..5467e5d2f 100644 --- a/provider/lpmessage/sender.go +++ b/provider/lpmessage/sender.go @@ -354,7 +354,7 @@ func (s *Sender) Send(ctx context.Context, msg *types.Message, mss *api.MessageS for { var err error - var sigCidStr, sendError string + var sigCidStr, sendError *string var sendSuccess *bool err = s.db.QueryRow(ctx, `select signed_cid, send_success, send_error from message_sends where send_task_id = $1`, &sendTaskID).Scan(&sigCidStr, &sendSuccess, &sendError) @@ -373,6 +373,11 @@ func (s *Sender) Send(ctx context.Context, msg *types.Message, mss *api.MessageS continue } + if sigCidStr == nil || sendError == nil { + // should never happen because sendSuccess is already not null here + return cid.Undef, xerrors.Errorf("got null values for sigCidStr or sendError, this should never happen") + } + if !*sendSuccess { sendErr = xerrors.Errorf("send error: %s", sendError) } else { diff --git a/provider/lpwindow/recover_task.go b/provider/lpwindow/recover_task.go index 6006f3c35..12f8522b5 100644 --- a/provider/lpwindow/recover_task.go +++ b/provider/lpwindow/recover_task.go @@ -217,7 +217,7 @@ func (w *WdPostRecoverDeclareTask) CanAccept(ids []harmonytask.TaskID, engine *h func (w *WdPostRecoverDeclareTask) TypeDetails() harmonytask.TaskTypeDetails { return harmonytask.TaskTypeDetails{ Max: 128, - Name: "WdPostRecoverDeclare", + Name: "WdPostRecover", Cost: resources.Resources{ Cpu: 1, Gpu: 0, From bf5132e50bedd405948c85d51365d29c0956c9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 6 Dec 2023 23:00:53 +0100 Subject: [PATCH 17/68] more sender fixes --- provider/lpmessage/sender.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/provider/lpmessage/sender.go b/provider/lpmessage/sender.go index 5467e5d2f..0db0c0b51 100644 --- a/provider/lpmessage/sender.go +++ b/provider/lpmessage/sender.go @@ -379,9 +379,9 @@ func (s *Sender) Send(ctx context.Context, msg *types.Message, mss *api.MessageS } if !*sendSuccess { - sendErr = xerrors.Errorf("send error: %s", sendError) + sendErr = xerrors.Errorf("send error: %s", *sendError) } else { - sigCid, err = cid.Parse(sigCidStr) + sigCid, err = cid.Parse(*sigCidStr) if err != nil { return cid.Undef, xerrors.Errorf("parsing signed cid: %w", err) } From efb4a09cf8330acd64b38714c6800bd85ca21a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 7 Dec 2023 12:17:53 +0100 Subject: [PATCH 18/68] harmony: Fix task reclaim on restart --- lib/harmony/harmonytask/harmonytask.go | 4 +-- lib/harmony/harmonytask/task_type_handler.go | 38 ++++++++++++-------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/harmony/harmonytask/harmonytask.go b/lib/harmony/harmonytask/harmonytask.go index 31b632975..7577c5cf5 100644 --- a/lib/harmony/harmonytask/harmonytask.go +++ b/lib/harmony/harmonytask/harmonytask.go @@ -176,7 +176,7 @@ func New( continue // not really fatal, but not great } } - if !h.considerWork("recovered", []TaskID{TaskID(w.ID)}) { + if !h.considerWork(workSourceRecover, []TaskID{TaskID(w.ID)}) { log.Error("Strange: Unable to accept previously owned task: ", w.ID, w.Name) } } @@ -285,7 +285,7 @@ func (e *TaskEngine) pollerTryAllWork() { continue } if len(unownedTasks) > 0 { - accepted := v.considerWork("poller", unownedTasks) + accepted := v.considerWork(workSourcePoller, unownedTasks) if accepted { return // accept new work slowly and in priority order } diff --git a/lib/harmony/harmonytask/task_type_handler.go b/lib/harmony/harmonytask/task_type_handler.go index 79a156fef..34f7a5c3e 100644 --- a/lib/harmony/harmonytask/task_type_handler.go +++ b/lib/harmony/harmonytask/task_type_handler.go @@ -49,6 +49,11 @@ func (h *taskTypeHandler) AddTask(extra func(TaskID, *harmonydb.Tx) (bool, error } } +const ( + workSourcePoller = "poller" + workSourceRecover = "recovered" +) + // considerWork is called to attempt to start work on a task-id of this task type. // It presumes single-threaded calling, so there should not be a multi-threaded re-entry. // The only caller should be the one work poller thread. This does spin off other threads, @@ -87,22 +92,25 @@ top: return false } - // 4. Can we claim the work for our hostname? - ct, err := h.TaskEngine.db.Exec(h.TaskEngine.ctx, "UPDATE harmony_task SET owner_id=$1 WHERE id=$2 AND owner_id IS NULL", h.TaskEngine.ownerID, *tID) - if err != nil { - log.Error(err) - return false - } - if ct == 0 { - log.Infow("did not accept task", "task_id", strconv.Itoa(int(*tID)), "reason", "already Taken", "name", h.Name) - var tryAgain = make([]TaskID, 0, len(ids)-1) - for _, id := range ids { - if id != *tID { - tryAgain = append(tryAgain, id) - } + // if recovering we don't need to try to claim anything because those tasks are already claimed by us + if from != workSourceRecover { + // 4. Can we claim the work for our hostname? + ct, err := h.TaskEngine.db.Exec(h.TaskEngine.ctx, "UPDATE harmony_task SET owner_id=$1 WHERE id=$2 AND owner_id IS NULL", h.TaskEngine.ownerID, *tID) + if err != nil { + log.Error(err) + return false + } + if ct == 0 { + log.Infow("did not accept task", "task_id", strconv.Itoa(int(*tID)), "reason", "already Taken", "name", h.Name) + var tryAgain = make([]TaskID, 0, len(ids)-1) + for _, id := range ids { + if id != *tID { + tryAgain = append(tryAgain, id) + } + } + ids = tryAgain + goto top } - ids = tryAgain - goto top } h.Count.Add(1) From 0e49673c4991a0a2ad74d2f8d19a4b154002625f Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Thu, 7 Dec 2023 15:32:35 -0600 Subject: [PATCH 19/68] fix: db serialize txn - retry --- cmd/lotus-provider/proving.go | 4 ++ lib/harmony/harmonydb/userfuncs.go | 45 +++++++++++++++++++- lib/harmony/harmonytask/task_type_handler.go | 9 +++- storage/paths/db_index.go | 35 +++++++++------ 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/cmd/lotus-provider/proving.go b/cmd/lotus-provider/proving.go index 577b5b5f9..621896c91 100644 --- a/cmd/lotus-provider/proving.go +++ b/cmd/lotus-provider/proving.go @@ -82,6 +82,7 @@ var wdPostTaskCmd = &cli.Command{ return xerrors.Errorf("cannot get miner id %w", err) } var id int64 + retryAddTask: _, err = deps.db.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { err = tx.QueryRow(`INSERT INTO harmony_task (name, posted_time, added_by) VALUES ('WdPost', CURRENT_TIMESTAMP, 123) RETURNING id`).Scan(&id) if err != nil { @@ -102,6 +103,9 @@ var wdPostTaskCmd = &cli.Command{ return true, nil }) if err != nil { + if harmonydb.IsErrSerialization(err) { + goto retryAddTask + } return xerrors.Errorf("writing SQL transaction: %w", err) } fmt.Printf("Inserted task %v. Waiting for success ", id) diff --git a/lib/harmony/harmonydb/userfuncs.go b/lib/harmony/harmonydb/userfuncs.go index 788ca4a34..add50c269 100644 --- a/lib/harmony/harmonydb/userfuncs.go +++ b/lib/harmony/harmonydb/userfuncs.go @@ -3,6 +3,7 @@ package harmonydb import ( "context" "errors" + "runtime" "github.com/georgysavva/scany/v2/pgxscan" "github.com/jackc/pgerrcode" @@ -10,6 +11,8 @@ import ( "github.com/jackc/pgx/v5/pgconn" ) +var inTxErr = errors.New("Cannot use a non-transaction func in a transaction") + // rawStringOnly is _intentionally_private_ to force only basic strings in SQL queries. // In any package, raw strings will satisfy compilation. Ex: // @@ -22,6 +25,9 @@ type rawStringOnly string // Note, for CREATE & DROP please keep these permanent and express // them in the ./sql/ files (next number). func (db *DB) Exec(ctx context.Context, sql rawStringOnly, arguments ...any) (count int, err error) { + if usedInTransaction() { + return 0, inTxErr + } res, err := db.pgx.Exec(ctx, string(sql), arguments...) return int(res.RowsAffected()), err } @@ -55,6 +61,9 @@ type Query struct { // fmt.Println(id, name) // } func (db *DB) Query(ctx context.Context, sql rawStringOnly, arguments ...any) (*Query, error) { + if usedInTransaction() { + return &Query{}, inTxErr + } q, err := db.pgx.Query(ctx, string(sql), arguments...) return &Query{q}, err } @@ -66,6 +75,9 @@ type Row interface { Scan(...any) error } +type rowErr struct{} +func (rowErr) Scan(..any) error { return inTxErr } + // QueryRow gets 1 row using column order matching. // This is a timesaver for the special case of wanting the first row returned only. // EX: @@ -74,7 +86,10 @@ type Row interface { // var ID = 123 // err := db.QueryRow(ctx, "SELECT name, pet FROM users WHERE ID=?", ID).Scan(&name, &pet) func (db *DB) QueryRow(ctx context.Context, sql rawStringOnly, arguments ...any) Row { - return db.pgx.QueryRow(ctx, string(sql), arguments...) + if usedInTransaction() { + return rowErr{} + } + return db.pgx.QueryRow(ctx, string(sql), arguments...) } /* @@ -92,6 +107,9 @@ Ex: err := db.Select(ctx, &users, "SELECT name, id, tel_no FROM customers WHERE pet=?", pet) */ func (db *DB) Select(ctx context.Context, sliceOfStructPtr any, sql rawStringOnly, arguments ...any) error { + if usedInTransaction() { + return inTxErr + } return pgxscan.Select(ctx, db.pgx, sliceOfStructPtr, string(sql), arguments...) } @@ -100,10 +118,30 @@ type Tx struct { ctx context.Context } +// usedInTransaction is a helper to prevent nesting transactions +// & non-transaction calls in transactions. In the case of a stack read error, +// it will return false, so only use true for a course of action. +func usedInTransaction() bool { + ok := true + fn := "" + for v:=2; ok; v++ { + _,_,fn,ok = runtime.Caller(v) + if strings.Contains(fn, "BeginTransaction") { + return true + } + } + return false +} + // BeginTransaction is how you can access transactions using this library. // The entire transaction happens in the function passed in. // The return must be true or a rollback will occur. +// Be sure to test the error for IsErrSerialization() if you want to retry +// when there is a DB serialization error. func (db *DB) BeginTransaction(ctx context.Context, f func(*Tx) (commit bool, err error)) (didCommit bool, retErr error) { + if usedInTransaction() { + return 0, inTxErr + } tx, err := db.pgx.BeginTx(ctx, pgx.TxOptions{}) if err != nil { return false, err @@ -156,3 +194,8 @@ func IsErrUniqueContraint(err error) bool { var e2 *pgconn.PgError return errors.As(err, &e2) && e2.Code == pgerrcode.UniqueViolation } + +func IsErrSerialization(err error) bool { + var e2 *pgconn.PgError + return errors.As(err, &e2) && e2.Code == pgerrcode.SerializationFailure +} diff --git a/lib/harmony/harmonytask/task_type_handler.go b/lib/harmony/harmonytask/task_type_handler.go index 34f7a5c3e..6091cb61e 100644 --- a/lib/harmony/harmonytask/task_type_handler.go +++ b/lib/harmony/harmonytask/task_type_handler.go @@ -25,6 +25,7 @@ type taskTypeHandler struct { func (h *taskTypeHandler) AddTask(extra func(TaskID, *harmonydb.Tx) (bool, error)) { var tID TaskID +retryAddTask: _, err := h.TaskEngine.db.BeginTransaction(h.TaskEngine.ctx, func(tx *harmonydb.Tx) (bool, error) { // create taskID (from DB) _, err := tx.Exec(`INSERT INTO harmony_task (name, added_by, posted_time) @@ -44,6 +45,9 @@ func (h *taskTypeHandler) AddTask(extra func(TaskID, *harmonydb.Tx) (bool, error log.Debugf("addtask(%s) saw unique constraint, so it's added already.", h.Name) return } + if harmonydb.IsErrSerialization(err) { + goto retryAddTask + } log.Error("Could not add task. AddTasFunc failed: %v", err) return } @@ -161,7 +165,7 @@ top: func (h *taskTypeHandler) recordCompletion(tID TaskID, workStart time.Time, done bool, doErr error) { workEnd := time.Now() - +retryRecordCompletion: cm, err := h.TaskEngine.db.BeginTransaction(h.TaskEngine.ctx, func(tx *harmonydb.Tx) (bool, error) { var postedTime time.Time err := tx.QueryRow(`SELECT posted_time FROM harmony_task WHERE id=$1`, tID).Scan(&postedTime) @@ -214,6 +218,9 @@ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, tID, h.Name, postedTime, workStart, wo return true, nil }) if err != nil { + if harmonydb.IsErrSerialization(err) { + goto retryRecordCompletion + } log.Error("Could not record transaction: ", err) return } diff --git a/storage/paths/db_index.go b/storage/paths/db_index.go index 1e4abfab1..69a03198d 100644 --- a/storage/paths/db_index.go +++ b/storage/paths/db_index.go @@ -180,12 +180,12 @@ func (dbi *DBIndex) StorageAttach(ctx context.Context, si storiface.StorageInfo, } } +retryAttachStorage: // Single transaction to attach storage which is not present in the DB _, err := dbi.harmonyDB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { - var urls sql.NullString var storageId sql.NullString - err = dbi.harmonyDB.QueryRow(ctx, + err = tx.QueryRow( "Select storage_id, urls FROM storage_path WHERE storage_id = $1", string(si.ID)).Scan(&storageId, &urls) if err != nil && !strings.Contains(err.Error(), "no rows in result set") { return false, xerrors.Errorf("storage attach select fails: %v", err) @@ -200,7 +200,7 @@ func (dbi *DBIndex) StorageAttach(ctx context.Context, si storiface.StorageInfo, } currUrls = union(currUrls, si.URLs) - _, err = dbi.harmonyDB.Exec(ctx, + _, err = tx.Exec( "UPDATE storage_path set urls=$1, weight=$2, max_storage=$3, can_seal=$4, can_store=$5, groups=$6, allow_to=$7, allow_types=$8, deny_types=$9 WHERE storage_id=$10", strings.Join(currUrls, ","), si.Weight, @@ -220,7 +220,7 @@ func (dbi *DBIndex) StorageAttach(ctx context.Context, si storiface.StorageInfo, } // Insert storage id - _, err = dbi.harmonyDB.Exec(ctx, + _, err = tx.Exec( "INSERT INTO storage_path "+ "Values($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)", si.ID, @@ -245,6 +245,9 @@ func (dbi *DBIndex) StorageAttach(ctx context.Context, si storiface.StorageInfo, return true, nil }) if err != nil { + if harmonydb.IsErrSerialization(err) { + goto retryAttachStorage + } return err } @@ -284,22 +287,26 @@ func (dbi *DBIndex) StorageDetach(ctx context.Context, id storiface.ID, url stri log.Warnw("Dropping sector path endpoint", "path", id, "url", url) } else { + retryDropPath: // Single transaction to drop storage path and sector decls which have this as a storage path _, err := dbi.harmonyDB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { // Drop storage path completely - _, err = dbi.harmonyDB.Exec(ctx, "DELETE FROM storage_path WHERE storage_id=$1", id) + _, err = tx.Exec("DELETE FROM storage_path WHERE storage_id=$1", id) if err != nil { return false, err } // Drop all sectors entries which use this storage path - _, err = dbi.harmonyDB.Exec(ctx, "DELETE FROM sector_location WHERE storage_id=$1", id) + _, err = tx.Exec("DELETE FROM sector_location WHERE storage_id=$1", id) if err != nil { return false, err } return true, nil }) if err != nil { + if harmonydb.IsErrSerialization(err) { + goto retryDropPath + } return err } log.Warnw("Dropping sector storage", "path", id) @@ -373,9 +380,10 @@ func (dbi *DBIndex) StorageDeclareSector(ctx context.Context, storageID storifac return xerrors.Errorf("invalid filetype") } +retryStorageDeclareSector: _, err := dbi.harmonyDB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { var currPrimary sql.NullBool - err = dbi.harmonyDB.QueryRow(ctx, + err = tx.QueryRow( "SELECT is_primary FROM sector_location WHERE miner_id=$1 and sector_num=$2 and sector_filetype=$3 and storage_id=$4", uint64(s.Miner), uint64(s.Number), int(ft), string(storageID)).Scan(&currPrimary) if err != nil && !strings.Contains(err.Error(), "no rows in result set") { @@ -385,7 +393,7 @@ func (dbi *DBIndex) StorageDeclareSector(ctx context.Context, storageID storifac // If storage id already exists for this sector, update primary if need be if currPrimary.Valid { if !currPrimary.Bool && primary { - _, err = dbi.harmonyDB.Exec(ctx, + _, err = tx.Exec( "UPDATE sector_location set is_primary = TRUE WHERE miner_id=$1 and sector_num=$2 and sector_filetype=$3 and storage_id=$4", s.Miner, s.Number, ft, storageID) if err != nil { @@ -395,7 +403,7 @@ func (dbi *DBIndex) StorageDeclareSector(ctx context.Context, storageID storifac log.Warnf("sector %v redeclared in %s", s, storageID) } } else { - _, err = dbi.harmonyDB.Exec(ctx, + _, err = tx.Exec( "INSERT INTO sector_location "+ "values($1, $2, $3, $4, $5)", s.Miner, s.Number, ft, storageID, primary) @@ -407,6 +415,9 @@ func (dbi *DBIndex) StorageDeclareSector(ctx context.Context, storageID storifac return true, nil }) if err != nil { + if harmonydb.IsErrSerialization(err) { + goto retryStorageDeclareSector + } return err } @@ -750,7 +761,7 @@ func (dbi *DBIndex) lock(ctx context.Context, sector abi.SectorID, read storifac _, err := dbi.harmonyDB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { fts := (read | write).AllSet() - err = dbi.harmonyDB.Select(ctx, &rows, + err = tx.Select(&rows, `SELECT sector_filetype, read_ts, read_refs, write_ts FROM sector_location WHERE miner_id=$1 @@ -792,7 +803,7 @@ func (dbi *DBIndex) lock(ctx context.Context, sector abi.SectorID, read storifac } // Acquire write locks - _, err = dbi.harmonyDB.Exec(ctx, + _, err = tx.Exec( `UPDATE sector_location SET write_ts = NOW(), write_lock_owner = $1 WHERE miner_id=$2 @@ -807,7 +818,7 @@ func (dbi *DBIndex) lock(ctx context.Context, sector abi.SectorID, read storifac } // Acquire read locks - _, err = dbi.harmonyDB.Exec(ctx, + _, err = tx.Exec( `UPDATE sector_location SET read_ts = NOW(), read_refs = read_refs + 1 WHERE miner_id=$1 From 1e09e1e9661bd67d46f62b050fd1afd622d97223 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Thu, 7 Dec 2023 16:01:28 -0600 Subject: [PATCH 20/68] detect unsafe code uses --- lib/harmony/harmonydb/harmonydb.go | 3 ++ lib/harmony/harmonydb/userfuncs.go | 48 ++++++++++++++++-------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/lib/harmony/harmonydb/harmonydb.go b/lib/harmony/harmonydb/harmonydb.go index 0fed176d2..caa5d1daa 100644 --- a/lib/harmony/harmonydb/harmonydb.go +++ b/lib/harmony/harmonydb/harmonydb.go @@ -10,6 +10,7 @@ import ( "sort" "strconv" "strings" + "sync" "time" logging "github.com/ipfs/go-log/v2" @@ -33,6 +34,8 @@ type DB struct { cfg *pgxpool.Config schema string hostnames []string + BTFPOnce sync.Once + BTFP uintptr } var logger = logging.Logger("harmonydb") diff --git a/lib/harmony/harmonydb/userfuncs.go b/lib/harmony/harmonydb/userfuncs.go index add50c269..8abce73d0 100644 --- a/lib/harmony/harmonydb/userfuncs.go +++ b/lib/harmony/harmonydb/userfuncs.go @@ -9,6 +9,7 @@ import ( "github.com/jackc/pgerrcode" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" + "github.com/samber/lo" ) var inTxErr = errors.New("Cannot use a non-transaction func in a transaction") @@ -25,7 +26,7 @@ type rawStringOnly string // Note, for CREATE & DROP please keep these permanent and express // them in the ./sql/ files (next number). func (db *DB) Exec(ctx context.Context, sql rawStringOnly, arguments ...any) (count int, err error) { - if usedInTransaction() { + if db.usedInTransaction() { return 0, inTxErr } res, err := db.pgx.Exec(ctx, string(sql), arguments...) @@ -61,7 +62,7 @@ type Query struct { // fmt.Println(id, name) // } func (db *DB) Query(ctx context.Context, sql rawStringOnly, arguments ...any) (*Query, error) { - if usedInTransaction() { + if db.usedInTransaction() { return &Query{}, inTxErr } q, err := db.pgx.Query(ctx, string(sql), arguments...) @@ -76,7 +77,8 @@ type Row interface { } type rowErr struct{} -func (rowErr) Scan(..any) error { return inTxErr } + +func (rowErr) Scan(_ ...any) error { return inTxErr } // QueryRow gets 1 row using column order matching. // This is a timesaver for the special case of wanting the first row returned only. @@ -86,10 +88,10 @@ func (rowErr) Scan(..any) error { return inTxErr } // var ID = 123 // err := db.QueryRow(ctx, "SELECT name, pet FROM users WHERE ID=?", ID).Scan(&name, &pet) func (db *DB) QueryRow(ctx context.Context, sql rawStringOnly, arguments ...any) Row { - if usedInTransaction() { + if db.usedInTransaction() { return rowErr{} } - return db.pgx.QueryRow(ctx, string(sql), arguments...) + return db.pgx.QueryRow(ctx, string(sql), arguments...) } /* @@ -107,7 +109,7 @@ Ex: err := db.Select(ctx, &users, "SELECT name, id, tel_no FROM customers WHERE pet=?", pet) */ func (db *DB) Select(ctx context.Context, sliceOfStructPtr any, sql rawStringOnly, arguments ...any) error { - if usedInTransaction() { + if db.usedInTransaction() { return inTxErr } return pgxscan.Select(ctx, db.pgx, sliceOfStructPtr, string(sql), arguments...) @@ -118,29 +120,31 @@ type Tx struct { ctx context.Context } -// usedInTransaction is a helper to prevent nesting transactions -// & non-transaction calls in transactions. In the case of a stack read error, -// it will return false, so only use true for a course of action. -func usedInTransaction() bool { - ok := true - fn := "" - for v:=2; ok; v++ { - _,_,fn,ok = runtime.Caller(v) - if strings.Contains(fn, "BeginTransaction") { - return true - } - } - return false +// usedInTransaction is a helper to prevent nesting transactions +// & non-transaction calls in transactions. It only checks 20 frames. +// Fast: This memory should all be in CPU Caches. +func (db *DB) usedInTransaction() bool { + var framePtrs = (&[20]uintptr{})[:] + runtime.Callers(3, framePtrs) + return lo.Contains(framePtrs, db.BTFP) } // BeginTransaction is how you can access transactions using this library. // The entire transaction happens in the function passed in. // The return must be true or a rollback will occur. // Be sure to test the error for IsErrSerialization() if you want to retry -// when there is a DB serialization error. +// +// when there is a DB serialization error. +// +//go:noinline func (db *DB) BeginTransaction(ctx context.Context, f func(*Tx) (commit bool, err error)) (didCommit bool, retErr error) { - if usedInTransaction() { - return 0, inTxErr + db.BTFPOnce.Do(func() { + fp := make([]uintptr, 20) + runtime.Callers(1, fp) + db.BTFP = fp[0] + }) + if db.usedInTransaction() { + return false, inTxErr } tx, err := db.pgx.BeginTx(ctx, pgx.TxOptions{}) if err != nil { From 4ab92cae70784e1bf139e2e2c2c39a635be60a77 Mon Sep 17 00:00:00 2001 From: Phi Date: Fri, 8 Dec 2023 09:21:07 +0100 Subject: [PATCH 21/68] Fix log output format in wdPostTaskCmd Fix log output format in wdPostTaskCmd --- cmd/lotus-provider/proving.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-provider/proving.go b/cmd/lotus-provider/proving.go index 577b5b5f9..a3211b176 100644 --- a/cmd/lotus-provider/proving.go +++ b/cmd/lotus-provider/proving.go @@ -117,7 +117,7 @@ var wdPostTaskCmd = &cli.Command{ } fmt.Print(".") } - log.Infof("Result:", result.String) + log.Infof("Result: %s", result.String) return nil }, } From 986f240d914915cd8390ae810890f4ce22c0758b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 9 Dec 2023 18:08:32 +0900 Subject: [PATCH 22/68] fix: exchange: allow up to 10k messages per block Also explicitly limit how many bytes we're willing to read in one go such that we're capable of reading a worst-case tipset (like, really, never going to happen worst-case). Previously, this wasn't an issue. However, we've bumped the max number of messages from 8,192 to 150,000 and need to limit allocations somewhere else. --- chain/exchange/cbor_gen.go | 140 +++++----------------------- chain/exchange/client.go | 10 +- chain/exchange/protocol.go | 2 + chain/exchange/protocol_encoding.go | 125 +++++++++++++++++++++++++ gen/main.go | 2 +- 5 files changed, 161 insertions(+), 118 deletions(-) create mode 100644 chain/exchange/protocol_encoding.go diff --git a/chain/exchange/cbor_gen.go b/chain/exchange/cbor_gen.go index e66b6d798..71c75869d 100644 --- a/chain/exchange/cbor_gen.go +++ b/chain/exchange/cbor_gen.go @@ -306,9 +306,9 @@ func (t *Response) UnmarshalCBOR(r io.Reader) (err error) { return nil } -var lengthBufCompactedMessages = []byte{132} +var lengthBufCompactedMessagesCBOR = []byte{132} -func (t *CompactedMessages) MarshalCBOR(w io.Writer) error { +func (t *CompactedMessagesCBOR) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) return err @@ -316,12 +316,12 @@ func (t *CompactedMessages) MarshalCBOR(w io.Writer) error { cw := cbg.NewCborWriter(w) - if _, err := cw.Write(lengthBufCompactedMessages); err != nil { + if _, err := cw.Write(lengthBufCompactedMessagesCBOR); err != nil { return err } // t.Bls ([]*types.Message) (slice) - if len(t.Bls) > cbg.MaxLength { + if len(t.Bls) > 150000 { return xerrors.Errorf("Slice value in field t.Bls was too long") } @@ -334,7 +334,7 @@ func (t *CompactedMessages) MarshalCBOR(w io.Writer) error { } } - // t.BlsIncludes ([][]uint64) (slice) + // t.BlsIncludes ([]exchange.messageIndices) (slice) if len(t.BlsIncludes) > cbg.MaxLength { return xerrors.Errorf("Slice value in field t.BlsIncludes was too long") } @@ -343,24 +343,13 @@ func (t *CompactedMessages) MarshalCBOR(w io.Writer) error { return err } for _, v := range t.BlsIncludes { - if len(v) > cbg.MaxLength { - return xerrors.Errorf("Slice value in field v was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(v))); err != nil { + if err := v.MarshalCBOR(cw); err != nil { return err } - for _, v := range v { - - if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(v)); err != nil { - return err - } - - } } // t.Secpk ([]*types.SignedMessage) (slice) - if len(t.Secpk) > cbg.MaxLength { + if len(t.Secpk) > 150000 { return xerrors.Errorf("Slice value in field t.Secpk was too long") } @@ -373,7 +362,7 @@ func (t *CompactedMessages) MarshalCBOR(w io.Writer) error { } } - // t.SecpkIncludes ([][]uint64) (slice) + // t.SecpkIncludes ([]exchange.messageIndices) (slice) if len(t.SecpkIncludes) > cbg.MaxLength { return xerrors.Errorf("Slice value in field t.SecpkIncludes was too long") } @@ -382,26 +371,15 @@ func (t *CompactedMessages) MarshalCBOR(w io.Writer) error { return err } for _, v := range t.SecpkIncludes { - if len(v) > cbg.MaxLength { - return xerrors.Errorf("Slice value in field v was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(v))); err != nil { + if err := v.MarshalCBOR(cw); err != nil { return err } - for _, v := range v { - - if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(v)); err != nil { - return err - } - - } } return nil } -func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { - *t = CompactedMessages{} +func (t *CompactedMessagesCBOR) UnmarshalCBOR(r io.Reader) (err error) { + *t = CompactedMessagesCBOR{} cr := cbg.NewCborReader(r) @@ -430,7 +408,7 @@ func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { return err } - if extra > cbg.MaxLength { + if extra > 150000 { return fmt.Errorf("t.Bls: array too large (%d)", extra) } @@ -471,7 +449,7 @@ func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { } } - // t.BlsIncludes ([][]uint64) (slice) + // t.BlsIncludes ([]exchange.messageIndices) (slice) maj, extra, err = cr.ReadHeader() if err != nil { @@ -487,7 +465,7 @@ func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { } if extra > 0 { - t.BlsIncludes = make([][]uint64, extra) + t.BlsIncludes = make([]messageIndices, extra) } for i := 0; i < int(extra); i++ { @@ -499,47 +477,13 @@ func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { _ = extra _ = err - maj, extra, err = cr.ReadHeader() - if err != nil { - return err - } + { - if extra > cbg.MaxLength { - return fmt.Errorf("t.BlsIncludes[i]: array too large (%d)", extra) - } - - if maj != cbg.MajArray { - return fmt.Errorf("expected cbor array") - } - - if extra > 0 { - t.BlsIncludes[i] = make([]uint64, extra) - } - - for j := 0; j < int(extra); j++ { - { - var maj byte - var extra uint64 - var err error - _ = maj - _ = extra - _ = err - - { - - maj, extra, err = cr.ReadHeader() - if err != nil { - return err - } - if maj != cbg.MajUnsignedInt { - return fmt.Errorf("wrong type for uint64 field") - } - t.BlsIncludes[i][j] = uint64(extra) - - } + if err := t.BlsIncludes[i].UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.BlsIncludes[i]: %w", err) } - } + } } } @@ -550,7 +494,7 @@ func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { return err } - if extra > cbg.MaxLength { + if extra > 150000 { return fmt.Errorf("t.Secpk: array too large (%d)", extra) } @@ -591,7 +535,7 @@ func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { } } - // t.SecpkIncludes ([][]uint64) (slice) + // t.SecpkIncludes ([]exchange.messageIndices) (slice) maj, extra, err = cr.ReadHeader() if err != nil { @@ -607,7 +551,7 @@ func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { } if extra > 0 { - t.SecpkIncludes = make([][]uint64, extra) + t.SecpkIncludes = make([]messageIndices, extra) } for i := 0; i < int(extra); i++ { @@ -619,47 +563,13 @@ func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { _ = extra _ = err - maj, extra, err = cr.ReadHeader() - if err != nil { - return err - } + { - if extra > cbg.MaxLength { - return fmt.Errorf("t.SecpkIncludes[i]: array too large (%d)", extra) - } - - if maj != cbg.MajArray { - return fmt.Errorf("expected cbor array") - } - - if extra > 0 { - t.SecpkIncludes[i] = make([]uint64, extra) - } - - for j := 0; j < int(extra); j++ { - { - var maj byte - var extra uint64 - var err error - _ = maj - _ = extra - _ = err - - { - - maj, extra, err = cr.ReadHeader() - if err != nil { - return err - } - if maj != cbg.MajUnsignedInt { - return fmt.Errorf("wrong type for uint64 field") - } - t.SecpkIncludes[i][j] = uint64(extra) - - } + if err := t.SecpkIncludes[i].UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.SecpkIncludes[i]: %w", err) } - } + } } } diff --git a/chain/exchange/client.go b/chain/exchange/client.go index db39628be..fca8249ce 100644 --- a/chain/exchange/client.go +++ b/chain/exchange/client.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "fmt" + "io" "math/rand" "time" @@ -23,6 +24,10 @@ import ( "github.com/filecoin-project/lotus/lib/peermgr" ) +// Set the max exchange message size to 120MiB. Purely based on gas numbers, we can include ~8MiB of +// messages per block, so I've set this to 120MiB to be _very_ safe. +const maxExchangeMessageSize = (15 * 8) << 20 + // client implements exchange.Client, using the libp2p ChainExchange protocol // as the fetching mechanism. type client struct { @@ -434,10 +439,11 @@ func (c *client) sendRequestToPeer(ctx context.Context, peer peer.ID, req *Reque log.Warnw("CloseWrite err", "error", err) } - // Read response. + // Read response, limiting the size of the response to maxExchangeMessageSize as we allow a + // lot of messages (10k+) but they'll mostly be quite small. var res Response err = cborutil.ReadCborRPC( - bufio.NewReader(incrt.New(stream, ReadResMinSpeed, ReadResDeadline)), + bufio.NewReader(io.LimitReader(incrt.New(stream, ReadResMinSpeed, ReadResDeadline), maxExchangeMessageSize)), &res) if err != nil { c.peerTracker.logFailure(peer, build.Clock.Since(connectionStart), req.Length) diff --git a/chain/exchange/protocol.go b/chain/exchange/protocol.go index 5e12d31cc..cd25f4a43 100644 --- a/chain/exchange/protocol.go +++ b/chain/exchange/protocol.go @@ -154,6 +154,8 @@ type BSTipSet struct { // FIXME: The logic to decompress this structure should belong // // to itself, not to the consumer. +// +// NOTE: Max messages is: BlockMessageLimit (10k) * MaxTipsetSize (15) = 150k type CompactedMessages struct { Bls []*types.Message BlsIncludes [][]uint64 diff --git a/chain/exchange/protocol_encoding.go b/chain/exchange/protocol_encoding.go new file mode 100644 index 000000000..7df00a639 --- /dev/null +++ b/chain/exchange/protocol_encoding.go @@ -0,0 +1,125 @@ +package exchange + +import ( + "fmt" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" + + "github.com/filecoin-project/lotus/build" + types "github.com/filecoin-project/lotus/chain/types" +) + +// Type used for encoding/decoding compacted messages. This is a ustom type as we need custom limits. +// - Max messages is 150,000 as that's 15 times the max block size (in messages). It needs to be +// large enough to cover a full tipset full of full blocks. +type CompactedMessagesCBOR struct { + Bls []*types.Message `cborgen:"maxlen=150000"` + BlsIncludes []messageIndices + + Secpk []*types.SignedMessage `cborgen:"maxlen=150000"` + SecpkIncludes []messageIndices +} + +// Unmarshal into the "decoding" struct, then copy into the actual struct. +func (t *CompactedMessages) UnmarshalCBOR(r io.Reader) (err error) { + var c CompactedMessagesCBOR + if err := c.UnmarshalCBOR(r); err != nil { + return err + } + t.Bls = c.Bls + t.BlsIncludes = make([][]uint64, len(c.BlsIncludes)) + for i, v := range c.BlsIncludes { + t.BlsIncludes[i] = v.v + } + t.Secpk = c.Secpk + t.SecpkIncludes = make([][]uint64, len(c.SecpkIncludes)) + for i, v := range c.SecpkIncludes { + t.SecpkIncludes[i] = v.v + } + return nil +} + +// Copy into the encoding struct, then marshal. +func (t *CompactedMessages) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + var c CompactedMessagesCBOR + c.Bls = t.Bls + c.BlsIncludes = make([]messageIndices, len(t.BlsIncludes)) + for i, v := range t.BlsIncludes { + c.BlsIncludes[i].v = v + } + c.Secpk = t.Secpk + c.SecpkIncludes = make([]messageIndices, len(t.SecpkIncludes)) + for i, v := range t.SecpkIncludes { + c.SecpkIncludes[i].v = v + } + return c.MarshalCBOR(w) +} + +// this needs to be a struct or cborgen will peak into it and ignore the Unmarshal/Marshal functions +type messageIndices struct { + v []uint64 +} + +func (t *messageIndices) UnmarshalCBOR(r io.Reader) (err error) { + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra > build.BlockMessageLimit { + return fmt.Errorf("cbor input had wrong number of fields") + } + + if extra > 0 { + t.v = make([]uint64, extra) + } + + for i := 0; i < int(extra); i++ { + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.v[i] = uint64(extra) + + } + return nil +} + +func (t *messageIndices) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if len(t.v) > build.BlockMessageLimit { + return xerrors.Errorf("Slice value in field v was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.v))); err != nil { + return err + } + for _, v := range t.v { + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(v)); err != nil { + return err + } + } + return nil +} diff --git a/gen/main.go b/gen/main.go index 0cd3999c3..942b3ac2c 100644 --- a/gen/main.go +++ b/gen/main.go @@ -92,7 +92,7 @@ func main() { err = gen.WriteTupleEncodersToFile("./chain/exchange/cbor_gen.go", "exchange", exchange.Request{}, exchange.Response{}, - exchange.CompactedMessages{}, + exchange.CompactedMessagesCBOR{}, exchange.BSTipSet{}, ) if err != nil { From 88e90aaa44fbcca7c2505bade05db3f1035492bc Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 9 Dec 2023 18:21:22 +0900 Subject: [PATCH 23/68] fix lints --- chain/exchange/protocol_encoding.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/exchange/protocol_encoding.go b/chain/exchange/protocol_encoding.go index 7df00a639..ca15831d6 100644 --- a/chain/exchange/protocol_encoding.go +++ b/chain/exchange/protocol_encoding.go @@ -95,7 +95,7 @@ func (t *messageIndices) UnmarshalCBOR(r io.Reader) (err error) { if maj != cbg.MajUnsignedInt { return fmt.Errorf("wrong type for uint64 field") } - t.v[i] = uint64(extra) + t.v[i] = extra } return nil @@ -117,7 +117,7 @@ func (t *messageIndices) MarshalCBOR(w io.Writer) error { return err } for _, v := range t.v { - if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, uint64(v)); err != nil { + if err := cw.WriteMajorTypeHeader(cbg.MajUnsignedInt, v); err != nil { return err } } From f2a4891ada91ff7cfb6b4fd7b1ee02426593ebf1 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 9 Dec 2023 23:24:43 +0900 Subject: [PATCH 24/68] fix: exchange: explicitly cast the block message limit const (#11511) It's not a const for the testground build, and needs to be an int 99% of the time. So we might as well just cast here. --- chain/exchange/protocol_encoding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/exchange/protocol_encoding.go b/chain/exchange/protocol_encoding.go index ca15831d6..040dd0d40 100644 --- a/chain/exchange/protocol_encoding.go +++ b/chain/exchange/protocol_encoding.go @@ -79,7 +79,7 @@ func (t *messageIndices) UnmarshalCBOR(r io.Reader) (err error) { return fmt.Errorf("cbor input should be of type array") } - if extra > build.BlockMessageLimit { + if extra > uint64(build.BlockMessageLimit) { return fmt.Errorf("cbor input had wrong number of fields") } From 4a5c24176275dea965c6ed44bb42cb1c518a07c5 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Sat, 9 Dec 2023 23:47:21 +0800 Subject: [PATCH 25/68] bump version --- build/openrpc/full.json.gz | Bin 34817 -> 34817 bytes build/openrpc/gateway.json.gz | Bin 11875 -> 11875 bytes build/openrpc/miner.json.gz | Bin 16370 -> 16370 bytes build/openrpc/worker.json.gz | Bin 6052 -> 6052 bytes build/version.go | 2 +- documentation/en/cli-lotus-miner.md | 2 +- documentation/en/cli-lotus-worker.md | 2 +- documentation/en/cli-lotus.md | 2 +- 8 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index ad2116cb9187f20cea37fef3a37566fd3a2730cf..c40fbf2ccb25a5a4f9eebabe81c044faf4f0f2dc 100644 GIT binary patch delta 23 fcmZpiz|=T_X+j6%-i@6F?Hn&UKmVBWi;V#QelH6q delta 23 fcmZpiz|=T_X+j6%zKxv)?Hp?jf^Db#Vq*XRa*qi( diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 48ad91135e370665117694d7515928b8773c1ad8..ead9a4e655ce0c24ba7d60320fce3a5ec0c92da1 100644 GIT binary patch delta 21 ccmaDH^EhTgGh@}pmg~A48j??1vU`~r0C83b@c;k- delta 21 dcmaDH^EhTgGvls}E!TB97}Rb5XZJEO0044z2L~AKE^3RkL{Tm0BvRm`v3p{ delta 21 dcmexV|EYdL3uF7n)>M0rAjbFCAKNoC004Ob37-G} diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 8e9d63d795a477a58214191b82d59ea52770cd47..078e8f95c7f0c4af2487dfe8f2798551d7b43122 100644 GIT binary patch delta 21 ccmZ3YzeImRBjbyWO;X|<^7C8L3nLgA09~mEfB*mh delta 21 ccmZ3YzeImRBV)$KCMj_a$+8 Date: Sat, 9 Dec 2023 11:20:41 -0600 Subject: [PATCH 26/68] fix: lint --- lib/harmony/harmonydb/userfuncs.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/harmony/harmonydb/userfuncs.go b/lib/harmony/harmonydb/userfuncs.go index 8abce73d0..eb17efd46 100644 --- a/lib/harmony/harmonydb/userfuncs.go +++ b/lib/harmony/harmonydb/userfuncs.go @@ -12,7 +12,7 @@ import ( "github.com/samber/lo" ) -var inTxErr = errors.New("Cannot use a non-transaction func in a transaction") +var errTx = errors.New("Cannot use a non-transaction func in a transaction") // rawStringOnly is _intentionally_private_ to force only basic strings in SQL queries. // In any package, raw strings will satisfy compilation. Ex: @@ -27,7 +27,7 @@ type rawStringOnly string // them in the ./sql/ files (next number). func (db *DB) Exec(ctx context.Context, sql rawStringOnly, arguments ...any) (count int, err error) { if db.usedInTransaction() { - return 0, inTxErr + return 0, errTx } res, err := db.pgx.Exec(ctx, string(sql), arguments...) return int(res.RowsAffected()), err @@ -63,7 +63,7 @@ type Query struct { // } func (db *DB) Query(ctx context.Context, sql rawStringOnly, arguments ...any) (*Query, error) { if db.usedInTransaction() { - return &Query{}, inTxErr + return &Query{}, errTx } q, err := db.pgx.Query(ctx, string(sql), arguments...) return &Query{q}, err @@ -78,7 +78,7 @@ type Row interface { type rowErr struct{} -func (rowErr) Scan(_ ...any) error { return inTxErr } +func (rowErr) Scan(_ ...any) error { return errTx } // QueryRow gets 1 row using column order matching. // This is a timesaver for the special case of wanting the first row returned only. @@ -110,7 +110,7 @@ Ex: */ func (db *DB) Select(ctx context.Context, sliceOfStructPtr any, sql rawStringOnly, arguments ...any) error { if db.usedInTransaction() { - return inTxErr + return errTx } return pgxscan.Select(ctx, db.pgx, sliceOfStructPtr, string(sql), arguments...) } @@ -124,9 +124,9 @@ type Tx struct { // & non-transaction calls in transactions. It only checks 20 frames. // Fast: This memory should all be in CPU Caches. func (db *DB) usedInTransaction() bool { - var framePtrs = (&[20]uintptr{})[:] - runtime.Callers(3, framePtrs) - return lo.Contains(framePtrs, db.BTFP) + var framePtrs = (&[20]uintptr{})[:] // 20 can be stack-local (no alloc) + runtime.Callers(3, framePtrs) // skip past our caller. + return lo.Contains(framePtrs, db.BTFP) // Unsafe read @ beginTx overlap, but 'return false' is correct there. } // BeginTransaction is how you can access transactions using this library. @@ -144,7 +144,7 @@ func (db *DB) BeginTransaction(ctx context.Context, f func(*Tx) (commit bool, er db.BTFP = fp[0] }) if db.usedInTransaction() { - return false, inTxErr + return false, errTx } tx, err := db.pgx.BeginTx(ctx, pgx.TxOptions{}) if err != nil { From 96353e63ea062212b0227cb69155252764538856 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 10:50:49 -0600 Subject: [PATCH 27/68] exp backoff, short stack err --- cmd/lotus-provider/proving.go | 3 +++ lib/harmony/harmonydb/userfuncs.go | 6 +++--- lib/harmony/harmonytask/task_type_handler.go | 6 ++++++ storage/paths/db_index.go | 9 +++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/cmd/lotus-provider/proving.go b/cmd/lotus-provider/proving.go index 621896c91..025950586 100644 --- a/cmd/lotus-provider/proving.go +++ b/cmd/lotus-provider/proving.go @@ -82,6 +82,7 @@ var wdPostTaskCmd = &cli.Command{ return xerrors.Errorf("cannot get miner id %w", err) } var id int64 + retryDelay := time.Millisecond * 10 retryAddTask: _, err = deps.db.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { err = tx.QueryRow(`INSERT INTO harmony_task (name, posted_time, added_by) VALUES ('WdPost', CURRENT_TIMESTAMP, 123) RETURNING id`).Scan(&id) @@ -104,6 +105,8 @@ var wdPostTaskCmd = &cli.Command{ }) if err != nil { if harmonydb.IsErrSerialization(err) { + time.Sleep(retryDelay) + retryDelay *= 2 goto retryAddTask } return xerrors.Errorf("writing SQL transaction: %w", err) diff --git a/lib/harmony/harmonydb/userfuncs.go b/lib/harmony/harmonydb/userfuncs.go index eb17efd46..9e2b5a1b6 100644 --- a/lib/harmony/harmonydb/userfuncs.go +++ b/lib/harmony/harmonydb/userfuncs.go @@ -124,9 +124,9 @@ type Tx struct { // & non-transaction calls in transactions. It only checks 20 frames. // Fast: This memory should all be in CPU Caches. func (db *DB) usedInTransaction() bool { - var framePtrs = (&[20]uintptr{})[:] // 20 can be stack-local (no alloc) - runtime.Callers(3, framePtrs) // skip past our caller. - return lo.Contains(framePtrs, db.BTFP) // Unsafe read @ beginTx overlap, but 'return false' is correct there. + var framePtrs = (&[20]uintptr{})[:] // 20 can be stack-local (no alloc) + framePtrs = framePtrs[:runtime.Callers(3, framePtrs)] // skip past our caller. + return lo.Contains(framePtrs, db.BTFP) // Unsafe read @ beginTx overlap, but 'return false' is correct there. } // BeginTransaction is how you can access transactions using this library. diff --git a/lib/harmony/harmonytask/task_type_handler.go b/lib/harmony/harmonytask/task_type_handler.go index 6091cb61e..ccfcc1f6f 100644 --- a/lib/harmony/harmonytask/task_type_handler.go +++ b/lib/harmony/harmonytask/task_type_handler.go @@ -25,6 +25,7 @@ type taskTypeHandler struct { func (h *taskTypeHandler) AddTask(extra func(TaskID, *harmonydb.Tx) (bool, error)) { var tID TaskID + retryWait := time.Millisecond * 100 retryAddTask: _, err := h.TaskEngine.db.BeginTransaction(h.TaskEngine.ctx, func(tx *harmonydb.Tx) (bool, error) { // create taskID (from DB) @@ -46,6 +47,8 @@ retryAddTask: return } if harmonydb.IsErrSerialization(err) { + time.Sleep(retryWait) + retryWait *= 2 goto retryAddTask } log.Error("Could not add task. AddTasFunc failed: %v", err) @@ -165,6 +168,7 @@ top: func (h *taskTypeHandler) recordCompletion(tID TaskID, workStart time.Time, done bool, doErr error) { workEnd := time.Now() + retryWait := time.Millisecond * 100 retryRecordCompletion: cm, err := h.TaskEngine.db.BeginTransaction(h.TaskEngine.ctx, func(tx *harmonydb.Tx) (bool, error) { var postedTime time.Time @@ -219,6 +223,8 @@ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, tID, h.Name, postedTime, workStart, wo }) if err != nil { if harmonydb.IsErrSerialization(err) { + time.Sleep(retryWait) + retryWait *= 2 goto retryRecordCompletion } log.Error("Could not record transaction: ", err) diff --git a/storage/paths/db_index.go b/storage/paths/db_index.go index 69a03198d..e6bf3e5da 100644 --- a/storage/paths/db_index.go +++ b/storage/paths/db_index.go @@ -180,6 +180,7 @@ func (dbi *DBIndex) StorageAttach(ctx context.Context, si storiface.StorageInfo, } } + retryWait := time.Millisecond * 100 retryAttachStorage: // Single transaction to attach storage which is not present in the DB _, err := dbi.harmonyDB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { @@ -246,6 +247,8 @@ retryAttachStorage: }) if err != nil { if harmonydb.IsErrSerialization(err) { + time.Sleep(retryWait) + retryWait *= 2 goto retryAttachStorage } return err @@ -287,6 +290,7 @@ func (dbi *DBIndex) StorageDetach(ctx context.Context, id storiface.ID, url stri log.Warnw("Dropping sector path endpoint", "path", id, "url", url) } else { + retryWait := time.Millisecond * 100 retryDropPath: // Single transaction to drop storage path and sector decls which have this as a storage path _, err := dbi.harmonyDB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { @@ -305,6 +309,8 @@ func (dbi *DBIndex) StorageDetach(ctx context.Context, id storiface.ID, url stri }) if err != nil { if harmonydb.IsErrSerialization(err) { + time.Sleep(retryWait) + retryWait *= 2 goto retryDropPath } return err @@ -380,6 +386,7 @@ func (dbi *DBIndex) StorageDeclareSector(ctx context.Context, storageID storifac return xerrors.Errorf("invalid filetype") } + retryWait := time.Millisecond * 100 retryStorageDeclareSector: _, err := dbi.harmonyDB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { var currPrimary sql.NullBool @@ -416,6 +423,8 @@ retryStorageDeclareSector: }) if err != nil { if harmonydb.IsErrSerialization(err) { + time.Sleep(retryWait) + retryWait *= 2 goto retryStorageDeclareSector } return err From de38e77cfc11d471d13eb00c6ae209e6bf8abb03 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 11:31:38 -0600 Subject: [PATCH 28/68] tx-detector use atomic --- lib/harmony/harmonydb/harmonydb.go | 3 ++- lib/harmony/harmonydb/userfuncs.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/harmony/harmonydb/harmonydb.go b/lib/harmony/harmonydb/harmonydb.go index caa5d1daa..5ec9f5a25 100644 --- a/lib/harmony/harmonydb/harmonydb.go +++ b/lib/harmony/harmonydb/harmonydb.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "time" logging "github.com/ipfs/go-log/v2" @@ -35,7 +36,7 @@ type DB struct { schema string hostnames []string BTFPOnce sync.Once - BTFP uintptr + BTFP atomic.Uintptr } var logger = logging.Logger("harmonydb") diff --git a/lib/harmony/harmonydb/userfuncs.go b/lib/harmony/harmonydb/userfuncs.go index 9e2b5a1b6..7fcf76dcd 100644 --- a/lib/harmony/harmonydb/userfuncs.go +++ b/lib/harmony/harmonydb/userfuncs.go @@ -126,7 +126,7 @@ type Tx struct { func (db *DB) usedInTransaction() bool { var framePtrs = (&[20]uintptr{})[:] // 20 can be stack-local (no alloc) framePtrs = framePtrs[:runtime.Callers(3, framePtrs)] // skip past our caller. - return lo.Contains(framePtrs, db.BTFP) // Unsafe read @ beginTx overlap, but 'return false' is correct there. + return lo.Contains(framePtrs, db.BTFP.Load()) // Unsafe read @ beginTx overlap, but 'return false' is correct there. } // BeginTransaction is how you can access transactions using this library. @@ -141,7 +141,7 @@ func (db *DB) BeginTransaction(ctx context.Context, f func(*Tx) (commit bool, er db.BTFPOnce.Do(func() { fp := make([]uintptr, 20) runtime.Callers(1, fp) - db.BTFP = fp[0] + db.BTFP.Store(fp[0]) }) if db.usedInTransaction() { return false, errTx From becfc470a291c84881699584356ea5cacb6fadbf Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 17:47:29 -0600 Subject: [PATCH 29/68] basic ensemble provider --- itests/kit/ensemble.go | 56 +++++++++++++++++++++++++++++----- itests/kit/ensemble_presets.go | 2 +- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index 3c83ba896..12e2ce8aa 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -20,6 +20,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" "github.com/filecoin-project/go-address" cborutil "github.com/filecoin-project/go-cbor-util" @@ -45,6 +46,9 @@ import ( "github.com/filecoin-project/lotus/chain/stmgr" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/wallet/key" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" + "github.com/filecoin-project/lotus/cmd/lotus-provider/rpc" + "github.com/filecoin-project/lotus/cmd/lotus-provider/tasks" "github.com/filecoin-project/lotus/cmd/lotus-seed/seed" "github.com/filecoin-project/lotus/cmd/lotus-worker/sealworker" "github.com/filecoin-project/lotus/gateway" @@ -120,15 +124,17 @@ type Ensemble struct { options *ensembleOpts inactive struct { - fullnodes []*TestFullNode - miners []*TestMiner - workers []*TestWorker + fullnodes []*TestFullNode + providernodes []*TestProviderNode + miners []*TestMiner + workers []*TestWorker } active struct { - fullnodes []*TestFullNode - miners []*TestMiner - workers []*TestWorker - bms map[*TestMiner]*BlockMiner + fullnodes []*TestFullNode + providernodes []*TestProviderNode + miners []*TestMiner + workers []*TestWorker + bms map[*TestMiner]*BlockMiner } genesis struct { version network.Version @@ -221,6 +227,20 @@ func (n *Ensemble) FullNode(full *TestFullNode, opts ...NodeOpt) *Ensemble { return n } +// FullNode enrolls a new Provider node. +func (n *Ensemble) Provider(lp *TestProviderNode, opts ...NodeOpt) *Ensemble { + options := DefaultNodeOpts + for _, o := range opts { + err := o(&options) + require.NoError(n.t, err) + } + + *lp = TestProviderNode{t: n.t, options: options, Deps: &deps.Deps{}} + + n.inactive.providernodes = append(n.inactive.providernodes, lp) + return n +} + // Miner enrolls a new miner, using the provided full node for chain // interactions. func (n *Ensemble) MinerEnroll(minerNode *TestMiner, full *TestFullNode, opts ...NodeOpt) *Ensemble { @@ -886,6 +906,28 @@ func (n *Ensemble) Start() *Ensemble { // to active, so clear the slice. n.inactive.workers = n.inactive.workers[:0] + for _, p := range n.inactive.providernodes { + + // TODO setup config with options + err := p.Deps.PopulateRemainingDeps(context.Background(), &cli.Context{}, false) + require.NoError(n.t, err) + + shutdownChan := make(chan struct{}) + taskEngine, err := tasks.StartTasks(ctx, p.Deps) + if err != nil { + return nil + } + defer taskEngine.GracefullyTerminate(time.Hour) + + err = rpc.ListenAndServe(ctx, p.Deps, shutdownChan) // Monitor for shutdown. + require.NoError(n.t, err) + finishCh := node.MonitorShutdown(shutdownChan) //node.ShutdownHandler{Component: "rpc server", StopFunc: rpcStopper}, + //node.ShutdownHandler{Component: "provider", StopFunc: stop}, + + <-finishCh + + n.active.providernodes = append(n.active.providernodes, p) + } // --------------------- // MISC // --------------------- diff --git a/itests/kit/ensemble_presets.go b/itests/kit/ensemble_presets.go index 88f07b684..68b85fde0 100644 --- a/itests/kit/ensemble_presets.go +++ b/itests/kit/ensemble_presets.go @@ -112,7 +112,7 @@ func EnsembleProvider(t *testing.T, opts ...interface{}) (*TestFullNode, *TestPr full TestFullNode provider TestProviderNode ) - ens := NewEnsemble(t, eopts...).FullNode(&full, nopts...).Provider(&provider, &full, nopts...).Start() + ens := NewEnsemble(t, eopts...).FullNode(&full, nopts...).Provider(&provider, nopts...).Start() return &full, &provider, ens } From cdcb96567c8c598ada8c6aa60f8366f83b5d2cf7 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 18:12:05 -0600 Subject: [PATCH 30/68] listenAndServe hooked up --- cmd/lotus-provider/rpc/rpc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-provider/rpc/rpc.go b/cmd/lotus-provider/rpc/rpc.go index 0fe1039d9..b724d8d4d 100644 --- a/cmd/lotus-provider/rpc/rpc.go +++ b/cmd/lotus-provider/rpc/rpc.go @@ -134,5 +134,5 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c log.Warn("Graceful shutdown successful") }() - return nil + return srv.ListenAndServe() } From 0bad4d910dd055deb20440144509f60873511687 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 18:30:39 -0600 Subject: [PATCH 31/68] fix the listener --- cmd/lotus-provider/proving.go | 2 +- cmd/lotus-provider/rpc/rpc.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/lotus-provider/proving.go b/cmd/lotus-provider/proving.go index 1602739ed..379bfdf85 100644 --- a/cmd/lotus-provider/proving.go +++ b/cmd/lotus-provider/proving.go @@ -86,7 +86,7 @@ var wdPostTaskCmd = &cli.Command{ retryDelay := time.Millisecond * 10 retryAddTask: - _, err = deps.db.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { + _, err = deps.DB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) { err = tx.QueryRow(`INSERT INTO harmony_task (name, posted_time, added_by) VALUES ('WdPost', CURRENT_TIMESTAMP, 123) RETURNING id`).Scan(&id) if err != nil { log.Error("inserting harmony_task: ", err) diff --git a/cmd/lotus-provider/rpc/rpc.go b/cmd/lotus-provider/rpc/rpc.go index b724d8d4d..cc0ecbb3b 100644 --- a/cmd/lotus-provider/rpc/rpc.go +++ b/cmd/lotus-provider/rpc/rpc.go @@ -123,6 +123,7 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-worker")) return ctx }, + Addr: dependencies.ListenAddr, } go func() { From 0175faf5c2a3b7695e7d863714e3becd0d028fdf Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 21:10:15 -0600 Subject: [PATCH 32/68] deps fix --- cmd/lotus-provider/deps/deps.go | 7 +++++-- cmd/lotus-provider/rpc/rpc.go | 1 + cmd/lotus-provider/run.go | 7 ++++--- ~/.lotus-provider/journal/lotus-journal.ndjson | 0 4 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 ~/.lotus-provider/journal/lotus-journal.ndjson diff --git a/cmd/lotus-provider/deps/deps.go b/cmd/lotus-provider/deps/deps.go index 54305f6a1..13b83b83d 100644 --- a/cmd/lotus-provider/deps/deps.go +++ b/cmd/lotus-provider/deps/deps.go @@ -83,8 +83,8 @@ func StorageAuth(apiKey string) (sealer.StorageAuth, error) { } func GetDeps(ctx context.Context, cctx *cli.Context) (*Deps, error) { - var deps *Deps - return deps, deps.PopulateRemainingDeps(ctx, cctx, true) + var deps Deps + return &deps, deps.PopulateRemainingDeps(ctx, cctx, true) } type Deps struct { @@ -107,6 +107,9 @@ const ( func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context, makeRepo bool) error { + if deps == nil { + *deps = Deps{} + } var err error if makeRepo { // Open repo diff --git a/cmd/lotus-provider/rpc/rpc.go b/cmd/lotus-provider/rpc/rpc.go index cc0ecbb3b..1f075f79a 100644 --- a/cmd/lotus-provider/rpc/rpc.go +++ b/cmd/lotus-provider/rpc/rpc.go @@ -135,5 +135,6 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c log.Warn("Graceful shutdown successful") }() + log.Infof("Setting up RPC server at %s", dependencies.ListenAddr) return srv.ListenAndServe() } diff --git a/cmd/lotus-provider/run.go b/cmd/lotus-provider/run.go index 975762f0a..f58d0c939 100644 --- a/cmd/lotus-provider/run.go +++ b/cmd/lotus-provider/run.go @@ -113,11 +113,12 @@ var runCmd = &cli.Command{ } } - var dependencies *deps.Deps - err = dependencies.PopulateRemainingDeps(ctx, cctx, true) + var deps deps.Deps + err = deps.PopulateRemainingDeps(ctx, cctx, true) if err != nil { return err } + dependencies := &deps taskEngine, err := tasks.StartTasks(ctx, dependencies) @@ -136,4 +137,4 @@ var runCmd = &cli.Command{ <-finishCh return nil }, -} \ No newline at end of file +} diff --git a/~/.lotus-provider/journal/lotus-journal.ndjson b/~/.lotus-provider/journal/lotus-journal.ndjson new file mode 100644 index 000000000..e69de29bb From a478b734fd7d93ea30a1de2210c3160e185a06f7 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 23:15:41 -0600 Subject: [PATCH 33/68] build-env: unable to exit from deps --- cmd/lotus-provider/deps/deps.go | 5 +---- cmd/lotus-provider/main.go | 6 +++--- cmd/lotus-provider/run.go | 10 +++++++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cmd/lotus-provider/deps/deps.go b/cmd/lotus-provider/deps/deps.go index 13b83b83d..9a0a3691f 100644 --- a/cmd/lotus-provider/deps/deps.go +++ b/cmd/lotus-provider/deps/deps.go @@ -106,10 +106,6 @@ const ( ) func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context, makeRepo bool) error { - - if deps == nil { - *deps = Deps{} - } var err error if makeRepo { // Open repo @@ -242,6 +238,7 @@ Get it with: jq .PrivateKey ~/.lotus-miner/keystore/MF2XI2BNNJ3XILLQOJUXMYLUMU`, deps.Maddrs = append(deps.Maddrs, dtypes.MinerAddress(addr)) } } + fmt.Println("last line of populate") return nil } diff --git a/cmd/lotus-provider/main.go b/cmd/lotus-provider/main.go index 48ff70122..18b2e87f3 100644 --- a/cmd/lotus-provider/main.go +++ b/cmd/lotus-provider/main.go @@ -5,7 +5,7 @@ import ( "fmt" "os" "os/signal" - "runtime/debug" + "runtime/pprof" "syscall" "github.com/fatih/color" @@ -29,8 +29,8 @@ func SetupCloseHandler() { go func() { <-c fmt.Println("\r- Ctrl+C pressed in Terminal") - debug.PrintStack() - os.Exit(1) + pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) + panic(1) }() } diff --git a/cmd/lotus-provider/run.go b/cmd/lotus-provider/run.go index f58d0c939..8e7d5ad79 100644 --- a/cmd/lotus-provider/run.go +++ b/cmd/lotus-provider/run.go @@ -113,14 +113,18 @@ var runCmd = &cli.Command{ } } - var deps deps.Deps - err = deps.PopulateRemainingDeps(ctx, cctx, true) + fmt.Println("before populateRemainingDeps") + dependencies := &deps.Deps{} + err = dependencies.PopulateRemainingDeps(ctx, cctx, true) + fmt.Println("after popdeps") if err != nil { + fmt.Println("err", err) return err } - dependencies := &deps + fmt.Println("ef") taskEngine, err := tasks.StartTasks(ctx, dependencies) + fmt.Println("gh") if err != nil { return nil From 4161c270d73f7ac706f9b2d2d8314378d2fc5609 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 23:16:57 -0600 Subject: [PATCH 34/68] debugWeb 1 --- cmd/lotus-provider/rpc/rpc.go | 18 +- cmd/lotus-provider/web/api/debug/debug.go | 95 +++++++++ cmd/lotus-provider/web/api/routes.go | 12 ++ cmd/lotus-provider/web/srv.go | 40 ++++ cmd/lotus-provider/web/static/index.html | 181 ++++++++++++++++++ .../web/static/modules/chain-connectivity.js | 73 +++++++ node/config/def.go | 4 +- node/config/types.go | 3 + 8 files changed, 423 insertions(+), 3 deletions(-) create mode 100644 cmd/lotus-provider/web/api/debug/debug.go create mode 100644 cmd/lotus-provider/web/api/routes.go create mode 100644 cmd/lotus-provider/web/srv.go create mode 100644 cmd/lotus-provider/web/static/index.html create mode 100644 cmd/lotus-provider/web/static/modules/chain-connectivity.js diff --git a/cmd/lotus-provider/rpc/rpc.go b/cmd/lotus-provider/rpc/rpc.go index 1f075f79a..4b4a77cf9 100644 --- a/cmd/lotus-provider/rpc/rpc.go +++ b/cmd/lotus-provider/rpc/rpc.go @@ -13,6 +13,7 @@ import ( "github.com/gorilla/mux" logging "github.com/ipfs/go-log/v2" "go.opencensus.io/tag" + "golang.org/x/sync/errgroup" "golang.org/x/xerrors" "github.com/filecoin-project/go-jsonrpc" @@ -20,6 +21,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" + "github.com/filecoin-project/lotus/cmd/lotus-provider/web" "github.com/filecoin-project/lotus/lib/rpcenc" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/metrics/proxy" @@ -126,15 +128,27 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c Addr: dependencies.ListenAddr, } + log.Infof("Setting up RPC server at %s", dependencies.ListenAddr) + + web, err := web.GetSrv(ctx, dependencies) + if err != nil { + return err + } + go func() { <-ctx.Done() log.Warn("Shutting down...") if err := srv.Shutdown(context.TODO()); err != nil { log.Errorf("shutting down RPC server failed: %s", err) } + if err := web.Shutdown(context.Background()); err != nil { + log.Errorf("shutting down web server failed: %s", err) + } log.Warn("Graceful shutdown successful") }() - log.Infof("Setting up RPC server at %s", dependencies.ListenAddr) - return srv.ListenAndServe() + eg := errgroup.Group{} + eg.Go(srv.ListenAndServe) + eg.Go(web.ListenAndServe) + return eg.Wait() } diff --git a/cmd/lotus-provider/web/api/debug/debug.go b/cmd/lotus-provider/web/api/debug/debug.go new file mode 100644 index 000000000..1dcd7c5a3 --- /dev/null +++ b/cmd/lotus-provider/web/api/debug/debug.go @@ -0,0 +1,95 @@ +// Package debug provides the API for various debug endpoints in lotus-provider. +package debug + +import ( + "encoding/json" + "fmt" + "net/http" + "time" + + "github.com/gorilla/mux" + logging "github.com/ipfs/go-log/v2" + + "github.com/filecoin-project/lotus/build" + cliutil "github.com/filecoin-project/lotus/cli/util" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" +) + +var log = logging.Logger("lp/web/debug") + +type debug struct { + *deps.Deps +} + +func Routes(r *mux.Router, deps *deps.Deps) { + d := debug{deps} + r.Methods("GET").Path("chain-state-sse").HandlerFunc(d.chainStateSSE) +} + +type rpcInfo struct { + Address string + CLayers []string + Reachable bool + SyncState string + Version string +} + +func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + w.Header().Set("Content-Type", "text/event-stream") + w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Connection", "keep-alive") + + v1api := d.Deps.Full + ctx := r.Context() + + ai := cliutil.ParseApiInfo(d.Deps.Cfg.Apis.ChainApiInfo[0]) + ver, err := v1api.Version(ctx) + if err != nil { + log.Warnw("Version", "error", err) + return + } + +sse: + for { + head, err := v1api.ChainHead(ctx) + if err != nil { + log.Warnw("ChainHead", "error", err) + return + } + + var syncState string + switch { + case time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs*3/2): // within 1.5 epochs + syncState = "ok" + case time.Now().Unix()-int64(head.MinTimestamp()) < int64(build.BlockDelaySecs*5): // within 5 epochs + syncState = fmt.Sprintf("slow (%s behind)", time.Since(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second)) + default: + syncState = fmt.Sprintf("behind (%s behind)", time.Since(time.Unix(int64(head.MinTimestamp()), 0)).Truncate(time.Second)) + } + + select { + case <-ctx.Done(): + break sse + default: + } + + fmt.Fprintf(w, "data: ") + err = json.NewEncoder(w).Encode(rpcInfo{ + Address: ai.Addr, + CLayers: []string{}, + Reachable: true, + Version: ver.Version, + SyncState: syncState, + }) + if err != nil { + log.Warnw("json encode", "error", err) + return + } + fmt.Fprintf(w, "\n\n") + if f, ok := w.(http.Flusher); ok { + f.Flush() + } + } +} diff --git a/cmd/lotus-provider/web/api/routes.go b/cmd/lotus-provider/web/api/routes.go new file mode 100644 index 000000000..91e317722 --- /dev/null +++ b/cmd/lotus-provider/web/api/routes.go @@ -0,0 +1,12 @@ +// Package api provides the HTTP API for the lotus provider web gui. +package api + +import ( + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" + "github.com/filecoin-project/lotus/cmd/lotus-provider/web/api/debug" + "github.com/gorilla/mux" +) + +func Routes(r *mux.Router, deps *deps.Deps) { + debug.Routes(r.PathPrefix("/debug").Subrouter(), deps) +} diff --git a/cmd/lotus-provider/web/srv.go b/cmd/lotus-provider/web/srv.go new file mode 100644 index 000000000..f59a8d837 --- /dev/null +++ b/cmd/lotus-provider/web/srv.go @@ -0,0 +1,40 @@ +// Package web defines the HTTP web server for static files and endpoints. +package web + +import ( + "context" + "embed" + "net" + "net/http" + "strings" + + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" + "github.com/filecoin-project/lotus/cmd/lotus-provider/web/api" + "github.com/filecoin-project/lotus/metrics" + "github.com/gorilla/mux" + "go.opencensus.io/tag" +) + +// go:embed static +var static embed.FS + +func GetSrv(ctx context.Context, deps *deps.Deps) (*http.Server, error) { + mux := mux.NewRouter() + api.Routes(mux.PathPrefix("/api").Subrouter(), deps) + mux.NotFoundHandler = http.FileServer(http.FS(static)) + + return &http.Server{ + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.HasSuffix(r.URL.Path, "/") { + r.URL.Path = r.URL.Path + "index.html" + return + } + mux.ServeHTTP(w, r) + }), + BaseContext: func(listener net.Listener) context.Context { + ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-provider")) + return ctx + }, + Addr: deps.Cfg.Subsystems.GuiAddress, + }, nil +} diff --git a/cmd/lotus-provider/web/static/index.html b/cmd/lotus-provider/web/static/index.html new file mode 100644 index 000000000..731ee799b --- /dev/null +++ b/cmd/lotus-provider/web/static/index.html @@ -0,0 +1,181 @@ + + + + Lotus Provider Cluster Overview + + + + + +

+
+

Lotus Provider Cluster

+
+
+ version [todo] +
+
+
+
+
+

Chain Connectivity

+ +
+
+
+
+

Actor Summary

+ + + + + + + + + + + + + + + + + +
AddressConfig LayersQaPDeadlines
f01234mig023TiB +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/cmd/lotus-provider/web/static/modules/chain-connectivity.js b/cmd/lotus-provider/web/static/modules/chain-connectivity.js new file mode 100644 index 000000000..871f40094 --- /dev/null +++ b/cmd/lotus-provider/web/static/modules/chain-connectivity.js @@ -0,0 +1,73 @@ +import { LitElement, html, css } from 'https://cdn.jsdelivr.net/npm/lit-html@3.1.0/lit-html.min.js'; +window.customElements.define('chain-connectivity', class MyElement extends LitElement { + constructor() { + super(); + this.data = []; + this.loadData(); + } + loadData() { + const eventSource = new EventSource('/api/debug/chain-state-sse'); + eventSource.onmessage = (event) => { + this.data.push(JSON.parse(event.data)); + }; + eventSource.onerror = (error) => { + console.error('Error:', error); + loadData(); + }; + }; + + static get styles() { + return [css` + :host { + box-sizing: border-box; /* Don't forgert this to include padding/border inside width calculation */ + } + table { + border-collapse: collapse; + } + + table td, table th { + border-left: 1px solid #f0f0f0; + padding: 1px 5px; + } + + table tr td:first-child, table tr th:first-child { + border-left: none; + } + + .success { + color: green; + } + .warning { + color: yellow; + } + .error { + color: red; + } + `]; + } + render = () => html` + + + + + + + + + + + ${this.data.map(item => html` + + + + + + + + `)} + + + + +
RPC AddressReachabilitySync StatusVersion
{{.Address}}${item.Address}${item.Reachable ? html`ok` : html`FAIL`}${item.SyncState === "ok" ? html`ok` : html`${item.SyncState}`}${item.Version}
Data incoming...
` +}); diff --git a/node/config/def.go b/node/config/def.go index dc358b140..e8f315add 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -351,7 +351,9 @@ func DefaultUserRaftConfig() *UserRaftConfig { func DefaultLotusProvider() *LotusProviderConfig { return &LotusProviderConfig{ - Subsystems: ProviderSubsystemsConfig{}, + Subsystems: ProviderSubsystemsConfig{ + GuiAddress: ":4701", + }, Fees: LotusProviderFees{ DefaultMaxFee: DefaultDefaultMaxFee, MaxPreCommitGasFee: types.MustParseFIL("0.025"), diff --git a/node/config/types.go b/node/config/types.go index 2152e0795..6233191f4 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -96,6 +96,9 @@ type ProviderSubsystemsConfig struct { WindowPostMaxTasks int EnableWinningPost bool WinningPostMaxTasks int + + // The address that should listen for Web GUI requests. + GuiAddress string } type DAGStoreConfig struct { From 17e17eaac3fe6542a26ac2ac16749b8f807c15fd Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 23:36:04 -0600 Subject: [PATCH 35/68] move --- cmd/lotus-provider/web/static/{modules => }/chain-connectivity.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cmd/lotus-provider/web/static/{modules => }/chain-connectivity.js (100%) diff --git a/cmd/lotus-provider/web/static/modules/chain-connectivity.js b/cmd/lotus-provider/web/static/chain-connectivity.js similarity index 100% rename from cmd/lotus-provider/web/static/modules/chain-connectivity.js rename to cmd/lotus-provider/web/static/chain-connectivity.js From 8070e3424f8f5a761f05eec2c92ddbe642c5bdac Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 23:47:31 -0600 Subject: [PATCH 36/68] fix deps --- cmd/lotus-provider/web/static/chain-connectivity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-provider/web/static/chain-connectivity.js b/cmd/lotus-provider/web/static/chain-connectivity.js index 871f40094..2381a2f22 100644 --- a/cmd/lotus-provider/web/static/chain-connectivity.js +++ b/cmd/lotus-provider/web/static/chain-connectivity.js @@ -1,4 +1,4 @@ -import { LitElement, html, css } from 'https://cdn.jsdelivr.net/npm/lit-html@3.1.0/lit-html.min.js'; +import { LitElement, html, css } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-all.min.js'; window.customElements.define('chain-connectivity', class MyElement extends LitElement { constructor() { super(); From 5717ec8c0af286e1d3832ace7c561ca2bbdf7f07 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Mon, 11 Dec 2023 23:48:07 -0600 Subject: [PATCH 37/68] fix deps2 --- cmd/lotus-provider/web/static/chain-connectivity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-provider/web/static/chain-connectivity.js b/cmd/lotus-provider/web/static/chain-connectivity.js index 2381a2f22..6fc63234f 100644 --- a/cmd/lotus-provider/web/static/chain-connectivity.js +++ b/cmd/lotus-provider/web/static/chain-connectivity.js @@ -1,4 +1,4 @@ -import { LitElement, html, css } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-all.min.js'; +import { LitElement, html, css } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js'; window.customElements.define('chain-connectivity', class MyElement extends LitElement { constructor() { super(); From bc76004c1564da48ecda173b92d65c038e50e30a Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 12 Dec 2023 08:07:38 -0600 Subject: [PATCH 38/68] module --- cmd/lotus-provider/web/static/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/lotus-provider/web/static/index.html b/cmd/lotus-provider/web/static/index.html index 731ee799b..00b48b6fd 100644 --- a/cmd/lotus-provider/web/static/index.html +++ b/cmd/lotus-provider/web/static/index.html @@ -2,7 +2,7 @@ Lotus Provider Cluster Overview - + - -
-
-

Lotus Provider Cluster

-
-
- version [todo] -
+
+
+

Lotus Provider Cluster

-
-
-
-

Chain Connectivity

- -
+
+ version [todo] +
+
+
+
+
+

Chain Connectivity

+

Actor Summary

- - - - - - + + + + + + - - - - - - - +
AddressConfig LayersQaPDeadlines
AddressConfig LayersQaPDeadlines
f01234mig023TiB -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+

Cluster Machines

+ + + + + + + + + + + +
HostIDConfig LayersLast Contact
+
+
+

Recently Finished Tasks

+ + + + + + + + + + + + + + + +
NameIDExecutorPostedStartEndOutcomeMessage
+
+
+
+

Cluster Tasks

+ + + + + + + + + + + +
TaskIDPostedOwner
+
+
- \ No newline at end of file diff --git a/lib/harmony/harmonytask/task_type_handler.go b/lib/harmony/harmonytask/task_type_handler.go index ccfcc1f6f..a6e8933d2 100644 --- a/lib/harmony/harmonytask/task_type_handler.go +++ b/lib/harmony/harmonytask/task_type_handler.go @@ -184,6 +184,9 @@ retryRecordCompletion: return false, fmt.Errorf("could not log completion: %w", err) } result = "" + if doErr != nil { + result = "non-failing error: " + doErr.Error() + } } else { if doErr != nil { result = "error: " + doErr.Error() diff --git a/provider/lpwinning/winning_task.go b/provider/lpwinning/winning_task.go index 907b594fd..6e5e1cc5a 100644 --- a/provider/lpwinning/winning_task.go +++ b/provider/lpwinning/winning_task.go @@ -156,13 +156,18 @@ func (t *WinPostTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (don ComputeTime: details.CompTime, } - persistNoWin := func() error { - _, err := t.db.Exec(ctx, `UPDATE mining_base_block SET no_win = true WHERE task_id = $1`, taskID) + persistNoWin := func() (bool, error) { + n, err := t.db.Exec(ctx, `UPDATE mining_base_block SET no_win = true WHERE task_id = $1`, taskID) if err != nil { - return xerrors.Errorf("marking base as not-won: %w", err) + return false, xerrors.Errorf("marking base as not-won: %w", err) + } + log.Debugw("persisted no-win", "rows", n) + + if n == 0 { + return false, xerrors.Errorf("persist no win: no rows updated") } - return nil + return false, nil } // ensure we have a beacon entry for the epoch we're mining on @@ -182,13 +187,13 @@ func (t *WinPostTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (don if mbi == nil { // not eligible to mine on this base, we're done here log.Debugw("WinPoSt not eligible to mine on this base", "tipset", types.LogCids(base.TipSet.Cids())) - return true, persistNoWin() + return persistNoWin() } if !mbi.EligibleForMining { // slashed or just have no power yet, we're done here log.Debugw("WinPoSt not eligible for mining", "tipset", types.LogCids(base.TipSet.Cids())) - return true, persistNoWin() + return persistNoWin() } if len(mbi.Sectors) == 0 { @@ -217,7 +222,7 @@ func (t *WinPostTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (don if eproof == nil { // not a winner, we're done here log.Debugw("WinPoSt not a winner", "tipset", types.LogCids(base.TipSet.Cids())) - return true, persistNoWin() + return persistNoWin() } } From 25b228c2f60cf9c0021544f06d11d766e64dc01a Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 19 Dec 2023 09:12:45 -0600 Subject: [PATCH 50/68] fix: lint --- cmd/lotus-provider/web/api/routes.go | 3 ++- cmd/lotus-provider/web/hapi/routes.go | 4 ++-- cmd/lotus-provider/web/srv.go | 5 +++-- documentation/en/cli-lotus-provider.md | 18 ++++++++++++++++++ .../en/default-lotus-provider-config.toml | 8 ++++++++ node/config/doc_gen.go | 12 ++++++++++++ 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/cmd/lotus-provider/web/api/routes.go b/cmd/lotus-provider/web/api/routes.go index 91e317722..9bb6fb67c 100644 --- a/cmd/lotus-provider/web/api/routes.go +++ b/cmd/lotus-provider/web/api/routes.go @@ -2,9 +2,10 @@ package api import ( + "github.com/gorilla/mux" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" "github.com/filecoin-project/lotus/cmd/lotus-provider/web/api/debug" - "github.com/gorilla/mux" ) func Routes(r *mux.Router, deps *deps.Deps) { diff --git a/cmd/lotus-provider/web/hapi/routes.go b/cmd/lotus-provider/web/hapi/routes.go index b56c8c7c0..d327a76a8 100644 --- a/cmd/lotus-provider/web/hapi/routes.go +++ b/cmd/lotus-provider/web/hapi/routes.go @@ -4,11 +4,11 @@ import ( "embed" "html/template" + "github.com/gorilla/mux" logging "github.com/ipfs/go-log/v2" + "golang.org/x/xerrors" "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" - "github.com/gorilla/mux" - "golang.org/x/xerrors" ) //go:embed web/* diff --git a/cmd/lotus-provider/web/srv.go b/cmd/lotus-provider/web/srv.go index 869280005..f41501fef 100644 --- a/cmd/lotus-provider/web/srv.go +++ b/cmd/lotus-provider/web/srv.go @@ -8,12 +8,13 @@ import ( "net/http" "strings" + "github.com/gorilla/mux" + "go.opencensus.io/tag" + "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" "github.com/filecoin-project/lotus/cmd/lotus-provider/web/api" "github.com/filecoin-project/lotus/cmd/lotus-provider/web/hapi" "github.com/filecoin-project/lotus/metrics" - "github.com/gorilla/mux" - "go.opencensus.io/tag" ) // go:embed static diff --git a/documentation/en/cli-lotus-provider.md b/documentation/en/cli-lotus-provider.md index de77697e3..a01cd0856 100644 --- a/documentation/en/cli-lotus-provider.md +++ b/documentation/en/cli-lotus-provider.md @@ -14,6 +14,7 @@ COMMANDS: stop Stop a running lotus provider config Manage node config by layers. The layer 'base' will always be applied. test Utility functions for testing + web Start lotus provider web interface version Print version help, h Shows a list of commands or help for one command DEVELOPER: @@ -247,6 +248,23 @@ OPTIONS: --help, -h show help ``` +## lotus-provider web +``` +NAME: + lotus-provider web - Start lotus provider web interface + +USAGE: + lotus-provider web [command options] [arguments...] + +DESCRIPTION: + Start an instance of lotus provider web interface. + This creates the 'web' layer if it does not exist, then calls run with that layer. + +OPTIONS: + --listen value Address to listen on (default: "127.0.0.1:4701") + --help, -h show help +``` + ## lotus-provider version ``` NAME: diff --git a/documentation/en/default-lotus-provider-config.toml b/documentation/en/default-lotus-provider-config.toml index 91606e503..8573fbda1 100644 --- a/documentation/en/default-lotus-provider-config.toml +++ b/documentation/en/default-lotus-provider-config.toml @@ -11,6 +11,14 @@ # type: int #WinningPostMaxTasks = 0 + # type: bool + #EnableWebGui = false + + # The address that should listen for Web GUI requests. + # + # type: string + #GuiAddress = ":4701" + [Fees] # type: types.FIL diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 13ecb2706..012214770 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -1013,6 +1013,18 @@ block rewards will be missed!`, Comment: ``, }, + { + Name: "EnableWebGui", + Type: "bool", + + Comment: ``, + }, + { + Name: "GuiAddress", + Type: "string", + + Comment: `The address that should listen for Web GUI requests.`, + }, }, "ProvingConfig": { { From bfc26cdc184c9c1f4dd8d9c7d8a8dea912aeb03b Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 19 Dec 2023 16:39:52 -0500 Subject: [PATCH 51/68] fix: sync: do not include incoming in return of syncFork (#11541) --- chain/sync.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/sync.go b/chain/sync.go index c61c9f310..4dccc2036 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -896,7 +896,7 @@ func (syncer *Syncer) syncFork(ctx context.Context, incoming *types.TipSet, know if commonParent { // known contains at least one of incoming's Parents => the common ancestor is known's Parents (incoming's Grandparents) - // in this case, we need to return {incoming, incoming.Parents()} + // in this case, we need to return {incoming.Parents()} incomingParents, err := syncer.store.LoadTipSet(ctx, incomingParentsTsk) if err != nil { // fallback onto the network @@ -912,7 +912,7 @@ func (syncer *Syncer) syncFork(ctx context.Context, incoming *types.TipSet, know incomingParents = tips[0] } - return []*types.TipSet{incoming, incomingParents}, nil + return []*types.TipSet{incomingParents}, nil } // TODO: Does this mean we always ask for ForkLengthThreshold blocks from the network, even if we just need, like, 2? Yes. From b0bc4a96320942c0673a3cab08314074edf4b4f9 Mon Sep 17 00:00:00 2001 From: Rob Quist Date: Wed, 20 Dec 2023 01:18:20 +0100 Subject: [PATCH 52/68] Fix 2 typo's (#11542) * Fix typo in miner * Fix typo in sectors.go --- cmd/lotus-miner/sectors.go | 2 +- cmd/lotus-shed/miner.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/lotus-miner/sectors.go b/cmd/lotus-miner/sectors.go index 07cc2e795..3e4439eb8 100644 --- a/cmd/lotus-miner/sectors.go +++ b/cmd/lotus-miner/sectors.go @@ -2290,7 +2290,7 @@ var sectorsCompactPartitionsCmd = &cli.Command{ if len(parts) <= 0 { return fmt.Errorf("must include at least one partition to compact") } - fmt.Printf("compacting %d paritions\n", len(parts)) + fmt.Printf("compacting %d partitions\n", len(parts)) var makeMsgForPartitions func(partitionsBf bitfield.BitField) ([]*types.Message, error) makeMsgForPartitions = func(partitionsBf bitfield.BitField) ([]*types.Message, error) { diff --git a/cmd/lotus-shed/miner.go b/cmd/lotus-shed/miner.go index a8bb93744..2f9b4ecf1 100644 --- a/cmd/lotus-shed/miner.go +++ b/cmd/lotus-shed/miner.go @@ -553,7 +553,7 @@ var sendInvalidWindowPoStCmd = &cli.Command{ return xerrors.Errorf("serializing params: %w", err) } - fmt.Printf("submitting bad PoST for %d paritions\n", len(partitionIndices)) + fmt.Printf("submitting bad PoST for %d partitions\n", len(partitionIndices)) smsg, err := api.MpoolPushMessage(ctx, &types.Message{ From: minfo.Worker, To: maddr, From 8dffab5d3964487448f232ab4ff7a3fe46283598 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 19 Dec 2023 18:58:55 -0600 Subject: [PATCH 53/68] fix: lp lint and dev simplicities --- cmd/lotus-provider/run.go | 8 ++++++-- cmd/lotus-provider/web/hapi/simpleinfo.go | 2 +- cmd/lotus-provider/web/srv.go | 13 ++++++++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/cmd/lotus-provider/run.go b/cmd/lotus-provider/run.go index 00e3079d9..a47cb6ec4 100644 --- a/cmd/lotus-provider/run.go +++ b/cmd/lotus-provider/run.go @@ -167,12 +167,16 @@ var webCmd = &cli.Command{ cfg := config.DefaultLotusProvider() cfg.Subsystems.EnableWebGui = true var b bytes.Buffer - toml.NewEncoder(&b).Encode(cfg) + if err = toml.NewEncoder(&b).Encode(cfg); err != nil { + return err + } if err = setConfig(db, "web", b.String()); err != nil { return err } } - cctx.Set("layers", "web") + if err = cctx.Set("layers", "web"); err != nil { + return err + } return runCmd.Action(cctx) }, } diff --git a/cmd/lotus-provider/web/hapi/simpleinfo.go b/cmd/lotus-provider/web/hapi/simpleinfo.go index 470739518..a14735a84 100644 --- a/cmd/lotus-provider/web/hapi/simpleinfo.go +++ b/cmd/lotus-provider/web/hapi/simpleinfo.go @@ -77,7 +77,7 @@ func (a *app) indexTasksHistory(w http.ResponseWriter, r *http.Request) { a.executeTemplate(w, "cluster_task_history", s) } -var templateDev = os.Getenv("LOTUS_HAPI_TEMPLATE_DEV") == "1" +var templateDev = os.Getenv("LOTUS_WEB_DEV") == "1" func (a *app) executeTemplate(w http.ResponseWriter, name string, data interface{}) { if templateDev { diff --git a/cmd/lotus-provider/web/srv.go b/cmd/lotus-provider/web/srv.go index f41501fef..c618d0baa 100644 --- a/cmd/lotus-provider/web/srv.go +++ b/cmd/lotus-provider/web/srv.go @@ -6,7 +6,9 @@ import ( "embed" "net" "net/http" + "os" "strings" + "time" "github.com/gorilla/mux" "go.opencensus.io/tag" @@ -20,6 +22,10 @@ import ( // go:embed static var static embed.FS +// An dev mode hack for no-restart changes to static and templates. +// You still need to recomplie the binary for changes to go code. +var webDev = os.Getenv("LOTUS_WEB_DEV") == "1" + func GetSrv(ctx context.Context, deps *deps.Deps) (*http.Server, error) { mux := mux.NewRouter() api.Routes(mux.PathPrefix("/api").Subrouter(), deps) @@ -28,6 +34,9 @@ func GetSrv(ctx context.Context, deps *deps.Deps) (*http.Server, error) { return nil, err } mux.NotFoundHandler = http.FileServer(http.FS(static)) + if webDev { + mux.NotFoundHandler = http.FileServer(http.Dir("cmd/lotus-provider/web/static")) + } return &http.Server{ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -41,6 +50,8 @@ func GetSrv(ctx context.Context, deps *deps.Deps) (*http.Server, error) { ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-provider")) return ctx }, - Addr: deps.Cfg.Subsystems.GuiAddress, + Addr: deps.Cfg.Subsystems.GuiAddress, + ReadTimeout: time.Minute * 3, + ReadHeaderTimeout: time.Minute * 3, // lint }, nil } From d9d1b4370ce149b1809c0d26f15014db3fc1df89 Mon Sep 17 00:00:00 2001 From: Rob Quist Date: Thu, 21 Dec 2023 18:14:00 +0100 Subject: [PATCH 54/68] Remove error log as its no longer an error since snap --- storage/pipeline/input.go | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/pipeline/input.go b/storage/pipeline/input.go index 6fdae03d9..b595f533d 100644 --- a/storage/pipeline/input.go +++ b/storage/pipeline/input.go @@ -600,7 +600,6 @@ func (m *Sealing) updateInput(ctx context.Context, sp abi.RegisteredSealProof) e log.Debugw("updateInput matching done", "matches", len(matches), "toAssign", len(toAssign), "assigned", assigned, "openSectors", len(m.openSectors), "pieces", len(m.pendingPieces)) if len(toAssign) > 0 { - log.Errorf("we are trying to create a new sector with open sectors %v", m.openSectors) if err := m.tryGetDealSector(ctx, sp, getExpirationCached); err != nil { log.Errorw("Failed to create a new sector for deals", "error", err) } From 464e492fd20ac28da2030a2c5df66fb6d964038e Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Sat, 30 Dec 2023 09:37:04 -0600 Subject: [PATCH 55/68] srv cleanups --- cli/util/api.go | 2 +- cmd/lotus-provider/deps/deps.go | 8 +++- cmd/lotus-provider/run.go | 14 +++++- cmd/lotus-provider/web/api/debug/debug.go | 31 ++++++------- cmd/lotus-provider/web/hapi/routes.go | 4 +- cmd/lotus-provider/web/srv.go | 53 +++++++++++++++++------ 6 files changed, 75 insertions(+), 37 deletions(-) diff --git a/cli/util/api.go b/cli/util/api.go index 3602b752d..fe1ac1536 100644 --- a/cli/util/api.go +++ b/cli/util/api.go @@ -445,7 +445,7 @@ func GetFullNodeAPIV1LotusProvider(ctx *cli.Context, ainfoCfg []string, opts ... for _, head := range heads { v1api, closer, err := client.NewFullNodeRPCV1(ctx.Context, head.addr, head.header, rpcOpts...) if err != nil { - log.Warnf("Not able to establish connection to node with addr: %s", head.addr) + log.Warnf("Not able to establish connection to node with addr: %s, Reason: %s", head.addr, err.Error()) continue } fullNodes = append(fullNodes, v1api) diff --git a/cmd/lotus-provider/deps/deps.go b/cmd/lotus-provider/deps/deps.go index 499cc7bec..7a8db855f 100644 --- a/cmd/lotus-provider/deps/deps.go +++ b/cmd/lotus-provider/deps/deps.go @@ -9,6 +9,7 @@ import ( "fmt" "net" "net/http" + "os" "strings" "github.com/BurntSushi/toml" @@ -176,7 +177,11 @@ func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context, if deps.Full == nil { var fullCloser func() - deps.Full, fullCloser, err = cliutil.GetFullNodeAPIV1LotusProvider(cctx, deps.Cfg.Apis.ChainApiInfo) + cfgApiInfo := deps.Cfg.Apis.ChainApiInfo + if v := os.Getenv("FULLNODE_API_INFO"); v != "" { + cfgApiInfo = []string{v} + } + deps.Full, fullCloser, err = cliutil.GetFullNodeAPIV1LotusProvider(cctx, cfgApiInfo) if err != nil { return err } @@ -267,6 +272,7 @@ func GetConfig(cctx *cli.Context, db *harmonydb.DB) (*config.LotusProviderConfig for _, k := range meta.Keys() { have = append(have, strings.Join(k, " ")) } + log.Infow("Using layer", "layer", layer, "config", lp) } _ = have // FUTURE: verify that required fields are here. // If config includes 3rd-party config, consider JSONSchema as a way that diff --git a/cmd/lotus-provider/run.go b/cmd/lotus-provider/run.go index a47cb6ec4..0f18f2843 100644 --- a/cmd/lotus-provider/run.go +++ b/cmd/lotus-provider/run.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "os" + "strings" "time" "github.com/BurntSushi/toml" @@ -155,6 +156,15 @@ var webCmd = &cli.Command{ Usage: "Address to listen on", Value: "127.0.0.1:4701", }, + &cli.StringSliceFlag{ + Name: "layers", + Usage: "list of layers to be interpreted (atop defaults). Default: base. Web will be added", + Value: cli.NewStringSlice("base"), + }, + &cli.BoolFlag{ + Name: "nosync", + Usage: "don't check full-node sync status", + }, }, Action: func(cctx *cli.Context) error { db, err := deps.MakeDB(cctx) @@ -174,7 +184,9 @@ var webCmd = &cli.Command{ return err } } - if err = cctx.Set("layers", "web"); err != nil { + layers := append([]string{"web"}, cctx.StringSlice("layers")...) + err = cctx.Set("layers", strings.Join(layers, ",")) + if err != nil { return err } return runCmd.Action(cctx) diff --git a/cmd/lotus-provider/web/api/debug/debug.go b/cmd/lotus-provider/web/api/debug/debug.go index 7382ca3f8..845684519 100644 --- a/cmd/lotus-provider/web/api/debug/debug.go +++ b/cmd/lotus-provider/web/api/debug/debug.go @@ -29,7 +29,7 @@ type debug struct { func Routes(r *mux.Router, deps *deps.Deps) { d := debug{deps} - r.Methods("GET").Path("chain-state-sse").HandlerFunc(d.chainStateSSE) + r.HandleFunc("/chain-state-sse", d.chainStateSSE) } type rpcInfo struct { @@ -79,29 +79,24 @@ func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) { return } - apiInfos := map[string][]byte{} // api address -> token - // for dedup by address - for _, info := range rpcInfos { - ai := cliutil.ParseApiInfo(info.Apis.ChainApiInfo[0]) - apiInfos[ai.Addr] = ai.Token - } + dedup := map[string]bool{} // for dedup by address infos := map[string]rpcInfo{} // api address -> rpc info var infosLk sync.Mutex var wg sync.WaitGroup - wg.Add(len(rpcInfos)) - for addr, token := range apiInfos { - addr := addr - ai := cliutil.APIInfo{ - Addr: addr, - Token: token, + for _, info := range rpcInfos { + ai := cliutil.ParseApiInfo(info.Apis.ChainApiInfo[0]) + if dedup[ai.Addr] { + continue } - go func(info string) { + dedup[ai.Addr] = true + wg.Add(1) + go func() { defer wg.Done() var clayers []string for layer, a := range confNameToAddr { - if a == addr { + if a == ai.Addr { clayers = append(clayers, layer) } } @@ -113,8 +108,8 @@ func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) { } defer func() { infosLk.Lock() + defer infosLk.Unlock() infos[ai.Addr] = myinfo - infosLk.Unlock() }() da, err := ai.DialArgs("v1") if err != nil { @@ -126,7 +121,7 @@ func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) { v1api, closer, err := client.NewFullNodeRPCV1(ctx, da, ah) if err != nil { - log.Warnf("Not able to establish connection to node with addr: %s", addr) + log.Warnf("Not able to establish connection to node with addr: %s", ai.Addr) return } defer closer() @@ -160,7 +155,7 @@ func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) { Version: ver.Version, SyncState: syncState, } - }(addr) + }() } wg.Wait() diff --git a/cmd/lotus-provider/web/hapi/routes.go b/cmd/lotus-provider/web/hapi/routes.go index d327a76a8..b07ab60a5 100644 --- a/cmd/lotus-provider/web/hapi/routes.go +++ b/cmd/lotus-provider/web/hapi/routes.go @@ -15,9 +15,7 @@ import ( var templateFS embed.FS func Routes(r *mux.Router, deps *deps.Deps) error { - - t := new(template.Template) - t, err := t.ParseFS(templateFS, "web/*") + t, err := template.ParseFS(templateFS, "web/*") if err != nil { return xerrors.Errorf("parse templates: %w", err) } diff --git a/cmd/lotus-provider/web/srv.go b/cmd/lotus-provider/web/srv.go index c618d0baa..d409eb868 100644 --- a/cmd/lotus-provider/web/srv.go +++ b/cmd/lotus-provider/web/srv.go @@ -4,9 +4,12 @@ package web import ( "context" "embed" + "io" + "io/fs" "net" "net/http" "os" + "path" "strings" "time" @@ -19,33 +22,57 @@ import ( "github.com/filecoin-project/lotus/metrics" ) -// go:embed static +//go:embed static var static embed.FS +var basePath = "/static/" + // An dev mode hack for no-restart changes to static and templates. // You still need to recomplie the binary for changes to go code. var webDev = os.Getenv("LOTUS_WEB_DEV") == "1" func GetSrv(ctx context.Context, deps *deps.Deps) (*http.Server, error) { - mux := mux.NewRouter() - api.Routes(mux.PathPrefix("/api").Subrouter(), deps) - err := hapi.Routes(mux.PathPrefix("/hapi").Subrouter(), deps) + mx := mux.NewRouter() + err := hapi.Routes(mx.PathPrefix("/hapi").Subrouter(), deps) if err != nil { return nil, err } - mux.NotFoundHandler = http.FileServer(http.FS(static)) + api.Routes(mx.PathPrefix("/api").Subrouter(), deps) + + basePath := basePath + + var static fs.FS = static if webDev { - mux.NotFoundHandler = http.FileServer(http.Dir("cmd/lotus-provider/web/static")) + basePath = "cmd/lotus-provider/web/static" + static = os.DirFS(basePath) } + mx.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // If the request is for a directory, redirect to the index file. + if strings.HasSuffix(r.URL.Path, "/") { + r.URL.Path += "index.html" + } + + file, err := static.Open(path.Join(basePath, r.URL.Path)[1:]) + if err != nil { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte("404 Not Found")) + return + } + defer file.Close() + + fileInfo, err := file.Stat() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("500 Internal Server Error")) + return + } + + http.ServeContent(w, r, fileInfo.Name(), fileInfo.ModTime(), file.(io.ReadSeeker)) + }) + return &http.Server{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if strings.HasSuffix(r.URL.Path, "/") { - r.URL.Path = r.URL.Path + "index.html" - return - } - mux.ServeHTTP(w, r) - }), + Handler: http.HandlerFunc(mx.ServeHTTP), BaseContext: func(listener net.Listener) context.Context { ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-provider")) return ctx From 56bbeb01af7d55489ea69f83847d39a47ba087bb Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 2 Jan 2024 11:29:55 -0600 Subject: [PATCH 56/68] fix: lint --- cmd/lotus-provider/web/srv.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/lotus-provider/web/srv.go b/cmd/lotus-provider/web/srv.go index d409eb868..55d20cc9a 100644 --- a/cmd/lotus-provider/web/srv.go +++ b/cmd/lotus-provider/web/srv.go @@ -56,15 +56,15 @@ func GetSrv(ctx context.Context, deps *deps.Deps) (*http.Server, error) { file, err := static.Open(path.Join(basePath, r.URL.Path)[1:]) if err != nil { w.WriteHeader(http.StatusNotFound) - w.Write([]byte("404 Not Found")) + _, _ = w.Write([]byte("404 Not Found")) return } - defer file.Close() + defer func() { _ = file.Close() }() fileInfo, err := file.Stat() if err != nil { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte("500 Internal Server Error")) + _, _ = w.Write([]byte("500 Internal Server Error")) return } From 15128b69a7a93a0a294d05b91b53164d7a90e060 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Wed, 3 Jan 2024 10:11:10 -0600 Subject: [PATCH 57/68] Update winning_task.go last return should be true --- provider/lpwinning/winning_task.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/provider/lpwinning/winning_task.go b/provider/lpwinning/winning_task.go index 6e5e1cc5a..bf4f2fe71 100644 --- a/provider/lpwinning/winning_task.go +++ b/provider/lpwinning/winning_task.go @@ -167,7 +167,7 @@ func (t *WinPostTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (don return false, xerrors.Errorf("persist no win: no rows updated") } - return false, nil + return true, nil } // ensure we have a beacon entry for the epoch we're mining on From ad8e90d31cfecf14daa09b603409734280bc3e29 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Wed, 3 Jan 2024 16:18:23 -0600 Subject: [PATCH 58/68] lp debugWeb ui bug --- cmd/lotus-provider/web/static/chain-connectivity.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/lotus-provider/web/static/chain-connectivity.js b/cmd/lotus-provider/web/static/chain-connectivity.js index 1b37666bb..ea7349c41 100644 --- a/cmd/lotus-provider/web/static/chain-connectivity.js +++ b/cmd/lotus-provider/web/static/chain-connectivity.js @@ -59,7 +59,6 @@ window.customElements.define('chain-connectivity', class MyElement extends LitEl ${this.data.map(item => html` - {{.Address}} ${item.Address} ${item.Reachable ? html`ok` : html`FAIL`} ${item.SyncState === "ok" ? html`ok` : html`${item.SyncState}`} From fafaf0d7af0c14a74a83da65b539ac5810bc8346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 4 Jan 2024 12:47:30 +0100 Subject: [PATCH 59/68] fix: wdpost: fix vanilla proof indexes --- storage/sealer/worker_local.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/storage/sealer/worker_local.go b/storage/sealer/worker_local.go index 9f2f2efdc..7fc494955 100644 --- a/storage/sealer/worker_local.go +++ b/storage/sealer/worker_local.go @@ -664,7 +664,7 @@ func (l *LocalWorker) GenerateWindowPoStAdv(ctx context.Context, ppt abi.Registe var wg sync.WaitGroup wg.Add(len(sectors)) - vproofs := make([][]byte, 0, len(sectors)) + vproofs := make([][]byte, len(sectors)) for i, s := range sectors { if l.challengeThrottle != nil { @@ -702,8 +702,7 @@ func (l *LocalWorker) GenerateWindowPoStAdv(ctx context.Context, ppt abi.Registe return } - //vproofs[i] = vanilla // todo substitutes?? - vproofs = append(vproofs, vanilla) + vproofs[i] = vanilla }(i, s) } wg.Wait() @@ -717,6 +716,22 @@ func (l *LocalWorker) GenerateWindowPoStAdv(ctx context.Context, ppt abi.Registe return storiface.WindowPoStResult{Skipped: skipped}, nil } + // compact skipped sectors + var skippedSoFar int + for i := range vproofs { + if len(vproofs[i]) == 0 { + skippedSoFar++ + continue + } + + if skippedSoFar > 0 { + vproofs[i-skippedSoFar] = vproofs[i] + } + } + + vproofs = vproofs[:len(vproofs)-skippedSoFar] + + // compute the PoSt! res, err := sb.GenerateWindowPoStWithVanilla(ctx, ppt, mid, randomness, vproofs, partitionIdx) r := storiface.WindowPoStResult{ PoStProofs: res, From fc8e4c54f8479e15e5fed784c1db18a525a5cf30 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Thu, 4 Jan 2024 09:47:56 -0600 Subject: [PATCH 60/68] docsgen --- documentation/en/cli-lotus-provider.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/documentation/en/cli-lotus-provider.md b/documentation/en/cli-lotus-provider.md index a01cd0856..5e5864107 100644 --- a/documentation/en/cli-lotus-provider.md +++ b/documentation/en/cli-lotus-provider.md @@ -261,8 +261,10 @@ DESCRIPTION: This creates the 'web' layer if it does not exist, then calls run with that layer. OPTIONS: - --listen value Address to listen on (default: "127.0.0.1:4701") - --help, -h show help + --listen value Address to listen on (default: "127.0.0.1:4701") + --layers value [ --layers value ] list of layers to be interpreted (atop defaults). Default: base. Web will be added (default: "base") + --nosync don't check full-node sync status (default: false) + --help, -h show help ``` ## lotus-provider version From 156a3a400cbff6cd2cf95e0a0c71038241a04e59 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 6 Jan 2024 15:42:52 -0800 Subject: [PATCH 61/68] fix: Eth API: accept input data in call arguments under field 'input' (#11505) The correct name for this field is 'input' according to the Ethereum specs [0]. However, for the longest time, clients have been using 'data' and servers have been lenient to accept both, preferring 'input' over 'data' when both appear. Our lack of support for 'input' had gone unnoticed until go-ethereum decided to adjust their ethclient implementation to issue eth_call and eth_estimateGas requests with the 'input' field instead of 'data' [1]. This suddenly broke apps using this client against Lotus' Eth API. [0]: https://github.com/ethereum/execution-apis/blob/main/src/schemas/transaction.yaml#L33-L35 [1]: ethereum/go-ethereum#28078 Co-authored-by: raulk --- chain/types/ethtypes/eth_types.go | 18 ++++++++++++--- chain/types/ethtypes/eth_types_test.go | 31 +++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/chain/types/ethtypes/eth_types.go b/chain/types/ethtypes/eth_types.go index b933329f4..bff15ed24 100644 --- a/chain/types/ethtypes/eth_types.go +++ b/chain/types/ethtypes/eth_types.go @@ -229,13 +229,25 @@ type EthCall struct { } func (c *EthCall) UnmarshalJSON(b []byte) error { - type TempEthCall EthCall - var params TempEthCall + type EthCallRaw EthCall // Avoid a recursive call. + type EthCallDecode struct { + // The field should be "input" by spec, but many clients use "data" so we support + // both, but prefer "input". + Input *EthBytes `json:"input"` + EthCallRaw + } + var params EthCallDecode if err := json.Unmarshal(b, ¶ms); err != nil { return err } - *c = EthCall(params) + + // If input is specified, prefer it. + if params.Input != nil { + params.Data = *params.Input + } + + *c = EthCall(params.EthCallRaw) return nil } diff --git a/chain/types/ethtypes/eth_types_test.go b/chain/types/ethtypes/eth_types_test.go index 4a73184c2..2a1b2df55 100644 --- a/chain/types/ethtypes/eth_types_test.go +++ b/chain/types/ethtypes/eth_types_test.go @@ -194,11 +194,40 @@ func TestMaskedIDInF4(t *testing.T) { } func TestUnmarshalEthCall(t *testing.T) { - data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":""}` + data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":"0xFF"}` var c EthCall err := c.UnmarshalJSON([]byte(data)) require.Nil(t, err) + require.EqualValues(t, []byte{0xff}, c.Data) +} + +func TestUnmarshalEthCallInput(t *testing.T) { + data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","input":"0xFF"}` + + var c EthCall + err := c.UnmarshalJSON([]byte(data)) + require.Nil(t, err) + require.EqualValues(t, []byte{0xff}, c.Data) +} + +func TestUnmarshalEthCallInputAndData(t *testing.T) { + data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":"0xFE","input":"0xFF"}` + + var c EthCall + err := c.UnmarshalJSON([]byte(data)) + require.Nil(t, err) + require.EqualValues(t, []byte{0xff}, c.Data) +} + +func TestUnmarshalEthCallInputAndDataEmpty(t *testing.T) { + // Even if the input is empty, it should be used when specified. + data := `{"from":"0x4D6D86b31a112a05A473c4aE84afaF873f632325","to":"0xFe01CC39f5Ae8553D6914DBb9dC27D219fa22D7f","gas":"0x5","gasPrice":"0x6","value":"0x123","data":"0xFE","input":""}` + + var c EthCall + err := c.UnmarshalJSON([]byte(data)) + require.Nil(t, err) + require.EqualValues(t, []byte{}, c.Data) } func TestUnmarshalEthBytes(t *testing.T) { From b93e89c401f83544e930ae40143b9ddcd3fc4874 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 8 Jan 2024 14:55:15 -0800 Subject: [PATCH 62/68] chore: mod: use upstream poseidon The upstream PR was merged https://github.com/triplewz/poseidon/pull/1. --- go.mod | 4 +--- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 11a4a5d22..457968e84 100644 --- a/go.mod +++ b/go.mod @@ -142,7 +142,7 @@ require ( github.com/samber/lo v1.38.1 github.com/stretchr/testify v1.8.4 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/triplewz/poseidon v0.0.0-20220525065023-a7cdb0e183e7 + github.com/triplewz/poseidon v0.0.0-20230828015038-79d8165c88ed github.com/urfave/cli/v2 v2.25.5 github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba github.com/whyrusleeping/cbor-gen v0.0.0-20230923211252-36a87e1ba72f @@ -346,5 +346,3 @@ require ( replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi replace github.com/filecoin-project/test-vectors => ./extern/test-vectors - -replace github.com/triplewz/poseidon => github.com/magik6k/poseidon v0.0.0-neptune diff --git a/go.sum b/go.sum index b0f13f5bb..97abc94c9 100644 --- a/go.sum +++ b/go.sum @@ -1178,8 +1178,6 @@ github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0Q github.com/magefile/mage v1.9.0 h1:t3AU2wNwehMCW97vuqQLtw6puppWXHO+O2MHo5a50XE= github.com/magefile/mage v1.9.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magik6k/poseidon v0.0.0-neptune h1:Dfz15iiYGGE9Esvn8pZFlbiiCrHuyZDxm6LGXQfaf9c= -github.com/magik6k/poseidon v0.0.0-neptune/go.mod h1:QYG1d0B4YZD7TgF6qZndTTu4rxUGFCCZAQRDanDj+9c= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -1608,6 +1606,8 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/triplewz/poseidon v0.0.0-20230828015038-79d8165c88ed h1:C8H2ql+vCBhEi7d3vMBBbdCAKv9s/thfPyLEuSvFpMU= +github.com/triplewz/poseidon v0.0.0-20230828015038-79d8165c88ed/go.mod h1:QYG1d0B4YZD7TgF6qZndTTu4rxUGFCCZAQRDanDj+9c= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg= github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= From 5621c1a193cc1598ad59181a9aaa3a706b671956 Mon Sep 17 00:00:00 2001 From: jennijuju Date: Tue, 9 Jan 2024 19:27:39 +0800 Subject: [PATCH 63/68] update go multi address --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 11a4a5d22..2200716e8 100644 --- a/go.mod +++ b/go.mod @@ -125,7 +125,7 @@ require ( github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mitchellh/go-homedir v1.1.0 github.com/multiformats/go-base32 v0.1.0 - github.com/multiformats/go-multiaddr v0.11.0 + github.com/multiformats/go-multiaddr v0.12.0 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multicodec v0.9.0 diff --git a/go.sum b/go.sum index b0f13f5bb..d69c610b3 100644 --- a/go.sum +++ b/go.sum @@ -1282,8 +1282,8 @@ github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= -github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10= -github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM= +github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE= +github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= From 06f0e6beb8e7b552da646f3d40cec6e767fd3200 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Tue, 9 Jan 2024 10:28:57 -0600 Subject: [PATCH 64/68] fix: docker --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index c3c46f71e..a17b50d09 100644 --- a/Makefile +++ b/Makefile @@ -100,6 +100,8 @@ BINS+=lotus-miner lotus-provider: $(BUILD_DEPS) rm -f lotus-provider $(GOCC) build $(GOFLAGS) -o lotus-provider ./cmd/lotus-provider +.PHONY: lotus-provider +BINS+=lotus-provider lp2k: GOFLAGS+=-tags=2k lp2k: lotus-provider From aeed4cba6bb041c286627d0a58d713c80f94310e Mon Sep 17 00:00:00 2001 From: jennijuju Date: Wed, 10 Jan 2024 21:15:45 +0800 Subject: [PATCH 65/68] update to the latest go multiaddress release --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index b30d87f62..c1b353fab 100644 --- a/go.mod +++ b/go.mod @@ -119,7 +119,7 @@ require ( github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/mitchellh/go-homedir v1.1.0 github.com/multiformats/go-base32 v0.1.0 - github.com/multiformats/go-multiaddr v0.12.0 + github.com/multiformats/go-multiaddr v0.12.1 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multicodec v0.9.0 @@ -154,11 +154,11 @@ require ( go.uber.org/fx v1.20.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.25.0 - golang.org/x/crypto v0.12.0 + golang.org/x/crypto v0.17.0 golang.org/x/net v0.14.0 golang.org/x/sync v0.3.0 - golang.org/x/sys v0.11.0 - golang.org/x/term v0.11.0 + golang.org/x/sys v0.15.0 + golang.org/x/term v0.15.0 golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 @@ -321,7 +321,7 @@ require ( go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/text v0.12.0 // indirect + golang.org/x/text v0.14.0 // indirect gonum.org/v1/gonum v0.13.0 // indirect google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect google.golang.org/grpc v1.55.0 // indirect diff --git a/go.sum b/go.sum index e1958bc8f..a7983d80c 100644 --- a/go.sum +++ b/go.sum @@ -1249,8 +1249,8 @@ github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= -github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE= -github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8= +github.com/multiformats/go-multiaddr v0.12.1 h1:vm+BA/WZA8QZDp1pF1FWhi5CT3g1tbi5GJmqpb6wnlk= +github.com/multiformats/go-multiaddr v0.12.1/go.mod h1:7mPkiBMmLeFipt+nNSq9pHZUeJSt8lHBgH6yhj0YQzE= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= @@ -1779,8 +1779,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -2014,16 +2014,16 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2033,8 +2033,8 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 170b9844efc6d6a2f1fa4c1e6f2fa751a081b594 Mon Sep 17 00:00:00 2001 From: Aayush Date: Mon, 8 Jan 2024 15:42:10 -0500 Subject: [PATCH 66/68] feat: exchange: change GetBlocks to always fetch the requested number of tipsets --- chain/exchange/client.go | 56 +++++++++++++++++++++++++----------- chain/exchange/interfaces.go | 4 +-- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/chain/exchange/client.go b/chain/exchange/client.go index 769c375ca..9cbb44955 100644 --- a/chain/exchange/client.go +++ b/chain/exchange/client.go @@ -284,16 +284,18 @@ func (c *client) validateCompressedIndices(chain []*BSTipSet) error { len(msgs.SecpkIncludes), blocksNum) } + blsLen := uint64(len(msgs.Bls)) + secpLen := uint64(len(msgs.Secpk)) for blockIdx := 0; blockIdx < blocksNum; blockIdx++ { for _, mi := range msgs.BlsIncludes[blockIdx] { - if int(mi) >= len(msgs.Bls) { + if mi >= blsLen { return xerrors.Errorf("index in BlsIncludes (%d) exceeds number of messages (%d)", mi, len(msgs.Bls)) } } for _, mi := range msgs.SecpkIncludes[blockIdx] { - if int(mi) >= len(msgs.Secpk) { + if mi >= secpLen { return xerrors.Errorf("index in SecpkIncludes (%d) exceeds number of messages (%d)", mi, len(msgs.Secpk)) } @@ -315,18 +317,36 @@ func (c *client) GetBlocks(ctx context.Context, tsk types.TipSetKey, count int) ) } - req := &Request{ - Head: tsk.Cids(), - Length: uint64(count), - Options: Headers, + var ret []*types.TipSet + start := tsk.Cids() + for len(ret) < count { + req := &Request{ + Head: start, + Length: uint64(count - len(ret)), + Options: Headers, + } + + validRes, err := c.doRequest(ctx, req, nil, nil) + if err != nil { + return nil, xerrors.Errorf("failed to doRequest: %w", err) + } + + if len(validRes.tipsets) == 0 { + return nil, xerrors.Errorf("doRequest fetched zero tipsets: %w", err) + } + + ret = append(ret, validRes.tipsets...) + + last := validRes.tipsets[len(validRes.tipsets)-1] + if last.Height() <= 1 { + // we've walked all the way up to genesis, return + break + } + + start = last.Parents().Cids() } - validRes, err := c.doRequest(ctx, req, nil, nil) - if err != nil { - return nil, err - } - - return validRes.tipsets, nil + return ret, nil } // GetFullTipSet implements Client.GetFullTipSet(). Refer to the godocs there. @@ -341,12 +361,16 @@ func (c *client) GetFullTipSet(ctx context.Context, peer peer.ID, tsk types.TipS validRes, err := c.doRequest(ctx, req, &peer, nil) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to doRequest: %w", err) } - return validRes.toFullTipSets()[0], nil - // If `doRequest` didn't fail we are guaranteed to have at least - // *one* tipset here, so it's safe to index directly. + fullTipsets := validRes.toFullTipSets() + + if len(fullTipsets) == 0 { + return nil, xerrors.New("unexpectedly got no tipsets in exchange") + } + + return fullTipsets[0], nil } // GetChainMessages implements Client.GetChainMessages(). Refer to the godocs there. diff --git a/chain/exchange/interfaces.go b/chain/exchange/interfaces.go index c95127929..ff11b63eb 100644 --- a/chain/exchange/interfaces.go +++ b/chain/exchange/interfaces.go @@ -28,8 +28,8 @@ type Server interface { // used by the Syncer. type Client interface { // GetBlocks fetches block headers from the network, from the provided - // tipset *backwards*, returning as many tipsets as the count parameter, - // or less. + // tipset *backwards*, returning as many tipsets as the count parameter. + // The ONLY case in which we return fewer than `count` tipsets is if we hit genesis. GetBlocks(ctx context.Context, tsk types.TipSetKey, count int) ([]*types.TipSet, error) // GetChainMessages fetches messages from the network, starting from the first provided tipset From 32559aa463f6e771d1a58aa97922f769c2572027 Mon Sep 17 00:00:00 2001 From: "Andrew Jackson (Ajax)" Date: Sat, 13 Jan 2024 06:47:22 -0600 Subject: [PATCH 67/68] rearrange --- cmd/lotus-provider/rpc/rpc.go | 5 ++--- cmd/lotus-provider/run.go | 15 +++++---------- .../web => provider/lpweb}/api/debug/debug.go | 0 .../web => provider/lpweb}/api/routes.go | 2 +- .../web => provider/lpweb}/hapi/routes.go | 0 .../web => provider/lpweb}/hapi/simpleinfo.go | 2 +- .../lpweb}/hapi/web/actor_summary.gohtml | 0 .../lpweb}/hapi/web/chain_rpcs.gohtml | 0 .../lpweb}/hapi/web/cluster_machines.gohtml | 0 .../lpweb}/hapi/web/cluster_task_history.gohtml | 0 .../lpweb}/hapi/web/cluster_tasks.gohtml | 0 {cmd/lotus-provider/web => provider/lpweb}/srv.go | 8 ++++---- .../lpweb}/static/chain-connectivity.js | 0 .../web => provider/lpweb}/static/index.html | 0 14 files changed, 13 insertions(+), 19 deletions(-) rename {cmd/lotus-provider/web => provider/lpweb}/api/debug/debug.go (100%) rename {cmd/lotus-provider/web => provider/lpweb}/api/routes.go (80%) rename {cmd/lotus-provider/web => provider/lpweb}/hapi/routes.go (100%) rename {cmd/lotus-provider/web => provider/lpweb}/hapi/simpleinfo.go (98%) rename {cmd/lotus-provider/web => provider/lpweb}/hapi/web/actor_summary.gohtml (100%) rename {cmd/lotus-provider/web => provider/lpweb}/hapi/web/chain_rpcs.gohtml (100%) rename {cmd/lotus-provider/web => provider/lpweb}/hapi/web/cluster_machines.gohtml (100%) rename {cmd/lotus-provider/web => provider/lpweb}/hapi/web/cluster_task_history.gohtml (100%) rename {cmd/lotus-provider/web => provider/lpweb}/hapi/web/cluster_tasks.gohtml (100%) rename {cmd/lotus-provider/web => provider/lpweb}/srv.go (90%) rename {cmd/lotus-provider/web => provider/lpweb}/static/chain-connectivity.js (100%) rename {cmd/lotus-provider/web => provider/lpweb}/static/index.html (100%) diff --git a/cmd/lotus-provider/rpc/rpc.go b/cmd/lotus-provider/rpc/rpc.go index d77d8c81e..e2897030f 100644 --- a/cmd/lotus-provider/rpc/rpc.go +++ b/cmd/lotus-provider/rpc/rpc.go @@ -21,10 +21,10 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" - "github.com/filecoin-project/lotus/cmd/lotus-provider/web" "github.com/filecoin-project/lotus/lib/rpcenc" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/metrics/proxy" + "github.com/filecoin-project/lotus/provider/lpweb" "github.com/filecoin-project/lotus/storage/paths" ) @@ -79,7 +79,6 @@ func (p *ProviderAPI) Shutdown(context.Context) error { } func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan chan struct{}) error { - fh := &paths.FetchHandler{Local: dependencies.LocalStore, PfHandler: &paths.DefaultPartialFileHandler{}} remoteHandler := func(w http.ResponseWriter, r *http.Request) { if !auth.HasPerm(r.Context(), nil, api.PermAdmin) { @@ -133,7 +132,7 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c eg.Go(srv.ListenAndServe) if dependencies.Cfg.Subsystems.EnableWebGui { - web, err := web.GetSrv(ctx, dependencies) + web, err := lpweb.GetSrv(ctx, dependencies) if err != nil { return err } diff --git a/cmd/lotus-provider/run.go b/cmd/lotus-provider/run.go index 0f18f2843..b1a4ff828 100644 --- a/cmd/lotus-provider/run.go +++ b/cmd/lotus-provider/run.go @@ -1,14 +1,12 @@ package main import ( - "bytes" "context" "fmt" "os" "strings" "time" - "github.com/BurntSushi/toml" "github.com/pkg/errors" "github.com/urfave/cli/v2" "go.opencensus.io/stats" @@ -22,7 +20,6 @@ import ( "github.com/filecoin-project/lotus/lib/ulimit" "github.com/filecoin-project/lotus/metrics" "github.com/filecoin-project/lotus/node" - "github.com/filecoin-project/lotus/node/config" ) type stackTracer interface { @@ -174,13 +171,11 @@ var webCmd = &cli.Command{ webtxt, err := getConfig(db, "web") if err != nil || webtxt == "" { - cfg := config.DefaultLotusProvider() - cfg.Subsystems.EnableWebGui = true - var b bytes.Buffer - if err = toml.NewEncoder(&b).Encode(cfg); err != nil { - return err - } - if err = setConfig(db, "web", b.String()); err != nil { + + s := `[Susbystems] + EnableWebGui = true + ` + if err = setConfig(db, "web", s); err != nil { return err } } diff --git a/cmd/lotus-provider/web/api/debug/debug.go b/provider/lpweb/api/debug/debug.go similarity index 100% rename from cmd/lotus-provider/web/api/debug/debug.go rename to provider/lpweb/api/debug/debug.go diff --git a/cmd/lotus-provider/web/api/routes.go b/provider/lpweb/api/routes.go similarity index 80% rename from cmd/lotus-provider/web/api/routes.go rename to provider/lpweb/api/routes.go index 9bb6fb67c..85b17486f 100644 --- a/cmd/lotus-provider/web/api/routes.go +++ b/provider/lpweb/api/routes.go @@ -5,7 +5,7 @@ import ( "github.com/gorilla/mux" "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" - "github.com/filecoin-project/lotus/cmd/lotus-provider/web/api/debug" + "github.com/filecoin-project/lotus/provider/lpweb/api/debug" ) func Routes(r *mux.Router, deps *deps.Deps) { diff --git a/cmd/lotus-provider/web/hapi/routes.go b/provider/lpweb/hapi/routes.go similarity index 100% rename from cmd/lotus-provider/web/hapi/routes.go rename to provider/lpweb/hapi/routes.go diff --git a/cmd/lotus-provider/web/hapi/simpleinfo.go b/provider/lpweb/hapi/simpleinfo.go similarity index 98% rename from cmd/lotus-provider/web/hapi/simpleinfo.go rename to provider/lpweb/hapi/simpleinfo.go index a14735a84..ee36a1e17 100644 --- a/cmd/lotus-provider/web/hapi/simpleinfo.go +++ b/provider/lpweb/hapi/simpleinfo.go @@ -82,7 +82,7 @@ var templateDev = os.Getenv("LOTUS_WEB_DEV") == "1" func (a *app) executeTemplate(w http.ResponseWriter, name string, data interface{}) { if templateDev { fs := os.DirFS("./cmd/lotus-provider/web/hapi/web") - a.t = template.Must(template.ParseFS(fs, "web/*")) + a.t = template.Must(template.ParseFS(fs, "*")) } if err := a.t.ExecuteTemplate(w, name, data); err != nil { log.Errorf("execute template %s: %v", name, err) diff --git a/cmd/lotus-provider/web/hapi/web/actor_summary.gohtml b/provider/lpweb/hapi/web/actor_summary.gohtml similarity index 100% rename from cmd/lotus-provider/web/hapi/web/actor_summary.gohtml rename to provider/lpweb/hapi/web/actor_summary.gohtml diff --git a/cmd/lotus-provider/web/hapi/web/chain_rpcs.gohtml b/provider/lpweb/hapi/web/chain_rpcs.gohtml similarity index 100% rename from cmd/lotus-provider/web/hapi/web/chain_rpcs.gohtml rename to provider/lpweb/hapi/web/chain_rpcs.gohtml diff --git a/cmd/lotus-provider/web/hapi/web/cluster_machines.gohtml b/provider/lpweb/hapi/web/cluster_machines.gohtml similarity index 100% rename from cmd/lotus-provider/web/hapi/web/cluster_machines.gohtml rename to provider/lpweb/hapi/web/cluster_machines.gohtml diff --git a/cmd/lotus-provider/web/hapi/web/cluster_task_history.gohtml b/provider/lpweb/hapi/web/cluster_task_history.gohtml similarity index 100% rename from cmd/lotus-provider/web/hapi/web/cluster_task_history.gohtml rename to provider/lpweb/hapi/web/cluster_task_history.gohtml diff --git a/cmd/lotus-provider/web/hapi/web/cluster_tasks.gohtml b/provider/lpweb/hapi/web/cluster_tasks.gohtml similarity index 100% rename from cmd/lotus-provider/web/hapi/web/cluster_tasks.gohtml rename to provider/lpweb/hapi/web/cluster_tasks.gohtml diff --git a/cmd/lotus-provider/web/srv.go b/provider/lpweb/srv.go similarity index 90% rename from cmd/lotus-provider/web/srv.go rename to provider/lpweb/srv.go index 55d20cc9a..f6bcfcf85 100644 --- a/cmd/lotus-provider/web/srv.go +++ b/provider/lpweb/srv.go @@ -1,5 +1,5 @@ -// Package web defines the HTTP web server for static files and endpoints. -package web +// Package lpweb defines the HTTP web server for static files and endpoints. +package lpweb import ( "context" @@ -17,9 +17,9 @@ import ( "go.opencensus.io/tag" "github.com/filecoin-project/lotus/cmd/lotus-provider/deps" - "github.com/filecoin-project/lotus/cmd/lotus-provider/web/api" - "github.com/filecoin-project/lotus/cmd/lotus-provider/web/hapi" "github.com/filecoin-project/lotus/metrics" + "github.com/filecoin-project/lotus/provider/lpweb/api" + "github.com/filecoin-project/lotus/provider/lpweb/hapi" ) //go:embed static diff --git a/cmd/lotus-provider/web/static/chain-connectivity.js b/provider/lpweb/static/chain-connectivity.js similarity index 100% rename from cmd/lotus-provider/web/static/chain-connectivity.js rename to provider/lpweb/static/chain-connectivity.js diff --git a/cmd/lotus-provider/web/static/index.html b/provider/lpweb/static/index.html similarity index 100% rename from cmd/lotus-provider/web/static/index.html rename to provider/lpweb/static/index.html From 73d830e2fb89c4b0f077771b465cf959dfd2d105 Mon Sep 17 00:00:00 2001 From: Phi Date: Wed, 17 Jan 2024 13:27:09 +0100 Subject: [PATCH 68/68] Remove merge conflict artefact Remove merge conflict artefact --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5da284702..9cf98e889 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -196,8 +196,6 @@ This patch release allows for up to 10k messages per block. Additionally, it int ## Improvements - fix: exchange: allow up to 10k messages per block ([filecoin-project/lotus#11506](https://github.com/filecoin-project/lotus/pull/11506)) ->>>>>>> releases - # v 1.25.0 / 2023-11-22 This is a highly recommended feature release of Lotus. This optional release supports the Filecoin network version 21 upgrade, codenamed Watermelon 🍉, in addition to the numerous improvements and enhancements for node operators, ETH RPC-providers and storage providers.